December 18, 2012

Jax-RS Jersey on WAS 6.1 : ASM ClassReader noSuchMethodException

Today I had to POC a Jersey REST application deployed on a Websphere Application Server 6.1.

At first I had the now classic Hibernate / Jersey exception related to asm dependency :


[13/12/12 14:36:32:296 CET] 00000033 ServletWrappe E   SRVE0100E: Exception init() non intercept?e par le servlet ServletContainer : java.lang.NoSuchMethodError: org/objectweb/asm/ClassReader.accept(Lorg/objectweb/asm/ClassVisitor;I)V
 at com.sun.jersey.server.impl.container.config.AnnotatedClassScanner.analyzeClassFile(AnnotatedClassScanner.java:322)
 at com.sun.jersey.server.impl.container.config.AnnotatedClassScanner.indexDir(AnnotatedClassScanner.java:271)
....
...

The thing is :

  • Hibernate is loading cglib, which in turns loads asm with an old version
  • Jersey needs asm with a newer version, and both version aren't compatibles because of changes in packages.
Solution (that's not from me, it's well documented on the network) :
  • Exclude cglib, asm and asm-attr when declaring hibernate maven dependency (if you're using maven of course)
  • Explicitely declare a dependecy to cglib-nodep. This cglib repackaged artefact includes cglib AND asm, with altered package definition not to conflict with jersey asm version.
So your poms should by now look like this :



   cglib
   cglib-nodep
   2.1_3




   org.hibernate
   hibernate
   
   
   
    
     asm
     asm
    
    
     asm
     asm-attrs
    
    
     cglib
     cglib
    
   





   com.sun.jersey
   jersey-server
   1.1.4.1






So now hibernate is using is own version of asm, and Jersey the 3.11 required version.
So why do I keep getting this error ?

After a few hours struggling with my favorite deployment manager, which I thought was the cause of the issue, I realized that the loaded ClassVisitor class was coming from WAS internal plugins.
After setting a breakpoint and inspecting the classloader, I saw that the class was loaded from this jar : 
C:/Program Files/IBM/SDP70/runtimes/base_v61/plugins/com.ibm.wsfp.main_6.1.0.jar

So what's left to us ?
  • Solution #1 : Delete this jar :-) - Works, but not optimal !
  • Solution #2 : There must be a Websphere setting related to the classloader (PARENT_FIRST vs PARENT_LAST ?), but I can't get it to work (I get exceptions in the was console whenever I try to change those settings).

Anyhow, if anybody knows how to tell Websphere to pick up my jar instead of its jar, please let me know ! Any help would be greatly appreciated.