04 July 2011

Plugging in a later version of EclipseLink to WebLogic Server

Talking with Doug Clarke of EclipseLink fame and fortune last week, it sounds like there is some real interest from developers in wanting to update WebLogic Server to use later versions of the EclipseLink in order to access it's evolving feature set.

Which should offer no surprises really, EclipseLink rocks.

Investigation

Turning to the situation at hand, the main points to be addressed are:

1. The later versions of EclipseLink are JPA 2.0 based, so we'll assume that the predominant use case is centered around using JPA 2.0.

WebLogic Server supports JPA 2.0 through the application of a Smart Update patch or via manual adjustments to the PRE_CLASSPATH to incorporate two additional JAR files that enable the use of JPA 2.0. 

We'll consider this one easy to handle using documented features.

2. WebLogic Server provides a version of EclipseLink that is loaded as one it's standard feature bearing modules and thus is present by default in the classpath of WebLogic Server for deployed applications.  For WLS 10.3.5, this version is org.eclipse.persistence_1.1.0.0_2-1.jar.

WebLogic Server has a feature called the Filtering Classloader, which enables applications to selectively override the libraries from WebLogic Server that an application sees.  This should allow an application to be configured to not use the default version of EclipseLink that WebLogic Server provides.  This requires each application to specifically provide a weblogic-application.xml file that lists the <prefer-application-packages> configuration set to explicitly filter our the org.eclipselink.persistence package.

3. Any change to the EclipseLink version should be isolated to just an application, and not applied to an entire WebLogic Server installation or domain.

To make the later version of EclipseLink available, there are a few simple options available that could be explored: a) the EclipseLink jar file could be added to the CLASSPATH of WebLogic Server; b) the EclipseLink jar file could be dropped into the $domain/lib directory; c) the newer version of EclipseLink could be used to replace the existing EclipseLink jar file shipped with WebLogic Server, retaining the same name; d) the WebLogic Server shared-library mechanism could be used to deploy the EclipseLink libraries which applications can then selectively reference.

For the sake of expediency, I won't bother going through the pros/cons with each of those options and will just pick a winner from my perspective: the use of a shared-library to provide a selectively consumable version of EclipseLink.

Let's just examine this for a moment -- a WebLogic Server shared-library is an artifact that can be deployed to a WebLogic Server target, which can then be referenced by an application being deployed, whereupon WebLogic Server will merge the contents of the shared-library with the application.  This enables common libraries to be deployed and used by multiple applications.  Furthermore, shared-libraries can take the format of a standard Java EE archives, where descriptors can be provided which are then also merged with the final application deployment. 

Given those capabilities:

a) it's possible to construct and deploy an EAR file based shared-library that contains a later version of EclipseLink and a weblogic-application.xml file which provides a preset prefer-application-packages setting that filters the org.eclipselink.persistence.* package. 

b) to use a later version of EclipseLink, an application simply needs to include it's own weblogic-application.xml that imports the EclipseLink shared-library it need to use.

Thus, we have a supported deployment format (can be targeted at single nodes, clusters, whatever ...) to provide later versions of EclipseLink, which can be shared and selectively used by applications as desired.

Implementation

To test this out in an end-to-end manner, I performed the following steps:

1. Downloaded eclipselink-2.2.0.v20110202-r8913.zip from the EclipseLink web site.

2. Created a small ant project to produce an eclipselink-shared-lib.ear file.  The layout of the shared-library is just a standard Java EE EAR file and contains the following items:

META-INF/weblogic-application.xml
META-INF/application.xml
lib/eclipselink.jar

The weblogic-application.xml file contains the following configuration elements:

<weblogic-application>
  <prefer-application-packages>
    <package-name>org.eclipse.persistence.*</package-name>
  </prefer-application-packages>
</weblogic-application>

The application.xml was a necessary element to support the runtime library merging.  As you can see from the below, it's basically a NOOP configuration file.

<application>
  <display-name>eclipselink-shared-lin</display-name>
  <module>
        <java></java>
  </module>
</application>

The ant build script produces an EAR file from these elements with one important addition that marks the EAR file as a shared-library for WebLogic Server by adding a number of attributes to the META-INF/MANIFEST.MF file:

<target name="package" depends="prepare">
    <jar destfile="dist/${ant.project.name}.ear">
        <metainf dir="etc" includes="*.xml"/>
        <manifest>
            <attribute name="Extension-Name" value="eclipselink"/>
            <attribute name="Specification-Version" value="2.0"/>
            <attribute name="Implementation-Version" value="2.2.0"/>
        </manifest>

        <fileset dir="build" includes="**/*"/>
    </jar>       
</target>

At deployment time, WebLogic Server will use the attributes as meta-data for the deployed shared-library.

The final EAR file looks like this:

sbutton:~/Projects/Java/eclipselink-shared-lib/dist $ jar tf eclipselink-shared-lib.ear
META-INF/
META-INF/MANIFEST.MF
META-INF/application.xml
META-INF/weblogic-application.xml
lib/
lib/eclipselink.jar

For reference, the simple ant project to build the eclipselink-shared-lib.ear file is here: eclipselink-shared-lib.zip.

3. Deployed eclipselink-shared-lib.ear to WebLogic Server.  This results in a new library being available on the server, eclipselink#2.0@2.2.0.

4. Created a test application that imports eclipselink#2.0@2.2.0 and outputs the version of it that it is seeing.

