WebSphere controls whether applications (EARs and WARs) are in PARENT_FIRST or PARENT_LAST classloading mode by its deployment.xml. RAD, or Rational Application Developer, has tools to generate this, as does the application server itself, but the Eclipse plugins do not at the time of this writing. So how do you configure your applications?
Simply, when your application attempts to load a class, say IOUtils from Apache Commons IO, the JVM needs to know what to do when it finds multiple classes with the same fully qualified name. You could have classes provided by your application server, global JARs that you have put into your application server, and JARs in your application.
_PARENT_FIRST _classloading means take classes found in WebSphere (the parent), or global JARs first. So if you bundle a version of Apache Commons IO that doesn’t match the parent version, your application will run with the parent version instead of your application’s version.
_PARENTLAST classloading means prefer your application’s first.
Imagine this scenario:
- Your servers have global JARs setup that specific applications running in the same WebSphere profile require
- You start a new application in your local development environment and you don’t realize the server has overridden certain JARs
- You bundle newer versions of those JARs in your application
So, with the “It works on my machine” stamp of approval you push to your servers only to find… failure.
There are plenty of other scenarios that could lead to an issue as well.
Unfortunately, there is no silver bullet. You may want to re-evaluate having shared libraries, update their versions, change the classloading mode of your application, or use a different WebSphere profile. The right answer really depends on your environment, but if changing the classloading mode is right for you, read on!
There are a few ways to make this change:
- Deploy your application to WebSphere and update the configuration in the admin console (or wsadmin)
- Use RAD (Rational Application Developer) to change it, if you have RAD
- Or, use a new tool that I’ve created!
To obtain a deployment.xml from WebSphere:
- Build your application as an EAR
- Manually install it to WebSphere (via your admin console at http://localhost:9060/ibm/console for example)
- Open your application in the admin console and configure your EAR’s classloader mode
- Use Manage Modules to configure the WARs’ classloader modes
- Save your changes to WebSphere
- Export your application from the admin console as an EAR
- Copy its ibmconfig with deployment.xml deeply nested in it
Generating deployment.xml in RAD is much easier:
- Right click your EAR
- Go to Java EE -> Open WebSphere Application Server Deployment
- Scroll to the bottom and configure classloader settings as desired
Updating the configuration in WebSphere generates a deployment.xml that you may not want to re-use. Let’s take a look at the differences:
Primarily, the WebSphere version includes node/cell specifics. If you take that version and deploy to a different server, you will end up with new folders in your profile/installedApps directory. This doesn’t cause any issues (that I’ve experienced) but its annoying.
If you take a look at the RAD version, its pretty basic and just lists the applications deployed and which classloading mode they are in. The ids are a standard format with the time after them.
So, assuming you are not using anything else in deployment.xml, this file is easy to reproduce! And to make it easier, I created a command line application to do it for you!
To use it, invoke the JAR, passing it your application.xml as the first parameter, followed by either:
- Nothing (which shows you its menu)
- list (lists the EAR and all web application’s classloading mode)
- set parent first (sets the EAR and all web applications to PARENT_FIRST)
- set parent last (sets the EAR and all web applications to PARENT_LAST)
And that’s it!
If you have any troubles with it, please create a GitHub issue and I’ll take a look!