Archive for February, 2008

Oracle Application Server - SNAFU

Monday, February 4th, 2008

A long time ago, I had had to deploy a J2EE application on Oracle Application Server/OC4J… I can’t remember which version it was but it doesn’t really matter because the issues I had then still exist today: the bloody thing doesn’t work out of the box, deals with my class loading scheme like it deals with a bad ho’, and the administration tooling provision looks like it could have been built by our friend Neanderthal…

Server configuration

Now I might be a bit overreacting, but what interest is there in releasing an application server onto which you can barely deploy an application? I keep running into “java.lang.OutOfMemoryError: PermGen space”… at least these errors are pretty well known: they happen when the JVM can’t allocate enough space for objects that won’t be garbage collected.

They are also quite easy to circumvent by adding -XX:MaxPermSize=256m to your java command (default is 8m, and you can increase this number as much as you need to and your box - I found that 256m was usually the right figure).

To do that in Oracle Application Server you can go into the EnterpriseManager and in the Administration tab of your OC4J instance, choose “Server Properties” and add a new line with the -XX:MaxPermSize option… done!
If you have OC4J as a standalone instance, you can simply edit the bin/oc4j (or oc4j.cmd on Windows) file and add the -XX:MaxPermSize option directly after the java command.

But you would think that the Oracle guys would have read that kind of documentation (Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine) and implemented sensible parameters so that the server works as best as possible when you start it for the first time, wouldn’t you?

Class loading issues

I am dreaming that one day, some bloke will build a NNWAS (No-Nonsense Web Application Server), where you would be able to deploy you web application without having to worry about the interactions between the class loading tree of your application and that of the container you deploy it upon.

The issue I am talking about is better described in this excellent article (http://www.qos.ch/logging/classloader.jsp). In a few words, the issue arises when one of your libraries (let’s call it high-level library, because it is often a library of abstractions) is attempting to load classes dynamically from a dependent library (the low-level library, containing the implementations), but the JVM has loaded a different copy of your high-level library in a classloader that is a parent of your application’s classloader.

This is depicted in the following diagram: The Server’s High-level library gets loaded first and when it requests the loading of a class in the Low-level library, the class loading mechanism is looking up in the classloaders tree and can’t find it.

Class loading issues diagram

One solution is to add the low-level library in the shared libraries of the server (in effect, pushing it up the tree of classloaders) or removing the high-level library from the server’s installation (in effect, promoting the application’s equivalent library to the right level of classloading in order to reach the low-level library), with all the possible risks that this strategy might incur.

Bad tooling

Finally, I would like to automatically deploy my application on my OC4J container after each Maven build, after each change in the CVS and overnight…
To that effect, Oracle provides a set of Ant tasks to deploy/undeploy the webapp, publish the shared libraries, create DataSources and connection pools, and even restart the server.

However, I wonder why those tools have been developed as Ant tasks if you can’t use them within a build system: the build will fail if you attempt to undeploy a webapp without it being deployed first (same for shared libraries and connection pools), that means you can’t use the same script to install fresh as you would to repeat install!
That also means that if, for some reason (invalid web.xml, missing dependency…), your build breaks during the deployment phase, you can’t simply re-run you build script once the issue is fixed, you also have to put the server in a stable state again manually.
Nearly a deal breaker for continuous integration, but moreover, really annoying when you are in the ramp-up phase of a project!


Situation Normal: All Fu##ed Up

Sphere: Related Content