Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17


JBoss : Deployment options of shared code

Posted on 2003-11-19
Medium Priority
Last Modified: 2007-12-19
We have a set of common libraries (utilities classes, Hibernate beans) that are used by multiple different J2EE applications. With Weblogic, each application is an EAR file that contains all of its JARs, plus a manifest in the EJB JAR. This works quite nicely. Each application is independent from the rest, which means that we can apply patches to individual applications on our production server, we can hot deploy the entire application, etc.

In JBoss, the default classloader architecture seems to encourage putting all the shared stuff in the [server]/lib folder. However, if I understand correctly, this code will not be hot-deployable, which really defeats the purpose of using a container in my mind (the whole reason I am learning JBoss is because I am fed up with Weblogic's unreliability while hot-deploying).

So, I tried building my EARs with a jboss-app.xml which creates a separate classloading context for each application. I was happy and thought this was working nicely, until I tried an application which looks up Home interfaces from the global JNDI namespace. What happened then is that the objects in JNDI were implementing separately loaded instances of the RemoteHome and RemoteSession interfaces, so PortableRemoteObject.narrow threw ClassCastException. I attempted to work around this problem by trying to figure out how to make JBoss use a non-JNP connection to JNDI, but I don't see a way to do this other than the HTTP invoker. Using the HTTP invoker inside the container is a big hack, but I decided to try it anyway; unfortunately this approach also failed (stack trace below).

So now I am 100% stuck. I can't deploy everything in [server]/lib, because then it won't hot deploy (right?). I also can't deploy everything in their own classloaders, because then I can't use remote Session beans through JNDI.

Surely people do stuff like this all the time. What is the right answer for my deployment situation? I have learned a lot about JBoss, and that is good. But I am ready for it all to start working now.

All this code is currently in production on a Weblogic server, so whatever my problems are they are JBoss-specific.

- kevin

Attempt to use HTTP JNDI provider:

12:41:44,986 WARN [HttpNamingContextFactory] Invalid reply content seen: class
at org.jboss.invocation.http.servlet.InvokerServlet.processRequest(Invok
Question by:kgilpin
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4

Expert Comment

ID: 9782892
Since each class is loaded in its own EAR, are you sure you have the same version of the remote interface and home interface in the EAR file of the calling EJB and the component itself?
Did you try to remove the jboss-application.xml and see what happens?

Author Comment

ID: 9783674
Each app definitely has the same version of the class, because both EARs package the same JAR file (Base.jar).

If I remove the jboss-app.xml, then this part of the application works. But I get LinkerErrors (in Struts) when I hot deploy. Even if I didn't get LinkerErrors, I still would want to use the jboss-app.xml, because it is important to me to be able to independently replace the JAR files in the different applications. If I want to fix a bug in one application, I don't want to have to verify that all the other applications will work with the patched code.

I believe my problem could be reproduced in a simple manner. First, write a remote Home and Session interface. Package these interfaces into Base.jar. Then, write an EJB 'A' which implements these interfaces, and package it into A-ejb.jar. Then put both Base.jar and A-ejb.jar in an EAR file, along with a Class-Path in the manifest of A-ejb.jar that references Base.jar, and a jboss-app.xml. Next, write another EJB or web application that also packages Base.jar and also has a jboss-app.xml. This application should look up A using its global JNDI name and try to PortableRemoteObject.narrow it to the Home interface. This will fail with ClassCastException in JBoss; works fine in Weblogic 7.

Removing the jboss-app.xmls will enable application B to use bean A, but it will prevent A and B from being hot-deployable if something in Base.jar changes.

Expert Comment

ID: 9788189
Can you put a log command that will detail the type of class you are getting? Try to remove the narrow command, and maybe do something like this:

Object o = ic.lookup("...");

The way I see it, either you ahve a faulty versioning of the class file (maybe the classpath is not configured correctly, and you are actually getting a class from someplace else - either the EJB returns something weird or your code classpath is broken) or that JBoss is trying to move the object in memory (since both files are deployed on the same server), doesn't notice that the classloader that loaded the classes is different, and then JBoss breaks.

I guess you are using JBoss 3.2.2, as this is a relatively new feature.
Free learning courses: Active Directory Deep Dive

Get a firm grasp on your IT environment when you learn Active Directory best practices with Veeam! Watch all, or choose any amount, of this three-part webinar series to improve your skills. From the basics to virtualization and backup, we got you covered.


Author Comment

ID: 9788304
I have put in such a log command. Specifically, what I did was print out

  Arrays.asList( o.getClass().getInterfaces() )

The o.getClass() is a Proxy class which doesn't tell you much about what it really is. The getInterfaces() prints out the remote Session interface that I expect the object to implement.

I am quite sure that the problem is that JBoss is assuming that it can, as you say, move the object in memory, not realizing that the client and the bound object implement 2 instances of the same interface, loaded in different ClassLoaders.

Author Comment

ID: 9788357
I have submitted a bug report to JBoss:

I will award the points for a workaround which solves the ClassCastException problem, or some demonstration that what I am seeing is not a JBoss bug. It would also be great to see someone reproduce this problem so I know that I am not misinterpreting what I am seeing.

Expert Comment

ID: 9790513
Since this is a new feature in JBOss class loading mechanism, and some guys from my company run into similar (but not the same) issues, I guess that the best thing to do is not to use the different class loaders in JBoss, but use a single one for all EAR files.
If you have issues with that, put the shared files inside the lib directory. they shouldn't change much anyway.
IDEA - how about putting the JAR file externally, encapsulate all needed business logic using EJBs, and then deploy just this JAR file?
This way, all EAR files can use this EJB, it is hot deployed, deployed only once.

Expert Comment

ID: 9816542
kgilpin, was this helpful?

Author Comment

ID: 9817206
Well, I need to be able to hot deploy everything. The problem with sharing a JAR file across EARs is that if I change something in that JAR file, I may potentially break every application. So I have to test every application before I deploy the change. If each application has its own copy of the shared JAR, I only need to test the one application that I am re-deploying.

I guess I didn't quite catch the meaning of your idea. Do you mean that the shared code would all be in an EAR file, and each application would access the shared code in this EAR file? Or will JBoss deploy a JAR file for me and allow me to hot-deploy that JAR? If the shared code is in an EAR, do I have to access all its functionality through EJB interfaces, or can I simply import classes from it and know that they will be available in the classpath? How are the other applications affected when the shared EAR/JAR is re-loaded? They will still have references to the old classes. Thanks for the follow-up.

Accepted Solution

vzilka earned 2000 total points
ID: 9817917
My idea is to deploy the common EJB as a single JAR file. This will imply of course that you need to check all the applications with the new JAR file.
As for the classpath thing - EAR files deployed in JBoss are not using other EAR files as their classpath.

This problem is so much DLL-hell that it gives me the creeps ;-)

Featured Post

Will your db performance match your db growth?

In Percona’s white paper “Performance at Scale: Keeping Your Database on Its Toes,” we take a high-level approach to what you need to think about when planning for database scalability.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Convert websphere application server default chained Certificates from 1024 to 2048 keysize or higher size and also you can change signatureAlgorithm . Please make sure Websphere Application Server fixpack or Above. The following steps a…
Meet the world's only “Transparent Cloud™” from Superb Internet Corporation. Now, you can experience firsthand a cloud platform that consistently outperforms Amazon Web Services (AWS), IBM’s Softlayer, and Microsoft’s Azure when it comes to CPU and …
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…
In this video, Percona Solution Engineer Rick Golba discuss how (and why) you implement high availability in a database environment. To discuss how Percona Consulting can help with your design and architecture needs for your database and infrastr…
Suggested Courses

715 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question