0

I'm trying to get JDO working within a Servlet; just a simple, basic Servlet. I know that a Servlet can connect to my db because a non-JDO servlet does it fine, and prints out data from the db (the following is at the start of a simple Servlet):

 StringBuilder sb = new StringBuilder();
 Connection conn = null;
 try {
         String userName = "jdo";
         String password = "jdo";
         String url = "jdbc:mysql://192.168.2.203:3306/jdo";
         Class.forName( "com.mysql.jdbc.Driver" ).newInstance();
         conn = DriverManager.getConnection( url, userName, password );
         sb.append( "Database connection established" );

         Statement s = conn.createStatement();
         s.executeQuery( "select id, make, model from car limit 1" );
         ResultSet rs = s.getResultSet();
         while ( rs.next() ) {
                 int id = rs.getInt( "id" );
                 String make = rs.getString( "make" );
                 String model = rs.getString( "model" );
                 sb.append( "id = " + id + ", make = " + make + ", model = " + model + "\n" );
         }
         rs.close();
         s.close();

 }

That's all fine, the StringBuilder gets the data from the db appended no problem. What doesn't work, however, is the following. It throws a stack trace at the last line (line 28) I'm about to paste in here (this code is also at the start of a simple Servlet, just a different Servlet to the one that contained the previous code):

 Properties p = new Properties();
 p.setProperty( "javax.jdo.option.ConnectionDriverName", "com.mysql.jdbc.Driver" );
 p.setProperty( "javax.jdo.option.ConnectionURL", "jdbc:mysql://192.168.2.203:3306/jdo" );
 p.setProperty( "javax.jdo.option.ConnectionUserName", "jdo" );
 p.setProperty( "javax.jdo.option.ConnectionPassword", "jdo" );
 PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory( p );  // this is line 28

The stack trace is at the bottom of this post, as it's rather long.

These two Servlets exist in the same war file, within which is the MySQL Connector/J jar file:

mkns@squeeze:~/workspace/JdoServlet$ jar tf dist/jdoservlet.war  | grep mysql
WEB-INF/lib/mysql-connector-java-5.1.6.jar

I'm baffled as to why the DataNucleus libs are not finding the MySQL Connector/J driver jar file? I may be missing the obvious here, but I've stripped my Servlets back as much as I can to see where the problem is (as above) and I can't figure out where I'm going wrong. Can anyone point out the mistake I'm making?

I'm using the latest version of DataNucleus, 3.0.9.

--- 8< ---

And now the stack trace; this is the full stack trace taken from the Tomcat6 catalina log file. Note that the lines from my app are in the masked out package name of com.xxxxxxxxxx.jdoservlet.*, so if you look for that, you can identify where the exception was thrown by my app.

12-Apr-2012 18:48:47 org.datanucleus.store.rdbms.RDBMSStoreManager <init>
SEVERE: Failed initialising database.
No suitable driver found for jdbc:mysql://192.168.2.203:3306/jdo
org.datanucleus.exceptions.NucleusDataStoreException: No suitable driver found for jdbc:mysql://192.168.2.203:3306/jdo
        at org.datanucleus.store.rdbms.ConnectionFactoryImpl$ManagedConnectionImpl.getConnection(ConnectionFactoryImpl.java:459)
        at org.datanucleus.store.rdbms.RDBMSStoreManager.<init>(RDBMSStoreManager.java:264)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at org.datanucleus.plugin.NonManagedPluginRegistry.createExecutableExtension(NonManagedPluginRegistry.java:681)
        at org.datanucleus.plugin.PluginManager.createExecutableExtension(PluginManager.java:290)
        at org.datanucleus.NucleusContext.createStoreManagerForProperties(NucleusContext.java:468)
        at org.datanucleus.NucleusContext.initialise(NucleusContext.java:280)
        at org.datanucleus.api.jdo.JDOPersistenceManagerFactory.freezeConfiguration(JDOPersistenceManagerFactory.java:591)
        at org.datanucleus.api.jdo.JDOPersistenceManagerFactory.createPersistenceManagerFactory(JDOPersistenceManagerFactory.java:326)
        at org.datanucleus.api.jdo.JDOPersistenceManagerFactory.getPersistenceManagerFactory(JDOPersistenceManagerFactory.java:195)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at javax.jdo.JDOHelper$16.run(JDOHelper.java:1956)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.jdo.JDOHelper.invoke(JDOHelper.java:1951)
        at javax.jdo.JDOHelper.invokeGetPersistenceManagerFactoryOnImplementation(JDOHelper.java:1159)
        at javax.jdo.JDOHelper.getPersistenceManagerFactory(JDOHelper.java:839)
        at javax.jdo.JDOHelper.getPersistenceManagerFactory(JDOHelper.java:698)
        at com.xxxxxxxxxx.jdoservlet.Test.process(Test.java:28)
        at com.xxxxxxxxxx.jdoservlet.AbstractServlet.doPost(AbstractServlet.java:35)
        at com.xxxxxxxxxx.jdoservlet.AbstractServlet.doGet(AbstractServlet.java:27)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
        at java.lang.Thread.run(Thread.java:662)
