2010-05-09

Shared Libraries versus Optional Packages

Starting with WebLogic Server 9, BEA introduced an interesting concept aiming at sharing more easily libraries between EARs.
From a performance point of view and memory imprint, there’s absolutely no change : the library will still be loaded in each and every EAR classloader.
But from a packaging point of view, it allows you to reduce significantly the size of your archives, by externalizing the common libraries.
Moreover, when you have to upgrade one of your lib, it’s easier to do, thanks to centralization.

In my case, I’m currently working on a key SOA project on which a huge work had been done on isolating services from a business point of view.
But technically, all the services were packaged in the same EAR, which is a serious problem for the high availability we are supposed to provide.
(in case of a new version, it would lead to an undeployment of the whole archive : production redeployment is not an option since the archive is pretty bulky)
So I had to explode the EAR in several WARs and adopt a strategy for the library sharing.

Deploying libraries


First of all, whether you'll use the “shared library” or the “optional package” mechanism, your libraries (JARs in our case but can be WAR, RAR …)
must respect a certain definition in their manifests, such as :
Extension-Name: fr.mbutton.blog
Specification-Vendor: Tengah Consulting 
Specification-Version: 1.0 
Implementation-Vendor-Id: fr.tengah-consulting 
Implementation-Vendor: Tengah Consulting 
Implementation-Version: 1.1
This example has been inspired by the example found on sun.com.
Based on my experience, the only lines that really matter are the following :
Extension-Name: fr.mbutton.blog
Specification-Version: 1.0
Implementation-Version: 1.1
WebLogic Server will use the extension name to determine the name it will use for the library you’re deploying.
If none, then the name of the file itself will be used to qualify deployed archive name, as explained on Oracle documentation.

In my case, I had to list all the libraries used in our application and see whether they were eligible for being deployed as a shared library.
And I realized that lots of libraries you can find on the market are / were not thought to be deployed as optional package / shared libraries.

So far, the only libraries that were clearly designed following this standard are the libs from Apache.
Regarding the specification & implementation versions, you may specify those pieces of information while deploying,
but it is a good practice to have them described in the library manifest.

Moreover as described in the official Oracle documentation, you should be careful while using this modus operandi :
“If both the manifest file and the weblogic.Deployer command line specify version information, and the values do not match, the deployment fails.
If you initially registered a library without providing a specification or implementation version,
you must undeploy the library before registering a newer version and specifying version string information.

You can register multiple versions of a library or package, but each version must use the same version strings.
For example, you cannot register a library having only a specification version,
and then register a new version of the library having both a specification and an implementation version.”
Referencing Shared Libraries

Now our libraries are correctly defined and deployed the use as shared libraries is really simple.
According to the documentation about the weblogic deployment descriptors (weblogic.xml & weblogic-application.xml), the way to reference a library is the following :
<library-ref>
    <library-name>fr.mbutton.blog</library-name>
    <specification-version>1.0</specification-version>
    <implementation-version>1.1</implementation-version>
    <exact-match>false</exact-match>
</library-ref>
But one major problem is that you cannot reference all the types, just as it is clearly said in the official documentation :
“You cannot reference any other type of shared Java EE library (EJB, Enterprise application, or plain JAR file)
from the weblogic.xml deployment descriptor file of a Web Application.”
In other words, it is impossible to reference JAR files in a web application (WAR).
Hummmm … annoying since it’s exactly what I’m trying to do …
Then my friend & colleague Romain told me about the optional packages.


Referencing Optional Packages

With optional packages, that annoying limitation is no more.
If you followed the pieces of advice regarding the correct deployment of libraries for a use as shared libraries,
that’s perfect because you won’t have anything to change to switch to optional packages.

The only thing that changes is the way you will refer to them.
Using optional packages, you simply have to update the manifest for your WAR such as :
Extension-List: blog
blog-Extension-Name: fr.mbutton.blog
blog-Specification-Version: 1.0
blog-Implementation-Version: 1.1
And suppose we have another library :
<library-ref>
    <library-name>org.springframework</library-name> 
    <specification-version>3.0</specification-version> 
    <implementation-version>3.9beta</implementation-version> 
    <exact-match>false</exact-match> 
</library-ref>
This time, the definition in the manifest would be :
Extension-List: blog spring
blog-Extension-Name: fr.mbutton.blog
spring-Extension-Name: org.springframework
blog-Specification-Version: 1.0
spring-Implementation-Version: 3.9beta
Once again, I’m not inventing this : you can read it here.

Finally …

Okay here we are, time for a conclusion !

Shared libraries :
  • are cool but do not allow all type of referencing (-)
  • are WebLogic Server specific (-)
  • are XML based (+?)
Whereas optional packages :
  • are standard … (+)
  • … but completely based on manifests : almost worst than Cobol ! (-)
  • allow a lot more possibilities (+)
Hope this post helped to enlighten a bit your path.

Resources :

Mots clés Technorati : ,,,,

4 comments:

Richard Schuller said...

I am trying to reproduce the steps you described in your blog but I am getting java.lang.NoClassDefFoundError when trying to deploy a jar that depends on the shared library

rattana said...

Bonjour,
Est ce que vous seriez disponibles pour m'éclairer sur certains points ?

Nadine said...

I have an inquiry regarding deployment

I have around 50 struts portlets in my weblogic portal, so we have now one ear which ends up that whenever we change any portlet or need to add a new module we will have to redeploy the whole portal !!!
I have read about federated portal, but it seems that its great advantage is when your portal wants to consume remote portlets deployed in remote producers, but this is not my case, since all my portlets are local ones, so I think there might be a simpler solution (*like in websphere where we have separate war for each portlet*)

How can I accomplish this in WebLogic, deploying each module in a seperate WAR?
Any suggestions?

Nadine said...

I have an inquiry regarding deployment

I have around 50 struts portlets in my weblogic portal, so we have now one ear which ends up that whenever we change any portlet or need to add a new module we will have to redeploy the whole portal !!!
I have read about federated portal, but it seems that its great advantage is when your portal wants to consume remote portlets deployed in remote producers, but this is not my case, since all my portlets are local ones, so I think there might be a simpler solution (*like in websphere where we have separate war for each portlet*)

How can I accomplish this in WebLogic, deploying each module in a seperate WAR?
Any suggestions?