7

If the class to override is called com.example.FooServlet and this class is inside a jar WEB-INF/lib/foo.jar, how to override it with a class also called com.example.FooServlet in another jar, say bar.jar?

Or is there any way to make sure the one in bar.jar is loaded first?

Making bar.jar a module is no-go because the FooServlet imports tons of classes from many jars in WEB-INF/lib.


As I stated above, I tried to contain bar.jar in a module, but got class not found or no class def error (can't remember clearly) as FooServlet extends/implements some extra classes/interfaces which are in 3rd party jars in WEB-INF/lib.

I'm not allowed to touch foo.jar or any of the jars that are already existing in WEB-INF/lib.

Dante WWWW
  • 2,729
  • 1
  • 17
  • 33

3 Answers3

3

You said you cannot touch existing jars, and you seem to imply you can add a jar of yours to WEB-INF/lib.

According to this:

  • there is no specified order of precedence for jars under WEB-INF/lib/*.jar.
    So if you add bar.jar in there, you don't know if it will be loaded before or after foo.jar.
  • the servlet spec says classes under WEB-INF/classes must be loaded before anything under WEB-INF/lib/*.jar

Assuming you can add a jar under WEB-INF/lib, you should be able to add a class (or several) under WEB-INF/classes, without touching the ones in place.
So, if you want the classes from bar.jar to be loaded first, you can unzip the contents of that jar under WEB-INF/classes instead (or just the class you want to be loaded in priority -- for example WEB-INF/classes/com/example/FooServlet.class).

Hugues M.
  • 19,846
  • 6
  • 37
  • 65
1

look at JBoss modules and how to handle them through jboss-deployment-structure.xml deployment descriptors.

It is simple...

For 2 different WAR files you can have 2 different modules having different com.example.FooServlet in different jars files each.

You just need to take your foo.jar and boo.jar files out of WAR file and add them to the appropriate modules.

ClassLoader for WAR picks needed class(es) from modules you define in jboss-deployment-structure.xml and never clashes with other versions.

Vadim
  • 4,027
  • 2
  • 10
  • 26
  • First, due to restriction I can't extract `foo.jar` from the WAR and make it a module; second, I tried to contain `bar.jar` in a module, but got class not found or no class def error (can't remember clearly). `FooServlet` extends/implements some extra classes/interfaces which are in 3rd party jars in WEB-INF/lib, and I can't extract them. – Dante WWWW Aug 21 '17 at 05:37
  • h-m-m... first - it means you problem is in that restrictions - and question is about them. Maybe the can be changed to achieve goal in simple, standard way? second - is about you do something not quite right with modules. Actually It works perfectly. I also have tons of 3-rd party jar files. – Vadim Aug 21 '17 at 11:47
  • Perhaps you need to move some 3-rd party jars out of WAR to the your module as well... Otherwise probably there is a way to manipulate class loaders on your own, but... i'm pretty sure it needs to much work and there will be much more unknown yet challenges.. still I suggest you to reconsider restrictions and make module approach work. It definitely does what you need. – Vadim Aug 21 '17 at 11:48
1

Java Agent Consideration

Assuming you have full control on how JBoss is being started, or at least you can change JBoss startup settings - the thing which comes to your help is Java agent.

In a nutshell Java agent is a custom 'plugin' jar to a JVM, and it can intercept loading of each and any class by that JVM. And - just what you need - it can perform substitution of byte code of any intercepted class. Further reading about Java agent concept

The goal you're trying to achieve isn't brand new, and seems it has already been resolved at some level. Check out this question as well as answer - it looks like there is almost full guide about writing the agent which replaces classes based on provided external jar with replacements.

The High-Level Plan

  1. Have your java agent developed, its jar compiled and placed near your bar.jar (as agent will read bar.jar directly)
  2. Edit JBoss startup command line to include -javaagent:/path/to/your/agent.jar
  3. Now during JBoss startup, your agent will replace each class by corresponding one if it is present in your provided bar.jar

The things may become a bit more complex depending on your JBoss version and deployment model, but there are some guides for popular agents installation which can be easily adapted to our case

Community
  • 1
  • 1
Kostiantyn
  • 1,856
  • 11
  • 13