TomEE - How does ClassLoader load from 3 webapps

160 Views Asked by At

I am working on deploying some of the existing web services to Apache TomEE 8. I have three webapps(EAR files) to deploy. I tried deploying each one of them independently and they are working fine and the class loader is able to load the necessary classes for that particular app.

But, when I try to deploy all three of them together, only one of the webapp is working properly and rest of the two are throwing internal server errors. When I look at the server logs, I see java.lang.ClassNotFoundException:com.example.classname for the other two apps, But, when I go to TomEE-8/webapps/app1/WEB-INF/classes/ , I am able to see the class that the exception is being thrown for.

So my question is How do I isolate classloader for each of the app and deploy all the three EARs together? I am new to Tomcat and TomEE and having a hard time figuring this out.

Below is my TomEE's directory structure for deployment:

  1. For app1 - TomEE/webapps/app1/WEB-INF/classes/com/example/app1class1.class
  2. For app2 - TomEE/webapps/app2/WEB-INF/classes/com/example/app2class1.class
  3. For app3 - TomEE/webapps/app3/WEB-INF/classes/com/example/app3class1.class

I have a common library common.jar, which the classloader should use for class loading, and I have placed in TomEE/lib. Rest of the configuration is the same as provided during installation.

For deployment, I am placing app1.ear, app2.ear and app3.ear files in the webapps directory and starting the server.

I expected all the three web services to be running but only one of them was running, presumably which was deployed first and the rest two are throwing java.lang.ClassNotFoundException. Can someone please help me with this? I have been trying to find any related issues and was not find any.

Edit-1:

Previous Liberty Server configuration:

<applicationManager autoExpand="true"/>
    <library id="commonlib"><fileset dir="path/to/common.jar"/></library>

    <application location="path/to/app1.ear" id = "app1.ear"
    name="app1.ear" type="ear"><classloader commonLibraryRef="commonlib"/></application>

    <application location="path/to/app2.ear" id = "app2.ear"
    name="app2.ear" type="ear"><classloader commonLibraryRef="commonlib"/></application>

    <application location="path/to/app3.ear" id = "app3.ear"
    name="app3.ear" type="ear"><classloader commonLibraryRef="commonlib"/></application>
2

There are 2 best solutions below

0
noobboi On BEST ANSWER

I was making a silly mistake in providing the same ID to all the webapps in the WEB-INF/web.xml file. Because of this, TomEE is deploying the first app and since the second app is also having the same ID in web.xml, it is trying to find the class in the WEB-INF/classes folder of the first deployed app. Resolved by providing unique IDs to all the apps in the web.xml

3
Romain Manni-Bucau On

TomEE follows a tree classloading. You can see the inherited tomcat one there (https://tomee.apache.org/tomee-8.0/docs/developer/classloading/index.html) then for your app you get a common classloader (child of tomcat) and then one webapp classloader per webapp (child of common).

So you just have to put common in yourear/lib folder (see library-directory from application.xml for example - or something equivalent) and it should be fine.

If you intend to use common.loader to share your common jar you must also put its dependencies in tomcat/lib and just deploy the webapps as webapps and not as an ear.

Last note: you likely need to configure tomee.xml to enable ear deployment in apps/ and not use webapps/ which has a specific handling if not already done (theorically it should work but it has side effects so better to stay off it). You can also review https://tomee.apache.org/tomee-8.0/docs/deployments.html if you prefer - it proposed alternative configurations.

What can happen if a common lib class can't be loaded so the webapp class can't be loaded transitively i nyour case.