Thread: loading jdbc Driver in servlet

loading jdbc Driver in servlet

From
Rob Sargent
Date:

Using java 1.8, postgresql-42.1.4.jar, embedded tomcat 9

It appears to me that I need to make the call "Class.forName("org.postgresql.Driver)" when the entry is in a servlet.  Is this expected, within a servlet, or is this just post hoc ergo propter hoc at it finest and I changed something else (wittingly or not).  Same code outside of servlet does not need the forced loading of the class and the manual claims it's not need after java 1.6

Re: loading jdbc Driver in servlet

From
Dave Cramer
Date:
Strange, I wouldn't think so, but then I haven't used a raw servlet for so long I have no idea.


On Fri, 14 Dec 2018 at 13:29, Rob Sargent <robjsargent@gmail.com> wrote:

Using java 1.8, postgresql-42.1.4.jar, embedded tomcat 9

It appears to me that I need to make the call "Class.forName("org.postgresql.Driver)" when the entry is in a servlet.  Is this expected, within a servlet, or is this just post hoc ergo propter hoc at it finest and I changed something else (wittingly or not).  Same code outside of servlet does not need the forced loading of the class and the manual claims it's not need after java 1.6

Re: loading jdbc Driver in servlet

From
Rob Sargent
Date:


On Dec 14, 2018, at 1:30 PM, Dave Cramer <pg@fastcrypt.com> wrote:

Strange, I wouldn't think so, but then I haven't used a raw servlet for so long I have no idea.


On Fri, 14 Dec 2018 at 13:29, Rob Sargent <robjsargent@gmail.com> wrote:

Using java 1.8, postgresql-42.1.4.jar, embedded tomcat 9

It appears to me that I need to make the call "Class.forName("org.postgresql.Driver)" when the entry is in a servlet.  Is this expected, within a servlet, or is this just post hoc ergo propter hoc at it finest and I changed something else (wittingly or not).  Same code outside of servlet does not need the forced loading of the class and the manual claims it's not need after java 1.6

I too am suspicious.  But the vagaries of javax are daunting.
But if I comment it out, as just now, “No suitable driver found...”.  I was days playing with configuration and such think that this very specific error message was telling me my CLASSPATH was wrong.

I wonder if I have an old javax installation (which I put in place just recently).




Re: loading jdbc Driver in servlet

From
Rob Sargent
Date:


On Dec 14, 2018, at 2:02 PM, Rob Sargent <robjsargent@gmail.com> wrote:



On Dec 14, 2018, at 1:30 PM, Dave Cramer <pg@fastcrypt.com> wrote:

Strange, I wouldn't think so, but then I haven't used a raw servlet for so long I have no idea.


On Fri, 14 Dec 2018 at 13:29, Rob Sargent <robjsargent@gmail.com> wrote:

Using java 1.8, postgresql-42.1.4.jar, embedded tomcat 9

It appears to me that I need to make the call "Class.forName("org.postgresql.Driver)" when the entry is in a servlet.  Is this expected, within a servlet, or is this just post hoc ergo propter hoc at it finest and I changed something else (wittingly or not).  Same code outside of servlet does not need the forced loading of the class and the manual claims it's not need after java 1.6

I too am suspicious.  But the vagaries of javax are daunting.
But if I comment it out, as just now, “No suitable driver found...”.  I was days playing with configuration and such think that this very specific error message was telling me my CLASSPATH was wrong.

I wonder if I have an old javax installation (which I put in place just recently).


I’m using javax.servlet-api-3.1.0.jar



Re: loading jdbc Driver in servlet

From
Dave Cramer
Date:
My guess is it has something to do with your servlet classpath loader. Which servlet engine are you using ?


On Fri, 14 Dec 2018 at 16:04, Rob Sargent <robjsargent@gmail.com> wrote:


On Dec 14, 2018, at 2:02 PM, Rob Sargent <robjsargent@gmail.com> wrote:



On Dec 14, 2018, at 1:30 PM, Dave Cramer <pg@fastcrypt.com> wrote:

Strange, I wouldn't think so, but then I haven't used a raw servlet for so long I have no idea.


On Fri, 14 Dec 2018 at 13:29, Rob Sargent <robjsargent@gmail.com> wrote:

Using java 1.8, postgresql-42.1.4.jar, embedded tomcat 9

