I used to be.. on Tomcat7 - The classloader magic world of a Monolith
I know that many of you probably don't use Tomcat for your applications deployment, but as you know there are tons of systems that currently run on this specific Application Server.
Most of the existing Monoliths around the world are deployed on Tomcat (or Weblogic or whatever) where the classloader is - of course - managed by the Application Server itself.
THE PROBLEM
We have this very old application that is working without any problem on Tomcat7. This application has an extensive use of class scanning due to Jaxb implementation that search on every Jar file and create a JaxbContext of known classes.
There was a request from customer to move the application from Tomcat7 to other Tomcat8 or Tomcat9, because the seven is out of standard for the company.
Ehi: there are no problem. There are just fews properties in catalina.properties that we need to copy and "le jeux sont faits", we can easily deploy. And this is was we did but...
Wait....whaaaaaat????? we have the correct ObjectFactory and there are no problems in old tomcat..what the hell is going wrong?
TOO MUCH CLASSES
If we looked at the jar inside the war, we can see more than 100 jar..which is of course not a problem..except for the fact that many of this jars are created by us. And many of this jars have similar packages and similar class names (there are some external services that uses xsd to build java classes..and there are a big problem of naming convention and fantasy..)
So why for Tomcat7 there are no problems, while for Tomcat8 and Tomcat9 it doesn't work? As we said before, Jaxb scans all the jar from classloader, so if you have any problem, usually it is the classloader that is working different.
Another strange thing is that using Docker, Tomcat8 and Tomcat9 works without problem, while using it in the client Virtual Machine, we had the problem.
All of the classes we need to scan are in WEB-INF/lib so - from a pure folder perspective - there is any problem on that: the same classes we had in Tomcat7 now we have in new Tomcats.
But the problem is not about "NoClassDefFoundError", so it is not a problem on which class they are inspecting, but probably the order in which they are inspecting.
And if you see the changelog in Tomcat8 and Tomcat9, they don't load using alphabetical order, they use the order that the O.S. implements.
This is also why the application works on Docker and not in the Client's VM: the O.S. is of course different and probably the Image we used locally, apply an alphabetical order, which bypasses the error.
THE SOLUTION
There is no other way to solve this problem than.. modify Tomcat. As you know Tomcat is open source, so you can download the src and - using Ant - build your own version if you need to modify something.
There are 2 points in the code where lib is scan: StandardRoot on method list and DirResourceRes on listWebAppPaths. We need to force the order here
So using ant, the entire tomcat is rebuilt under output/build folder.
We changed just classes into catalina, so we just need to change catalina.jar and that's it!
Everything worked perfectly!
CONCLUSION
When we deal with old applications, we face this type of problems, where the order of application will change the behaviour of your code.
There are too much collisions on your class name and this can impact the execution.
This is why we now tend to develop small applications, where the number of jar we will load is very tiny and there will be no problem on classloading. Because this should not be a problem: you application should not depend on the order you load the class.
But hey.. there is always a solution!
Commenti
Posta un commento