15 July 2008

Configuring a dataSource for MySQL using EM

If you try to use the EM console to configure an OC4J datasource that accesses a MySQL database, then you may run into a problem with EM reporting that the class you are specifying can't be found.

This troubles you somewhat because you've taken the usual approach of putting 3rd party libraries to be shared into the applib directory of the OC4J instance -- so the classes should be available!

Well the problem here is that when the datasource is being constructed by EM, the classloader that is used is one that is obtained from the ascontrol application. And if you look carefully at the configuration of the ascontrol application, you'll see that it specifically removes the global.libraries shared-library from its list of imports. And guess what -- the global.libraries shared-library is defined with a single code-source -- that being the contents of the applib directory. Therefore the ascontrol application does not see the mysqlconnector.jar file you put into the applib directory. At runtime OC4J would see it, so if you manually add the datasource definition it'll work fine -- but using EM to construct the MySQL datasource requires it to see the jar file.

The change to make this work is quite easy and you have few options:

1. You can edit the orion-application.xml file of the deployed ascontrol application, and comment out the line that removes the importing of the global.libraries.xml file:

<imported-shared-libraries>
<--
<remove-inherited name="global.libraries"/>
-->
<import-shared-library name="oracle.xml.security"/>
<import-shared-library name="oracle.xml.security"/>
</imported-shared-libraries>
2. You continue to use the convenience of applib to make the driver available container wide, but instead of reconfiguring the ascontrol application to not remove the global.libraries, you just drop the mysql-connector.jar file into the WEB-INF/lib directory of the ascontrol application, so it is able to locate the specified class from its own set of libraries. To to that, copy the mysql-connector.jar file into $ORACLE_HOME/j2ee/home/applications/ascontrol/ascontrol/web-inf/lib directory. And then restart either the ascontrol application, or the OC4J instance itself to ensure the new library is visible.

3. Instead of using the convenience of the applib directory, you can deploy the MySQL connector as a named/versioned shared-library and then specifically import it into applications where you need it. This would for example need to be done in the application you deploy that needs to connect to MySQL and where corresponding datasource is defined, and also in the ascontrol application itself. . To do the latter, since you can't use EM to configure itself, you'd need to edit the $ORACLE_HOME/j2ee/home/application-deployments/ascontrol/orion-application.xml file and manually add the import statement to pull in the MySQL shared-library:
  <imported-shared-libraries>
<remove-inherited name="global.libraries"/>
<import-shared-library name="oracle.xml.security"/>
<import-shared-library name="oracle.xml.security"/>
<import-shared-library name="mysql.connector"/>
</imported-shared-libraries>

02 July 2008

Using OC4J War File Manifest.mf Class-Path

There seemed to be some confusion around this area, so I posted a small example of using Manifest.mf Class-Path settings from a WAR file to OTN yesterday.

http://www.oracle.com/technology/tech/java/oc4j/10130/how_to/webapp-manifest-loading.zip

This example was build and tested against an OC4J 10.1.3 instance -- however it should work in the same way against 10.1.2 and 9.0.x releases. The app itself won't deploy to the earlier versions since the deployment files are using XSD. However the principle should be the same.

The use of OC4J 10.1.3 enables you to run classloader queries to observe the loader tree, see where code-sources are being loaded from, see which code-source classes are located in, etc.

Update: 3-July-2008

By removing any XSD elements from the deployment descriptors, the application referenced above can be rebuilt and successfully deployed to OC4J 10.1.2, whereupon the application works in exactly the same way as it does on 10.1.3. The only difference is in the output of the ClassLoader().toString method.

When running in 10.1.2, the output from the testservlet and testclass.jsp pages looks is shown below. In the output, you can see that the code-sources foobar.jar and myservlet.jar are loaded from the root level of the application deployment directory, as configured in the META-INF/MANIFEST.MF file; whereas that the simple.jar is loaded from the WEB-INF/lib directory of the web application as expected.

Note: the output has been formatted slightly to make it more presentable in this page view.
Test Class Access

Class Loader

sab.demo.warmanifest.beans.Foo
[ClassLoader: [
[D:\java\oc4j-1012\j2ee\home\applications\webapp-manifest-loading\foobar.jar archive],
[D:\java\oc4j-1012\j2ee\home\applications\webapp-manifest-loading\myservlet.jar archive],
[D:\java\oc4j-1012\j2ee\home\applications\webapp-manifest-loading\webapp\WEB-INF\lib\simple.jar archive]
]]

sab.demo.warmanifest.beans.Bar
[ClassLoader: [
[D:\java\oc4j-1012\j2ee\home\applications\webapp-manifest-loading\foobar.jar archive],
[D:\java\oc4j-1012\j2ee\home\applications\webapp-manifest-loading\myservlet.jar archive],
[D:\java\oc4j-1012\j2ee\home\applications\webapp-manifest-loading\webapp\WEB-INF\lib\simple.jar archive]
]]

sab.demo.warmanifest.beans.Simple
[ClassLoader: [
[D:\java\oc4j-1012\j2ee\home\applications\webapp-manifest-loading\foobar.jar archive],
[D:\java\oc4j-1012\j2ee\home\applications\webapp-manifest-loading\myservlet.jar archive],
[D:\java\oc4j-1012\j2ee\home\applications\webapp-manifest-loading\webapp\WEB-INF\lib\simple.jar archive]
]]

sab.demo.warmanifest.web.TestServlet
[ClassLoader: [
[D:\java\oc4j-1012\j2ee\home\applications\webapp-manifest-loading\foobar.jar archive],
[D:\java\oc4j-1012\j2ee\home\applications\webapp-manifest-loading\myservlet.jar archive],
[D:\java\oc4j-1012\j2ee\home\applications\webapp-manifest-loading\webapp\WEB-INF\lib\simple.jar archive]
]]

org.apache.log4j.Logger
[ClassLoader: [
[D:\java\oc4j-1012\j2ee\home\applications\webapp-manifest-loading\log4j-1.2.15.jar archive]
]]

oracle.jdbc.pool.OracleDataSource
sun.misc.Launcher$AppClassLoader@a39137

javax.servlet.http.HttpServlet
sun.misc.Launcher$AppClassLoader@a39137