Caused by: java.sql.SQLException: No suitable driver found for jdbc:mysql://192.168.2.203:3306/jdo
        at java.sql.DriverManager.getConnection(DriverManager.java:602)
        at java.sql.DriverManager.getConnection(DriverManager.java:154)
        at org.apache.commons.dbcp.DriverManagerConnectionFactory.createConnection(DriverManagerConnectionFactory.java:78)
        at org.apache.commons.dbcp.PoolableConnectionFactory.makeObject(PoolableConnectionFactory.java:582)
        at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1148)
        at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106)
        at org.datanucleus.store.rdbms.ConnectionFactoryImpl$ManagedConnectionImpl.getConnection(ConnectionFactoryImpl.java:444)
        ... 39 more
Nested Throwables StackTrace:
java.sql.SQLException: No suitable driver found for jdbc:mysql://192.168.2.203:3306/jdo
        at java.sql.DriverManager.getConnection(DriverManager.java:602)
        at java.sql.DriverManager.getConnection(DriverManager.java:154)
        at org.apache.commons.dbcp.DriverManagerConnectionFactory.createConnection(DriverManagerConnectionFactory.java:78)
        at org.apache.commons.dbcp.PoolableConnectionFactory.makeObject(PoolableConnectionFactory.java:582)
        at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1148)
        at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106)
        at org.datanucleus.store.rdbms.ConnectionFactoryImpl$ManagedConnectionImpl.getConnection(ConnectionFactoryImpl.java:444)
        at org.datanucleus.store.rdbms.RDBMSStoreManager.<init>(RDBMSStoreManager.java:264)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at org.datanucleus.plugin.NonManagedPluginRegistry.createExecutableExtension(NonManagedPluginRegistry.java:681)
        at org.datanucleus.plugin.PluginManager.createExecutableExtension(PluginManager.java:290)
        at org.datanucleus.NucleusContext.createStoreManagerForProperties(NucleusContext.java:468)
        at org.datanucleus.NucleusContext.initialise(NucleusContext.java:280)
        at org.datanucleus.api.jdo.JDOPersistenceManagerFactory.freezeConfiguration(JDOPersistenceManagerFactory.java:591)
        at org.datanucleus.api.jdo.JDOPersistenceManagerFactory.createPersistenceManagerFactory(JDOPersistenceManagerFactory.java:326)
        at org.datanucleus.api.jdo.JDOPersistenceManagerFactory.getPersistenceManagerFactory(JDOPersistenceManagerFactory.java:195)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at javax.jdo.JDOHelper$16.run(JDOHelper.java:1956)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.jdo.JDOHelper.invoke(JDOHelper.java:1951)
        at javax.jdo.JDOHelper.invokeGetPersistenceManagerFactoryOnImplementation(JDOHelper.java:1159)
        at javax.jdo.JDOHelper.getPersistenceManagerFactory(JDOHelper.java:839)
        at javax.jdo.JDOHelper.getPersistenceManagerFactory(JDOHelper.java:698)
        at com.xxxxxxxxxx.jdoservlet.Test.process(Test.java:28)
        at com.xxxxxxxxxx.jdoservlet.AbstractServlet.doPost(AbstractServlet.java:35)
        at com.xxxxxxxxxx.jdoservlet.AbstractServlet.doGet(AbstractServlet.java:27)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
        at java.lang.Thread.run(Thread.java:662)