It appears to me that I need to make the call "Class.forName("org.postgresql.Driver)" when the entry is in a servlet.  Is this expected, within a servlet, or is this just post hoc ergo propter hoc at it finest and I changed something else (wittingly or not).  Same code outside of servlet does not need the forced loading of the class and the manual claims it's not need after java 1.6

I too am suspicious.  But the vagaries of javax are daunting.
But if I comment it out, as just now, “No suitable driver found...”.  I was days playing with configuration and such think that this very specific error message was telling me my CLASSPATH was wrong.

I wonder if I have an old javax installation (which I put in place just recently).


I’m using javax.servlet-api-3.1.0.jar



Re: loading jdbc Driver in servlet

From
Rob Sargent
Date:
Tomcat version 9. Embedded in my main()

On Dec 16, 2018, at 9:30 AM, Dave Cramer <pg@fastcrypt.com> wrote:

My guess is it has something to do with your servlet classpath loader. Which servlet engine are you using ?


On Fri, 14 Dec 2018 at 16:04, Rob Sargent <robjsargent@gmail.com> wrote:


On Dec 14, 2018, at 2:02 PM, Rob Sargent <robjsargent@gmail.com> wrote:



On Dec 14, 2018, at 1:30 PM, Dave Cramer <pg@fastcrypt.com> wrote:

Strange, I wouldn't think so, but then I haven't used a raw servlet for so long I have no idea.


On Fri, 14 Dec 2018 at 13:29, Rob Sargent <robjsargent@gmail.com> wrote:

Using java 1.8, postgresql-42.1.4.jar, embedded tomcat 9

It appears to me that I need to make the call "Class.forName("org.postgresql.Driver)" when the entry is in a servlet.  Is this expected, within a servlet, or is this just post hoc ergo propter hoc at it finest and I changed something else (wittingly or not).  Same code outside of servlet does not need the forced loading of the class and the manual claims it's not need after java 1.6

I too am suspicious.  But the vagaries of javax are daunting.
But if I comment it out, as just now, “No suitable driver found...”.  I was days playing with configuration and such think that this very specific error message was telling me my CLASSPATH was wrong.

I wonder if I have an old javax installation (which I put in place just recently).


I’m using javax.servlet-api-3.1.0.jar



Re: loading jdbc Driver in servlet

From
Dave Cramer
Date:
So you are starting up tomcat yourself ? Perhaps that is the difference ?
I have no idea what the tomcat wrapper does, but I'd be curious if the same thing happens when stared normally

On Sun, 16 Dec 2018 at 12:20, Rob Sargent <robjsargent@gmail.com> wrote:
Tomcat version 9. Embedded in my main()

On Dec 16, 2018, at 9:30 AM, Dave Cramer <pg@fastcrypt.com> wrote:

My guess is it has something to do with your servlet classpath loader. Which servlet engine are you using ?


On Fri, 14 Dec 2018 at 16:04, Rob Sargent <robjsargent@gmail.com> wrote:


On Dec 14, 2018, at 2:02 PM, Rob Sargent <robjsargent@gmail.com> wrote:



On Dec 14, 2018, at 1:30 PM, Dave Cramer <pg@fastcrypt.com> wrote:

Strange, I wouldn't think so, but then I haven't used a raw servlet for so long I have no idea.


On Fri, 14 Dec 2018 at 13:29, Rob Sargent <robjsargent@gmail.com> wrote:

Using java 1.8, postgresql-42.1.4.jar, embedded tomcat 9

It appears to me that I need to make the call "Class.forName("org.postgresql.Driver)" when the entry is in a servlet.  Is this expected, within a servlet, or is this just post hoc ergo propter hoc at it finest and I changed something else (wittingly or not).  Same code outside of servlet does not need the forced loading of the class and the manual claims it's not need after java 1.6

I too am suspicious.  But the vagaries of javax are daunting.
But if I comment it out, as just now, “No suitable driver found...”.  I was days playing with configuration and such think that this very specific error message was telling me my CLASSPATH was wrong.

I wonder if I have an old javax installation (which I put in place just recently).


I’m using javax.servlet-api-3.1.0.jar



Re: loading jdbc Driver in servlet

From
Rob Sargent
Date:

> On Dec 16, 2018, at 12:12 PM, Dave Cramer <pg@fastcrypt.com> wrote:
>
> So you are starting up tomcat yourself ? Perhaps that is the difference ?
> I have no idea what the tomcat wrapper does, but I'd be curious if the same thing happens when stared normally
>
> Dave Cramer
>
Whatever the is the difference, it undoes changes in the language since java 1.6??!!





