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.

2 comments:

  1. Hi,

    You can try deploying your application with the detailed options through admin console.

    On the first page you will see an option which reads something like set option for reloading interval, check this option and provide a value in the text box.

    The jars that are required by your application, save it as a shared library and then provide this shared library reference to the concerned module.

    Once the deployment is complete, navigate to the application and open the class loading and update detection hyperlink, from here you can choose the option of PARENT_LAST.

    I hope this helps you.

    Cheers
    Vivek Mittal

    ReplyDelete
  2. Hi Vevek

    Thanks a lot for your answer. I'm not working on this topic anymore, so won't have time to try your solution. Antway, in the end, it looks like the bad jar was loaded by my IDE / application server connector, so I didn't have any problem in production.

    Thanks anyway.

    ReplyDelete