Thursday, April 12, 2007

Deploying an EJB twice ... :-)

OK. I know that what follows is a terrible mistake. Actually I knew it from the very beginning but I was curious to see what would happen. Here is how it goes: Two web applications were running on jboss for some years on two separate machines in the client 's data center. For ease of management, some time ago, the client requested that the two applications should be deployed on one machine with a single instance of jboss. No problem, I thought at first. After installing jboss 4.0.5 on the new machine and testing the two apps separately, it was about time to put them together. In the past we had some problems with such deployments if the two apps were using common libraries. Jboss documentation suggests that if you have two .ear files that include the same jars, a good practice is to remove the duplicate jars from the ear files and put them in the jboss 's lib folder. Another approach is to set

<attribute name="Isolated">true</attribute>

in the ear-deployer.xml file located in the deploy folder. This means that each ear has its own class loader isolated from other deployments and therefore each ear can have the same jars with the other without conflicts such as ClassCastException, LinkageError, etc.

The problem in our case was that the two web apps were using a unique id generator implemented as a session EJB (let 's call it UniqueIDEJB). This EJB had been developed internally years ago, it was packaged in a jar along with all the necessary deployment descriptors and nobody wanted to mess with it. The first ear that contained the UniqueIDEJB was deployed without problems but when the second app was deployed an error occurred indicating that the UniqueIDEJB was already registered in the jndi under the same name.
No problem, one might think. Just deploy the second instance under a different jndi name. After all, that is what deployment descriptors are for. Remember though that nobody wanted to mess with the legacy EJB, so we chose to remove to jar containing the EJB from the two ear files and deploy it independently.

At first, all went well and the two apps along with the UniqueIDEJB were deployed successfully. However there still was a jar file containing the client stubs of the EJB that was included in both apps. This should not be a problem due to the class loader isolation that we used, but things turned out differently. It seems that when the EJB is deployed, jboss creates some proxies that implement the remote and home interfaces, but when the web app looks the EJB up in jndi and tries to cast the result to the home interface, this home interface is loaded by a different class loader (the one of the web app), therefore a ClassCastException occurres.

Conclusion: Class loader isolation does not help when an EJB is included in several web apps. What one should do is deploy the EJB outside of any ear file and put the client stubs jar in jboss 's lib folder.

1 comment:

Anonymous said...

Thanks a lot. it was really helpful..