Arch2Arch Tab BEA.com
Syndicate this blog (XML)

WebLogic Event Server: Using Third-Party Libraries

Bookmark Blog Post

del.icio.us del.icio.us
Digg Digg
DZone DZone
Furl Furl
Reddit Reddit

Seth White's Blog | October 29, 2007   9:48 AM | Comments (2)


In this entry I discuss the options that are available for configuring third-party Java libraries for use with Event Server 2.0 applications.  This is a common requirement for many applications.

The first option that I would like to discuss is adding a third-party library jar to the boot classpath of the Event Server.  This is a good option to use if you want to try out a third-party library quickly during development and may also be appropriate for production deployments.  When using JRockit or the Sun JVM adding a jar to the boot classpath requires that one specify an additional argument when starting the Event Server, namely: -Xbootclasspath/a: <path_to_library_jar>\<jar_file_name>.  This will append the library jar to the boot classpath of the virtual machine and make the classes contained within the jar available to all applications deployed in your Event Server instance. 

How does this work exactly?  Well, the Event Server is based on a modular architecture (OSGi) in which each module is given its own classloader for loading the classes and resources needed by that module.  This fact plus the fact that each application is packaged as a module means that each application effectively gets its own classloader.  An application classloader first attempts to load classes from its parent which by default is the Java boot classloader before loading classes from some other module or from itself.  So, adding a class to the boot classpath will guarantee that the application loads the class from there.  If you would like more details about how OSGi bundle classloaders search for classes, see Section 3.8.4 of the OSGi Release 4 Core Specification

This approach works well for simple third-party libraries, but it has some limitations.  For example, all of the classes needed by the third-party library must be visible to the boot classloader.  This means you might end up needing to add several jars to the boot classpath if the jars reference each other's classes.  It also means that the third-party library cannot load classes contained in the application bundle since they are not visible to the boot classloader.  Another thing to keep in mind is that adding a class to the boot classpath makes it visible to all applications running in the server which may not be what you want.

Another technique that is quite similar to adding your library to the boot classpath is to place the library in the extensions subdirectory of the JVM.  The extension subdirectory is located here: <JAVA_HOME>/jre/lib/ext.  This can be useful if your library needs to load classes contained in other extension libraries.  If you decide to do things this way you need to specify the following command line argument to the JVM in addition to copying your library into the extensions directory.

-Dosgi.parentClassloader=ext

This argument tells the application classloaders to use the extension classloader as their parent and delegate to it instead of delegating to the boot classloader. 

You may be wondering why I recommend adding libraries to the boot or extension classpaths rather than simply using the -classpath option of the JVM.  This is because the Event Server uses java's -jar feature to specify the Java executable, like so

java  ... -jar <WLEVS_HOME>/bin/wlevs_2.0.jar

When the -jar option is used the user classpath setting is ignored, which means you can't use -classpath.  Of course, you could try to start the event server without using -jar, but this is not recommended.

So far, we've discussed what I would call "quick and dirty" techniques for configuring third-party libraries.  These techniques are great for prototyping during development.  A second, more elegant approach is to package the third-party library inside the application bundle itself.  You can do this by "exploding" the third-party jar or by including it directly.  If you include the third-party jar directly, you need to add it to what is called the "bundle classpath" by adding an entry like the following in the Manifest.mf file for your application.

Bundle-Classpath: <path_name>/<file_ name>.jar

This tells the server which nested jars in the application bundle contain classes that should be loaded by the application classloader.  This approach has a couple of advantages.  One advantage is that it helps to keep the application self-contained.  This makes it easier to deliver the application to another group for testing or deployment on a production system.  Another advantage is that the third-party library can now load any class that is visible to the bundle, including user-written classes.  This can be useful if the third-party library loads application classes by name.

The final option for configuring a third-party library is to package the library in its own bundle and deploy it to the server as a separate application.  The library bundle must export a set of packages containing classes that other bundles can use and it must also import any packages that contain classes that the library itself needs.  Getting these lists of exported and imported packages right usually requires some knowledge of the internal workings of the third-party library, so if your vendor hasn't provided you with a bundle up front, this option may be rather difficult.  It's worth noting, however, that tools like bnd can help immensely with the bundle creation process.  Conversely, if the third-party library needs to load application classes, your application bundle will need to export them.  Exporting classes from an application bundle has a subtle disadvantage which is that hot redeploy of the application may not work as expected once other bundles in the system have imported the application classes.  This is because a bundle can only import one version of a class, so if you hot redeploy your application and have made changes to an application class, those changes will not be visible to other bundles that have imported your application class until you restart the server.  For this reason, it's generally a good idea to avoid exporting classes from your applications.

That completes the list of alternatives for configuring third-party libraries.  To sum things up, the quick and dirty approaches are great for prototyping but make the application less self-contained.  Packaging third-party libraries in a separate bundle works well unless the third-party library needs to import application classes in which case it probably a better idea to package the third-party library within the application bundle itself.

Technorati Tags: , ,

Comments

Comments are listed in date ascending order (oldest first) | Post Comment

  • Great summary Seth.

    I like bnd myself. Here's a bnd file for the Oracle "thin" JDBC driver:

    Export-Package: oracle.*; version= 1.0
    Import-Package: *;resolution:=optional
    Private-Package: oracle.*
    
    and a little Ant snippet to run it:
    
      
        
      
    
      
    
      
    
    
    - Phil

    Posted by: paston on October 30, 2007 at 11:40 AM

  • Grr.... that looked good in "preview". I'll try once more to get quoted XML past Moveable Type before screaming for Jon....
    <target name="bnd-oracle">
      <path id="classpath">
        <fileset dir="${oracle.dir}/jdbc/lib/" includes="ojdbc14.jar"/>
      </path>
    
      <property name="flat.classpath" refid="classpath"/>
    
      <bnd
        classpath="${flat.classpath}"
        eclipse="false"
        failok="false"
        exceptions="true"
        files="oracle.bnd"
        output="${domain.dir}"/>
    </target>
    

    Posted by: paston on October 30, 2007 at 11:41 AM



Only logged in users may post comments. Login Here.

Powered by
Movable Type 3.31