Re: loading jdbc Driver in servlet

From
Rob Sargent
Date:


On Dec 16, 2018, at 5:55 PM, Martin Gainty <mgainty@hotmail.com> wrote:

99% of the problems with 'isolated classloader' are solved using the class e.g.

Granted. But this seems to fly in the face of both Postgres docs and modern JDKs. 

Re: loading jdbc Driver in servlet

From
Thomas Kellerer
Date:
Rob Sargent schrieb am 14.12.2018 um 19:28:
> Using java 1.8, postgresql-42.1.4.jar, embedded tomcat 9
> 
> It appears to me that I need to make the call
> "Class.forName("org.postgresql.Driver)" when the entry is in a
> servlet.  Is this expected, within a servlet, or is this just /post
> hoc ergo propter hoc /at it finest and I changed something else
> (wittingly or not).  Same code outside of servlet does not need the
> forced loading of the class and the manual claims it's not need after
> java 1.6

Class.forName() is definitely not needed if the driver's JAR file is 
included in the classloader of the class requesting a connection. 

Where exactly did you put the JDBC driver's jar file? 
And what exactly is your main() method doing?

If you look at Tomcat's startup script (catalina.sh or catalina.bat), it's
obvious that setting up the claspath isn't that straightforward. 
My guess is, that that your main() method does something different 
and does not properly include the driver's jar in the classpath. 

Thomas



Re: loading jdbc Driver in servlet

From
Dave Cramer
Date:


On Mon, 17 Dec 2018 at 02:28, Thomas Kellerer <spam_eater@gmx.net> wrote:
Rob Sargent schrieb am 14.12.2018 um 19:28:
> Using java 1.8, postgresql-42.1.4.jar, embedded tomcat 9
>
> It appears to me that I need to make the call
> "Class.forName("org.postgresql.Driver)" when the entry is in a
> servlet.  Is this expected, within a servlet, or is this just /post
> hoc ergo propter hoc /at it finest and I changed something else
> (wittingly or not).  Same code outside of servlet does not need the
> forced loading of the class and the manual claims it's not need after
> java 1.6

Class.forName() is definitely not needed if the driver's JAR file is
included in the classloader of the class requesting a connection.

Where exactly did you put the JDBC driver's jar file?
And what exactly is your main() method doing?

If you look at Tomcat's startup script (catalina.sh or catalina.bat), it's
obvious that setting up the claspath isn't that straightforward.
My guess is, that that your main() method does something different
and does not properly include the driver's jar in the classpath.


Servlet classpath issues are legendary. As Thomas points out setting up the classpath for a servlet engine is not trivial.





Re: loading jdbc Driver in servlet

From
Rob Sargent
Date:


On 12/17/18 4:26 AM, Dave Cramer wrote:


On Mon, 17 Dec 2018 at 02:28, Thomas Kellerer <spam_eater@gmx.net> wrote:
Rob Sargent schrieb am 14.12.2018 um 19:28:
> Using java 1.8, postgresql-42.1.4.jar, embedded tomcat 9
>
> It appears to me that I need to make the call
> "Class.forName("org.postgresql.Driver)" when the entry is in a
> servlet.  Is this expected, within a servlet, or is this just /post
> hoc ergo propter hoc /at it finest and I changed something else
> (wittingly or not).  Same code outside of servlet does not need the
> forced loading of the class and the manual claims it's not need after
> java 1.6

Class.forName() is definitely not needed if the driver's JAR file is
included in the classloader of the class requesting a connection.

Where exactly did you put the JDBC driver's jar file?
And what exactly is your main() method doing?

If you look at Tomcat's startup script (catalina.sh or catalina.bat), it's
obvious that setting up the claspath isn't that straightforward.
My guess is, that that your main() method does something different
and does not properly include the driver's jar in the classpath.


Servlet classpath issues are legendary. As Thomas points out setting up the classpath for a servlet engine is not trivial.


As I've manage to get down the road using "forName()" this becomes largely academic.

The classpath of the main does have postgres.

Using this

    System.out.println("main classpath: \n" + getClasspathString());

    private String getClasspathString() {
        StringBuffer classpath = new StringBuffer();
        ClassLoader applicationClassLoader = this.getClass().getClassLoader();
        if (applicationClassLoader == null) {
            applicationClassLoader = ClassLoader.getSystemClassLoader();
        }
        java.net.URL[] urls = ((java.net.URLClassLoader)applicationClassLoader).getURLs();
        for(int i=0; i < urls.length; i++) {
            classpath.append(urls[i].getFile()).append("\n");
        }   
        return classpath.toString();
    }

