Link to home
Start Free TrialLog in
Avatar of HycelTaylor
HycelTaylor

asked on

Having trouble implementing a commons-DBCP JOCL configuration file as a resource

I'm trying to get my JOCL file to load as a resource using the command, conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:/maxdb");.

I get the following exception:

java.sql.SQLException: No pool found for jdbc:apache:commons:dbcp:/maxdb.
     at org.apache.commons.dbcp.PoolingDriver.connect(PoolingDriver.java:144)
     at java.sql.DriverManager.getConnection(DriverManager.java:512)
     at java.sql.DriverManager.getConnection(DriverManager.java:193)
     at com.tss.testadmin.service.JOCLPoolingExample.main(JOCLPoolingExample.java:23)

Allow me to elaborate:

I've created a JOCL file and placed it in my classes subdirectory under, C:\apps\classes\com\tss\testadmin\resources.  The file, maxdb.jocl, is the following:

<object class="org.apache.commons.dbcp.PoolableConnectionFactory" xmlns="http://apache.org/xml/xmlns/jakarta/commons/jocl">
   <!-- the first argument is the ConnectionFactory -->
   <object class="org.apache.commons.dbcp.DriverManagerConnectionFactory">
      <string value="com.sap.dbtech.jdbc.DriverSapDB/jdbc:sapdb:///ADMIN"/>
      <object class="java.util.Properties" null="true"/>
   </object>
   <!-- the next argument is the ObjectPool -->
   <object class="org.apache.commons.pool.impl.GenericObjectPool">
      <object class="org.apache.commons.pool.PoolableObjectFactory" null="true"/>
      <int value="10"/> <!-- max active -->
      <byte value="1"/> <!-- when exhausted action, 0 = fail, 1 = block, 2 = grow -->
      <long value="2000"/> <!-- max wait -->
      <int value="10"/> <!-- max idle -->
      <boolean value="false"/> <!-- test on borrow -->
      <boolean value="false"/> <!-- test on return -->
      <long value="10000"/> <!-- time between eviction runs -->
      <int value="5"/> <!-- number of connections to test per eviction run -->
      <long value="5000"/> <!-- min evictable idle time -->
      <boolean value="true"/> <!-- test while idle -->
   </object>
   <!-- the next argument is the KeyedObjectPoolFactory -->
   <object class="org.apache.commons.pool.StackKeyedObjectPoolFactory">
      <int value="5"/> <!-- max idle -->
   </object>
   <string value="SELECT COUNT(*) FROM DUAL"/> <!-- validation query -->
   <boolean value="false"/> <!-- default read only -->
   <boolean value="true"/> <!-- default auto commit -->
</object>

I'm using the following source code in order to test my JOCL file:

package com.tss.testadmin.service;

import java.sql.*;

public class JOCLPoolingExample {

  public static void main(String[] args) {
    Connection conn = null;
    Statement stmt = null;
    ResultSet rset = null;

    try {
      System.out.println("Load the maxdb driver and the pooling driver.");
      Class.forName("com.sap.dbtech.jdbc.DriverSapDB");
      Class.forName("org.apache.commons.dbcp.PoolingDriver");

      System.out.println("Creating connection.");
      conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:/maxdb");
      System.out.println("Creating statement.");
      stmt = conn.createStatement();
      System.out.println("Executing statement.");
      rset = stmt.executeQuery("SELECT * FROM DUAL");
      System.out.println("Results:");
      int numcols = rset.getMetaData().getColumnCount();
      while (rset.next()) {
        for (int i = 1; i <= numcols; i++) {
          System.out.print("\t" + rset.getString(i));
        }
        System.out.println("");
      }
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    } catch (SQLException e) {
      e.printStackTrace();
    } finally {
      try {
        rset.close();
      } catch (Exception e) {
      }
      try {
        stmt.close();
      } catch (Exception e) {
      }
      try {
        conn.close();
      } catch (Exception e) {
      }
    }
  }
}

According to the instructions at, http://jakarta.apache.org/commons/dbcp/apidocs/org/apache/commons/dbcp/package-summary.html#package_description, I think I have done every thing right.  It states the following:

"Simply save that file somewhere in your classpath as eg.jocl, and the PoolingDriver will find it automatically. You need only register the PoolingDriver (for example, using the jdbc.drivers property), and use the the DriverManager to create your Connections, like you normally would:

Connection conn = DriverManager.getConnection("jdbc:apache:commons:dbcp:/eg");"

What I am doing wrong?

Thank, in advance.
Avatar of girionis
girionis
Flag of Greece image

Do you have the maxdb.jocl file somewhere in your classpath?
Avatar of HycelTaylor
HycelTaylor

ASKER

Yes,

If that means that it's in my classes subdirectory: c:\apps\classes\com\tss\testadmin\resources\maxdb.jocl

At the beginning of my CLASSPATH variable I have: c:\apps\classes;
From the link you posted:

>(Note that without the leading slash, the pool must be located at
>org/apache/commons/dbcp/PoolingDriver/eg.jocl within your classpath. See Class.getResource(java.
>lang.String) for details.)

Can you put the maxdb.jocl in the org/apache/commons/dbcp/PoolingDriver/ folder and try again? Otherwise put it inside the:

c:\apps\classes\com\tss\testadmin\maxdb.jocl (without the "resources" folder).

Try the above and tell me if they help.
Or even in the:

c:\apps\classes\com\tss\testadmin\service\maxdb.jocl
I've tried putting it in:

c:\apps\classes\com\tss\testadmin\resources\maxdb.jocl
c:\apps\classes\com\tss\testadmin\service\maxdb.jocl
c:\apps\classes\com\tss\testadmin\maxdb.jocl

All to no avail.

I'm not sure if I tried your last suggestion correctly.  I created the following subdirectory:

C:\apps\classes\org\apache\commons\dbcp\PoolingDriver and placed maxdb.jocl in it.  

It didn't work either.  Is this what you meant?
Try putting it in the

c:\apps\classes\com\tss\testadmin\service\maxdb.jocl

and tell me if it works.
Bah.. sorry ignore my above comment, you have already done so... Let me see what I can find.
ASKER CERTIFIED SOLUTION
Avatar of girionis
girionis
Flag of Greece image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Please ignore this line:

> DriverManager.getConnection("jdbc:apache:commons:dbcp:/maxdb");.

of my comment above. I was just doing a comparison of the name.
>  You need only register the PoolingDriver (for example, using the jdbc.drivers property),

Have you done the above?
Wonderful news!  I tried placing it under c:\apps\classes and now I have a new exception:

org.apache.commons.dbcp.DbcpException: org.xml.sax.SAXException: System property org.xml.sax.driver not specified
      at org.apache.commons.dbcp.PoolingDriver.getPool(PoolingDriver.java:110)
      at org.apache.commons.dbcp.PoolingDriver.connect(PoolingDriver.java:142)
      at java.sql.DriverManager.getConnection(DriverManager.java:512)
      at java.sql.DriverManager.getConnection(DriverManager.java:193)
      at com.tss.testadmin.service.JOCLPoolingExample.main(JOCLPoolingExample.java:39)
Caused by: org.xml.sax.SAXException: System property org.xml.sax.driver not specified
      at org.xml.sax.helpers.XMLReaderFactory.createXMLReader(XMLReaderFactory.java:90)
      at org.apache.commons.jocl.JOCLContentHandler.parse(JOCLContentHandler.java:377)
      at org.apache.commons.jocl.JOCLContentHandler.parse(JOCLContentHandler.java:309)
      at org.apache.commons.dbcp.PoolingDriver.getPool(PoolingDriver.java:108)
      ... 4 more
Exception in thread "main"

But, this is progress:-)

I'm not sure what,  System property org.xml.sax.driver not specified, means.  Any ideas?
Can you try adding these lines:

new PoolingDriver().registerPool("myPool", new GenericObjectPool(null));
That's good news, I knew it was a classpath problem but I was not sure where exactly it should be. This confirms the saying that goes "if in doubt it's a classpath problem" :)

> System property org.xml.sax.driver not specified