Kenny
  • 1,090
  • 7
  • 9
  • Obviously SQLException is *not* thrown from JDOHelper, it is thrown from JDBC classes. Print the stack trace of that – DataNucleus Apr 12 '12 at 15:10
  • Sure, that's done for you. This is the stack trace thrown to the tomcat6 catalina log file, let me know if that's not what you were wanting to see. – Kenny Apr 12 '12 at 17:59

2 Answers2

2

I had the exact same error except it was for the postgres jdbc driver on tomcat7 on a machine running ubuntu 12.04. I ended up taking the jdbc driver out of the war file and put it into /usr/share/tomcat7/lib/. This is a folder that tomcat looks for jar files.

This solution may not be for everyone as the jdbc driver will now be accessible to all servlets in all tomcat containers.

nacious
  • 41
  • 6
1

First thing: You typically omit the call to newInstance after the Class.forName call to load the database driver.

Second: DataNucleus prefers sometimes its own configuration. Have you tried to set the following properties according to the DataNucleus website?

datanucleus.ConnectionDriverName=com.mysql.jdbc.Driver datanucleus.ConnectionURL=jdbc:mysql://'host':'port'/'db-name' datanucleus.ConnectionUserName='user-name'
datanucleus.ConnectionPassword='password'

http://www.datanucleus.org/products/datanucleus/rdbms/support.html

Furthermore check that the driver was successfully deployed.

Does putting the jar in the directory specified in this question help?

Community
  • 1
  • 1
f4lco
  • 3,728
  • 5
  • 28
  • 53
  • First thing - that was one of my attempts to get it working, I just forgot to remove it; its redundant. Second thing - the configuration settings work fine in a CLI app, and they appear to be read since it knows to try to pick up the MySQL driver. As for the driver being deployed, I believe I demonstrated that in my OP? Do you disagree and think I need to do more to prove it has been deployed in the war file? – Kenny Apr 12 '12 at 20:04
  • WAR is just an archive. Maybe Tomcat doesn't unpack it the right way? Try to redeploy. Furthermore what's your development environment? Eclipse? – f4lco Apr 12 '12 at 22:04
  • Tomcat unpacks it without problem, as I can see the contents of the unpacked war in the webapps/ dir. I am using Eclipse, yes, but the code is compiled, enhanced and built into the war file using Ant, not Eclipse. I see you edited your answer to ask whether putting the MySQL Connector/J in Tomcat's lib/ directory helps... well, it "helps" in that it makes it work, but I'd prefer to have the MySQL Connector/J jar inside the war file of the webapp, if possible. Maybe it's not possible for it to work like that? – Kenny Apr 12 '12 at 22:30
  • It's definitely possible, but I run out of ideas what could be wrong. – f4lco Apr 13 '12 at 08:41
  • So you have successfully had this scenario working, with the MySQL Connector/J jar in the war file rather than in Tomcat's lib/ directory? – Kenny Apr 13 '12 at 09:36
  • I just tried it out - working. I copied the required JARs of the DataNucleus Access platform, all of its dependencies and the MySQL connector over to /WEB-INF/lib, created a standard servlet, copied your code and edited the properties to fit my MySQL installation and voila, no exceptions (it doesn't matter if Eclipse deployed onto Tomcat 6 or via export -> WAR and deploying with Tomcat's web UI). – f4lco Apr 13 '12 at 14:16
  • But most importantly - you removed the MySQL Connector/J jar from your tomcat6's lib/ directory, right? Because if you didn't, it will be using that one. And if you did, I'm utterly baffled. – Kenny Apr 13 '12 at 18:22
  • A Connector has never been in tomcat's lib since it was extracted from the download archive just before. – f4lco Apr 13 '12 at 20:50
  • So I downloaded a fresh version of tomcat, 6.0.35, and ran the webapp within that. And guess what - it worked, no problem. Just to make sure I wasn't going completely mad, I went back to my original tomcat installation (the standard tomcat install on Debian Squeeze), and it still doesn't work, with _the exact same war file_. So I can only assume that something weird is going on with the Debian packaged version of Tomcat; or that I have somehow broken it in some bizarre and weird way. – Kenny Apr 15 '12 at 11:34