WAS 8.5.5. web app getting NoSuchFieldError during startup

I have a maven web app, using WAS 8.5.5.

On app startup I'm getting the following error:

Caused by: java.lang.NoSuchFieldError: org/apache/http/message/BasicLineFormatter.INSTANCE

This means there's some sort of mismatch of jars (httpclient & httpcore) in my classpath.

To get more info, I ran the following code:

ClassLoader classLoader = Test.class.getClassLoader();
URL resource = classLoader.getResource("org/apache/http/message/BasicLineFormatter.class");
log.info("Outputting resoure info: " + resource.getFile() + " " + resource.getPath() + " " + resource.getRef());
          try {
                 log.info(FileLocator.resolve(resource));
                 log.info(FileLocator.toFileURL(resource));
          } catch (IOException e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
          }

This gave me the following output:

start Outputting resoure info: /org/apache/http/message/BasicLineFormatter.class /org/apache/http/message/BasicLineFormatter.class null start jar:file:/C:/RAD9.0/IBM/WebSphere/AppServer_2/plugins/com.ibm.ws.prereq.jaxrs.jar!/org/apache/http/message/BasicLineFormatter.class start file:/C:/RAD9.0/IBM/WebSphere/AppServer_2/profiles/AppSrv01/servers/server1/configuration/org.eclipse.osgi/bundles/105/1/.cp/org/apache/http/message/BasicLineFormatter.class

These are both obviously loaded to WAS on startup. How do I stop this from happening? I tried changing the priority of the module loading in the app settings by setting load parent last, but that stopped the app from coming up at all.

Any ideas?

Upvotes: 2

Views: 3441

Answers (2)

cwash
cwash

Reputation: 4245

You can also see where the offending class is loaded from using the Class Loader Viewer and searching for it. You have to enable this first by clicking Servers > Server Types > WebSphere application servers > server_name > Class loader viewer service, enable the service and restart the server.

enter image description here

As a quick fix, without having to switch to PARENT_LAST and create a shared library, I copied the JAR file from my .m2/repo folder to the AppServ/lib directory.

> cp C:\path\to\your\.m2\repository\org\apache\httpcomponents\httpcore\4.3.3\httpcore-4.3.3.jar "C:\Program Files (x86)\IBM\WebSphere\AppServer\lib"  

Then I added an entry to the JVM classpath within the server console:

Open https://localhost:9043/ibm/console and go to:

Servers > Server Types > WebSphere application servers > server_name. Then, in the Server Infrastructure section, click Java and process management > Process definition > Java virtual machine

Then enter the following under "Classpath"

C:\Program Files (x86)\IBM\WebSphere\AppServer/lib/httpcore-4.3.3.jar

Use a semicolon to separate entries.

Restart to retest.

Upvotes: 3

Alasdair
Alasdair

Reputation: 3176

It looks like you have a library in your application at a newer version than a copy in the application server so you end up with a mix of classes visible to your application. As you notice this is a bad thing.

There are a few ways to get around this, but the simplest is to change the classloader order to load classes from your application before the runtime. You can do this in the admin console by navigating to the application, selecting classloading and choosing the radio button labeled Classes loaded with local class loader first (parent last).

If you do this though you should make sure you don't include the Java EE packages in your application though (that sometimes happens with maven built applications).

Upvotes: 2

Related Questions