You are obviously using a SAX parser. You need to specify the driver of the SAX pareser you are using, either in the command line -Dorg.xml.sax.driver=myclass.sax.mydriver.DriverClass or in the properties of your class by usign the System.getProeprties().put("org.xml.sax.driver", <value of your sax driver here>);
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Two questions:

1) Where exactly, in my code, do you want me to put the instruction?

2) Do you want me to use the words "myPool"? Or replace it with something else?

Ignore the "myPool" thing, I just thought we coudl try it but it now works so this was never actually the problem.

Try to resolve the SAX issue. Which SAX parser are you using?
I am currently using the sax2.jar.  

I was trying to follow the example at, http://cvs.apache.org/viewcvs.cgi/jakarta-commons/dbcp/doc/JOCLPoolingDriverExample.java?rev=1.4&view=markup.  It says the following:

// To compile this example, you'll need nothing but the JDK (1.2+) in your classpath.
//
// To run this example, you'll want:
//  * commons-collections.jar
//  * commons-pool.jar
//  * commons-dbcp.jar
//  * the classes for your (underlying) JDBC driver
//  * sax2.jar (the SAX 2 API)
//  * a SAX2 friendly XML parser (jaxp.jar and parser.jar,
//    for example)
//  * the JOCL configuration for your database connection pool
//    (poolingDriverExample.jocl, for example)  in your classpath.

I looked every where to download, parser.jar, but couldn't find it.
I don't know if I need both.
I think you might already have parser.jar. Do a search on your hard drive and tell me if you can find it.
I think so.  My search has found a parser.jar under c:\StrutsStudioPro\eclipse\plugins\org.apache.lucene_1.2.1.
Does that sound like it?

Also, I have a crimson.jar.  Isn't it also a sax2 friendl XML parser?  And if it is, is there a reason for using one parser over another?

For crimson, I'm trying to figure out what to put for:

java -Dorg.xml.sax.driver=????
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
It's like pulling teeth.  

I added the VM command, -Dorg.xml.sax.driver=org.apache.crimson.parser.XMLReaderImpl, and it worked.  But then I got the following exception:

org.apache.commons.dbcp.DbcpException: java.lang.ClassNotFoundException: org.apache.commons.pool.StackKeyedObjectPoolFactory
      at org.apache.commons.dbcp.PoolingDriver.getPool(PoolingDriver.java:110)
      at org.apache.commons.dbcp.PoolingDriver.connect(PoolingDriver.java:142)
      at java.sql.DriverManager.getConnection(DriverManager.java:512)
      at java.sql.DriverManager.getConnection(DriverManager.java:193)
      at com.tss.testadmin.service.JOCLPoolingExample.main(JOCLPoolingExample.java:40)
      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:324)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:78)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool.StackKeyedObjectPoolFactory
      at org.apache.commons.jocl.JOCLContentHandler.startElement(JOCLContentHandler.java:514)
      at org.apache.crimson.parser.Parser2.maybeElement(Parser2.java:1488)
      at org.apache.crimson.parser.Parser2.content(Parser2.java:1779)
      at org.apache.crimson.parser.Parser2.maybeElement(Parser2.java:1507)
      at org.apache.crimson.parser.Parser2.parseInternal(Parser2.java:500)
      at org.apache.crimson.parser.Parser2.parse(Parser2.java:305)
      at org.apache.crimson.parser.XMLReaderImpl.parse(XMLReaderImpl.java:442)
      at org.apache.commons.jocl.JOCLContentHandler.parse(JOCLContentHandler.java:380)
      at org.apache.commons.jocl.JOCLContentHandler.parse(JOCLContentHandler.java:309)
      at org.apache.commons.dbcp.PoolingDriver.getPool(PoolingDriver.java:108)

So, I checked the package and there is no class named: org.apache.commons.pool.StackKeyedObjectPoolFactory.

So, I checked the jocl config file that I copied from the example in the JOCL api documentation, and found the following:

 <!-- the next argument is the KeyedObjectPoolFactory -->
   <object class="org.apache.commons.pool.StackKeyedObjectPoolFactory">
      <int value="5"/> <!-- max idle -->
   </object>

So, I changed it to the following:

<!-- the next argument is the KeyedObjectPoolFactory -->
   <object class="org.apache.commons.pool.KeyedObjectPoolFactory">
      <int value="5"/> <!-- max idle -->
   </object>