I get:

main classpath:
/home/u0138544/gits/java/gitlab/gtdb/tport/build/libs/tport.jar
/home/u0138544/gits/java/gitlab/gtdb/tools/build/libs/tools.jar
/home/u0138544/gits/java/gitlab/gtdb/sgs/build/libs/sgs.jar
/home/u0138544/.m2/repository/org/slf4j/slf4j-api/1.7.7/slf4j-api-1.7.7.jar
/home/u0138544/.gradle/caches/modules-2/files-2.1/org.postgresql/postgresql/42.1.4/1c7788d16b67d51f2f38ae99e474ece968bf715a/postgresql-42.1.4.jar
/home/u0138544/.gradle/caches/modules-2/files-2.1/net.sf.jopt-simple/jopt-simple/4.9/ee9e9eaa0a35360dcfeac129ff4923215fd65904/jopt-simple-4.9.jar
/home/u0138544/.gradle/caches/modules-2/files-2.1/javax.servlet/javax.servlet-api/3.1.0/3cd63d075497751784b2fa84be59432f4905bf7c/javax.servlet-api-3.1.0.jar
/home/u0138544/.gradle/caches/modules-2/files-2.1/javax.servlet/javax.servlet-api/3.1.0/3cd63d075497751784b2fa84be59432f4905bf7c/javax.servlet-api-3.1.0.jar
/home/u0138544/.gradle/caches/modules-2/files-2.1/javax.xml.bind/jaxb-api/2.2.12/4c83805595b15acf41d71d49e3add7c0e85baaed/jaxb-api-2.2.12.jar
/home/u0138544/.gradle/caches/modules-2/files-2.1/org.apache.tomcat.embed/tomcat-embed-core/9.0.12/136c8dc5c84e82bf2d68bb10648d4fa8b402184/tomcat-embed-core-9.0.12.jar
/home/u0138544/.gradle/caches/modules-2/files-2.1/org.apache.tomcat.embed/tomcat-embed-el/9.0.12/8ee44bee76043321860cde871cf6343de1483ff5/tomcat-embed-el-9.0.12.jar
/home/u0138544/.gradle/caches/modules-2/files-2.1/org.apache.tomcat.embed/tomcat-embed-jasper/9.0.12/f81c352450b9695b73b90b3e5ef78d6f7fcb1a96/tomcat-embed-jasper-9.0.12.jar
/home/u0138544/.gradle/caches/modules-2/files-2.1/org.apache.tomcat.embed/tomcat-embed-logging-juli/9.0.0.M6/2b083aa89d92ce10356158da1e643f8a8e890b49/tomcat-embed-logging-juli-9.0.0.M6.jar
/home/u0138544/.gradle/caches/modules-2/files-2.1/org.apache.tomcat/tomcat-annotations-api/9.0.12/dfda698ec20b257a6801a2df25c76554658f6005/tomcat-annotations-api-9.0.12.jar
/home/u0138544/work/test/gtdb/

That is generated inside the run() method, as my main() is a Runnable (perhaps unnecessarily so, I'm in the midst of a migration from handling sockets myself to letting Tomcat do that work.  I'm embedding Tomcat to make the footprint just a little more streamlined (or maybe obfuscated).

Inside the servlet the classpath is:

Servlet classpath: file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/classes/
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/groovy-all-2.4.7.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/jaxb-api-2.2.12.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/tomcat-embed-logging-juli-9.0.0.M6.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/jpsgcs-3.1.1-2.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/jackson-annotations-2.9.8.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/tools.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/logback-classic-1.1.2.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/logback-access-1.1.2.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/jackson-core-2.9.8.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/jooq-3.11.7.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/logback-core-1.1.2.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/jooq-codegen-3.11.7.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/tomcat-embed-core-9.0.12.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/jackson-databind-2.9.8.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/tomcat-annotations-api-9.0.12.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/postgresql-42.1.4.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/jooq.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/sgs.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/jopt-simple-4.9.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/longpowerset-1.0.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/slf4j-api-1.7.7.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/anno.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/javax.servlet-api-3.1.0.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/tport.jar
file:/home/u0138544/work/test/crashpad/monitor/webapp.war*/WEB-INF/lib/jooq-meta-3.11.7.jar


Happy to let this be part of the servlet classpath legend!