The application uses a weblogic.xml to reference the eclipselink#2.0@2.2.0 shared-library that was deployed, which picks up both the new version of eclipselink.jar as well as the filtering-classloader description the library contains:



weblogic-application.xml:

<weblogic-application>
    <library-ref>
        <library-name>eclipselink</library-name>
        <specification-version>2.0</specification-version>
        <implementation-version>2.2.0</implementation-version>
    </library-ref>

</weblogic-application>

Within the application, used a simple servlet that outputs the version of EclipseLink it is seeing:

out.printf("<p>EclipseLink Version: %s</p>", org.eclipse.persistence.Version.getVersionString());


5. Packaged the application into an EAR file and deployed it to WebLogic Server as an application.

When the application is accessed it reports the new version of EclipseLink supplied via the shared-library:

EclipseLink Version: 2.2.0.v20110202-r8913
 
6. Performed a negative test by undeploying the application, removed the weblogic-application.xml file from it and redeployed it.

When the application is accessed it reports the default version of EclipseLink that WebLogic Server supplies:

EclipseLink Version: 2.1.3.v20110304-r9073

7.  With the basic premise validated, add a JPA module to validate the code-weaving EclipseLink performs works as expected.  To verify the version EclipseLink is using the EclipseLink log level was set to fine and the console output reviewed, which showed up as Eclipse Persistence Services - 2.2.0.v20110202-r8913

Summary

The use of WebLogic Server shared-libraries appears to be a very suitable model for providing later versions of EclipseLink that automatically filter out the WebLogic Server supplied versions, which applications can selectively choose to import when they need the later versions.

This was just a simple test of the concept of using WebLogic Server shared-libraries to do this.  The EclipseLink/TopLink team are in the throes of formally certifying this approach, so keep an eye out for it on the EclipseLink site if it does pass full muster!

5 comments:

Anonymous said...

First comment: why isn't simply putting the 2.x eclipselink.jar in the webapp's WEB-INF/lib folder an option? Then the configuration wouldn't be required right?


I need to deploy a J2EE container agnostic webapp, and it currently works under tomcat/eclipselink 2.1.1/MySQL. Deploying the same webapp in WebLogic 10.3.5 results in this sent to the console when the EntityManager connects:




INFO: EclipseLink, version: Eclipse Persistence Services - 2.1.3.v20110304-r9073


Oct 5, 2011 7:53:36 AM org.eclipse.persistence.session.file:/C:/Oracle/Middleware/user_projects/domains/titn/autodeploy/titn/WEB-INF/classes/_titn




The exact same log statement when running under tomcat produces the expected version: 2.1.1.v20100817-r8050


It's driving me insane. I have no idea where it's getting 2.1.3 from, and then when it tries the first insert, I get a constraint violation saying the PK is null when commit() is called!


Do you have any diagnostic suggestions or form recommendations?

Buttso said...

Hi --

The primary difference here that you need to take into account is that Tomcat is a servlet container and doesn't provide any form of default JPA implementation.

WebLogic Server on the other hand (and GlassFish and JBoss and TomEE now) are Java EE servers and therefore provide a default JPA implementation as part of their runtime.

If you are deploying your application to WebLogic Server, then unless you have a specific need for a specific version of EclipseLink, you really don't need to bundle anything with the application. Since WebLogic Server provides the JPA API/implementation, your application doesn't need to provide.

The EclipseLink 2.1.3 version output you see will be from the default version that WebLogic Server provides as part of it's Java EE requirements.

If you want to change the version of EclipseLink that WebLogic Server uses to match what you are needing to bundle inside your application to support JPA on Tomcat, then you'll need to follow the sorts of instructions here.

You may perhaps see that as "make work" you have to do in order to get WebLogic Server to use your app to deploy -- I'd see it a little differently in that you are needing to do more work in your application running on Tomcat (ie transaction management, library bundling) since it doesn't provide JPA support.

Hope that helps some.

-steve-

Arulkumaran Kumaraswamipillai said...

Had this problem recently, and this article helped resolve it.

Anonymous said...

I am trying to upgrade my weblogic JPA (eclipselink) version to 2.1?

Hi,

how to enable JPA2.1 support in weblogic 12.1.2 ?

I am finding javax.persistence_2.1.0.0_1-0-2.jar in /modules/ directory of my weblogic 12.1.2 production installation. but I am not able use JPA2.1 methods , during runtime , I am getting noSuchMethod error when I try to call createStoredProcedureQuery. but in the javax.persistence_2.1.0.0_1-0-2.jar it is there.

StoredProcedureQuery storedProcedure =
entityManager.createStoredProcedureQuery("SP_GET_GSA_CAMEL2");


I have added the below line in commEnv.sh, But no help. Still getting the error.

export PRE_CLASSPATH=/wls/product/ofm12.1.2/oracle_common/modules/javax.persistence_2.1.0.0_1-0-2.jar:

can somebody reply any specific steps I have to follow to enable JPA2.1 features in weblogic 12.1.2.

regards
Muthuvel

Buttso said...

WLS 12.1.2 supports JPA 2.0.

Updating to JPA 2.1 on WLS 12.1.2 is not really possible to do as there are some integration points within the container to allow it to work properly and these are currently based on the mandated JPA 2.0 specification.

The good news is that we will be supporting an optional update to JPA 2.1 in the forthcoming WLS 12.1.3 release, so the steps you have shown here will be possible to perform and have the container support JPA 2.1 instead of the default JPA 2.0 it is configured with.