Apparently, this is not correct either.  Now, I get the following exception:

org.apache.commons.dbcp.DbcpException: java.lang.NullPointerException
      at org.apache.commons.dbcp.PoolingDriver.getPool(PoolingDriver.java:110)
      at org.apache.commons.dbcp.PoolingDriver.connect(PoolingDriver.java:142)
      at java.sql.DriverManager.getConnection(DriverManager.java:512)
      at java.sql.DriverManager.getConnection(DriverManager.java:193)
      at com.tss.testadmin.service.JOCLPoolingExample.main(JOCLPoolingExample.java:39)
      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:324)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:78)
Caused by: java.lang.NullPointerException
      at org.apache.commons.jocl.JOCLContentHandler.endElement(JOCLContentHandler.java:553)
      at org.apache.crimson.parser.Parser2.maybeElement(Parser2.java:1528)
      at org.apache.crimson.parser.Parser2.content(Parser2.java:1779)
      at org.apache.crimson.parser.Parser2.maybeElement(Parser2.java:1507)
      at org.apache.crimson.parser.Parser2.parseInternal(Parser2.java:500)
      at org.apache.crimson.parser.Parser2.parse(Parser2.java:305)
      at org.apache.crimson.parser.XMLReaderImpl.parse(XMLReaderImpl.java:442)
      at org.apache.commons.jocl.JOCLContentHandler.parse(JOCLContentHandler.java:380)
      at org.apache.commons.jocl.JOCLContentHandler.parse(JOCLContentHandler.java:309)
      at org.apache.commons.dbcp.PoolingDriver.getPool(PoolingDriver.java:108)

It's progress.  Any suggestions?
> So, I checked the package and there is no class named: org.apache.commons.pool.StackKeyedObjectPoolFactory.

Can you make sure that you have *all* the needed files?
I'm pretty sure I have all the files.  There's not StackKeyedObjectPoolFactory.  I went to , http://cvs.apache.org/viewcvs.cgi/jakarta-commons/dbcp/doc/test.jocl?rev=1.2&view=markup, and replace my jocl schema with the one on this page.  I tried using the following configuration document:

<object class="org.apache.commons.dbcp.PoolableConnectionFactory" xmlns="http://apache.org/xml/

xmlns/jakarta/commons/jocl">
   <object class="org.apache.commons.dbcp.DriverConnectionFactory">
      <object class="com.sap.dbtech.jdbc.DriverSapDB"/>
      <string value="jdbc:sapdb:///ESCO"/>
      <object class="java.util.Properties" null="true"/>
   </object>
   <object class="org.apache.commons.pool.impl.GenericObjectPool">
      <object class="org.apache.commons.pool.PoolableObjectFactory" null="true"/>
      <int value="10"/>
      <byte value="1"/>
      <long value="2000"/>
      <int value="10"/>
      <boolean value="true"/>
      <boolean value="true"/>
      <long value="10000"/>
      <int value="5"/>
      <long value="5000"/>
      <boolean value="true"/>
   </object>
   <object class="org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory">
      <object class="org.apache.commons.pool.KeyedPoolableObjectFactory" null="true"/>
      <int value="10"/>
      <byte value="1"/>
      <long value="2000"/>
      <int value="10"/>
      <boolean value="true"/>
      <boolean value="true"/>
      <long value="10000"/>
      <int value="5"/>
      <long value="5000"/>
      <boolean value="true"/>
   </object>
   <string value="SELECT COUNT(*) FROM DUAL"/>
   <boolean value="false"/>
   <boolean value="true"/>
</object>

This gave the following exception:

java.lang.NullPointerException
      at com.sap.dbtech.jdbc.DriverSapDB.openTrace(DriverSapDB.java:206)
      at com.sap.dbtech.jdbc.DriverSapDB.connect(DriverSapDB.java:173)
      at org.apache.commons.dbcp.DriverConnectionFactory.createConnection(DriverConnectionFactory.java:83)
      at org.apache.commons.dbcp.PoolableConnectionFactory.makeObject(PoolableConnectionFactory.java:184)
      at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:722)
      at org.apache.commons.dbcp.PoolingDriver.connect(PoolingDriver.java:147)
      at java.sql.DriverManager.getConnection(DriverManager.java:512)
      at java.sql.DriverManager.getConnection(DriverManager.java:193)
      at com.tss.testadmin.service.JOCLPoolingExample.main(JOCLPoolingExample.java:40)
      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:324)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:78)
Exception in thread "main"

So, I modified the configuration slightly from:

  <object class="org.apache.commons.dbcp.DriverConnectionFactory">
      <object class="com.sap.dbtech.jdbc.DriverSapDB"/>
      <string value="jdbc:sapdb:///ESCO"/>
      <object class="java.util.Properties" null="true"/>
   </object>

To:

  <object class="org.apache.commons.dbcp.DriverConnectionFactory">
      <object class="com.sap.dbtech.jdbc.DriverSapDB"/>
      <string value="com.sap.dbtech.jdbc.DriverSapDB/jdbc:sapdb:///ESCO"/>
      <object class="java.util.Properties" null="true"/>
   </object>

Now I'm getting the following exception:

java.lang.NullPointerException
      at org.apache.commons.dbcp.DelegatingConnection.setAutoCommit(DelegatingConnection.java:237)
      at org.apache.commons.dbcp.DelegatingConnection.setAutoCommit(DelegatingConnection.java:237)
      at org.apache.commons.dbcp.PoolableConnectionFactory.activateObject(PoolableConnectionFactory.java:273)
      at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:753)
      at org.apache.commons.dbcp.PoolingDriver.connect(PoolingDriver.java:147)
      at java.sql.DriverManager.getConnection(DriverManager.java:512)
      at java.sql.DriverManager.getConnection(DriverManager.java:193)
      at com.tss.testadmin.service.JOCLPoolingExample.main(JOCLPoolingExample.java:40)
      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:324)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:78)
Exception in thread "main"

I don't know if I'm getting warmer or not?  Any suggestions?
You know what?  I'm beginning to think that using a JOCL file is just that, a Joke.  I successfully tried the following set of code to get a connection:

try {
      Class.forName("com.sap.dbtech.jdbc.DriverSapDB");
      Class.forName("org.apache.commons.dbcp.PoolingDriver");

      GenericObjectPool connectionPool = new GenericObjectPool(null);
      ConnectionFactory connectionFactory = new DriverManagerConnectionFactory
        ("jdbc:sapdb:///ADMIN", "myuser", "mypassword");
      PoolableConnectionFactory poolableConnectionFactory =
         new PoolableConnectionFactory(connectionFactory, connectionPool, null, null, false, true);
      PoolingDataSource dataSource = new PoolingDataSource(connectionPool);
      Connection conn = dataSource.getConnection();
    } catch (Exception e) {
      e.printStackTrace();
    }

With the time that it is taking to figure out how to use the JOCL resource correctly, I could use the commons-config to extract information from the config file and initialize the above classes myself;  which is exactly what I'm gonna do.

Anyway, you answered the question that started all of this.  That was how to find the resource in the class path. So, you've more than earned the 500 points and then some.  

Thank you girionis, for all of your help today conserning this issue.  I'm much obliged:-)
> I don't know if I'm getting warmer or not?  Any suggestions?

Same here. What is the line that throws the npe?
Also it would be good if you could try another parser.
Well, as long as you are happy with the solution and it works then go for it :)

Glad I was of help :)
Just one more question conserning you suggestion about using another parser.

I tried using the Parser.jar, that I found on my harddrive, but it doesn't appear to the actual Parser. But some subset of it or simple another class, entirely, with the same name.

What parser would you suggest?  
What about Xerces-J?

Irrespective of the one you suggest, how do you determine which is the right class to register.  For example, with crimson, you knew to use java -Dorg.xml.sax.driver=org.apache.crimson.parser.XMLReaderImpl.

Thank you for accepting :)

I use xerces-2 from the apache project: http://xml.apache.org/xerces2-j/

> Irrespective of the one you suggest, how do you determine which is the right class to register.

One of the classes in the jar file is the driver. You need to look at the docs to find out which one you have to use :)