SAAJ Problem

SAAJ Problem
Leave a Comment Posted by azagozdzinski on February 15, 2011

Last days I was struggling trying to find out the reason for error we were receiving occasionaly. The problem was that we couldn’t find the conditions under the error was happening, except that the error was thrown by our WEB_APP. First main suspect was corrupted JDK, but when the same happened on the other server that idea died (how many corrupted JDK can you have? ;) ). So I started digging …

The error message was:

1. java.lang.NoClassDefFoundError: Could not initialize class com.sun.xml.internal.ws.api.BindingID

That class is included in rt.jar – that ’s why the first suspect was JDK.

Lucky for me we had historical logs so I could trace last error occurences. The finding was that the error above is sometimes preceded with another one:

2. java.lang.IllegalArgumentException: com.sun.xml.messaging.saaj.soap.LocalStrings != com.sun.xml.internal.messaging.saaj.soap.LocalStrings

It was not always a rule, but it looked like there was at least one occurence of error [2] followed by many errors [1]. So I decided to investigate the second one.

That error is thrown by java.util.logging.Logger.getLogger(String paramString1, String paramString2) method where paramString2 is resource bundle name.

Implementation:

/* */ public static synchronized Logger getLogger(String paramString1, String paramString2)
/* */ {
/* 308 */ LogManager localLogManager = LogManager.getLogManager();
/* 309 */ Logger localLogger = localLogManager.demandLogger(paramString1);
/* 310 */ if (localLogger.resourceBundleName == null)
/* */ {
/* 312 */ localLogger.setupResourceInfo(paramString2);
/* 313 */ } else if (!(localLogger.resourceBundleName.equals(paramString2))) {
/* 314 */ throw new IllegalArgumentException(localLogger.resourceBundleName + " != " + paramString2);
/* */ }
/* */
/* 317 */ return localLogger;
/* */ }

In our case that means that there is an attempt to create new logger with resource bundle ‘com.sun.xml.internal.messaging.saaj.soap.LocalStrings’, while there is already another one created for the same class, but with resource bundle ‘com.sun.xml.messaging.saaj.soap.LocalStrings’.

I digged into libraries and found that the logger is being created by implementation class SAAJMetaFactoryImpl.

That class can be found in (at least) two places:

1. rt.jar: com.sun.xml.internal.messaging.saaj.soap.SAAJMetaFactoryImpl

protected static final Logger log = Logger.getLogger("javax.xml.messaging.saaj.soap", com.sun.xml.internal.messaging.saaj.soap.LocalStrings");

1. saaj-impl-X.X.jar: com.sun.xml.messaging.saaj.soap.SAAJMetaFactoryImpl

protected static final Logger log = Logger.getLogger("javax.xml.messaging.saaj.soap", "com.sun.xml.messaging.saaj.soap.LocalStrings");

First one is a part of JDK installation while second one is part of one of our applications EAR (saaj-impl-1.3.2.jar). For this description sake, let’s call it OUR_SERVICE_APP.

I had another, closer look on stack traces and the puzzles started to fit.

First error stack looks as follows:

Caused by: java.lang.ExceptionInInitializerError
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at java.lang.Class.newInstance0(Class.java:355)
at java.lang.Class.newInstance(Class.java:308)
at javax.xml.soap.FactoryFinder.newInstance(FactoryFinder.java:59)
at javax.xml.soap.FactoryFinder.find(FactoryFinder.java:186)
at javax.xml.soap.SAAJMetaFactory.getInstance(SAAJMetaFactory.java:79)
at javax.xml.soap.MessageFactory.newInstance(MessageFactory.java:148)
at com.sun.xml.internal.ws.api.SOAPVersion.<init>(SOAPVersion.java:167)
at com.sun.xml.internal.ws.api.SOAPVersion.<clinit>(SOAPVersion.java:72)
at com.sun.xml.internal.ws.api.BindingID.<clinit>(BindingID.java:324)
at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parseBinding(RuntimeWSDLParser.java:413)
at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parseWSDL(RuntimeWSDLParser.java:310)
at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:135)
at com.sun.xml.internal.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:254)
at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:217)
at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:165)
at com.sun.xml.internal.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:93)
at javax.xml.ws.Service.<init>(Service.java:56)
at our.web_app.webserviceclient.ClientService.<init>(ClientService.java:xx)
... 13 more
Caused by: java.lang.IllegalArgumentException: com.sun.xml.messaging.saaj.soap.LocalStrings != com.sun.xml.internal.messaging.saaj.soap.LocalStrings
at java.util.logging.Logger.getLogger(Logger.java:314)
at com.sun.xml.internal.messaging.saaj.soap.SAAJMetaFactoryImpl.<clinit>(SAAJMetaFactoryImpl.java:41)
... 51 more

That means that our WEB_APP invocation for ClientService encounters problem while trying to init class SAAJMetaFactoryImpl because there is the same logger with different resource bundle in memory already. Logger created by SAAJMetaFactoryImpl class as ‘side effect’ of OUR_SERVICE_APP is static and final, so it considered as constant object kept in memory since SAAJMetaFactoryImpl class has been initiated by OUR_SERVICE_APP.

Anyway, the stack trace above shows that the RuntimeWSDLParser.parseBinding method tries to init class BindingID which in turn initiates number of other classes. Finally it tries to obtain implementation for SAAJMetaFactory interface and finds com.sun.xml.internal.messaging.saaj.soap.SAAJMetaFactoryImpl that in turn throws an exception while getting static Logger object reference.

That means that it fails on initialization of BindingID class.

RuntimeWSDLParser.parseBinding(RuntimeWSDLParser.java:413) source code:

Line 413: binding.setBindingId(BindingID.SOAP11_HTTP);

Where BindingID.SOAP11_HTTP is constant that represents SOAP1.1/HTTP.

And here we are with the second error:

java.lang.NoClassDefFoundError: Could not initialize class com.sun.xml.internal.ws.api.BindingID
at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parseBinding(RuntimeWSDLParser.java:413)
at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parseWSDL(RuntimeWSDLParser.java:310)
at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:135)
at com.sun.xml.internal.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:254)
at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:217)
at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:165)
at com.sun.xml.internal.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:93)
at javax.xml.ws.Service.<init>(Service.java:56)
at our.web_app.webserviceclient.ClientService.<init>(ClientService.java:xx)
{…}

Initialization of BindingID class failed at first error so this class definition has been unloaded from memory. Result: JVM (or class loader) throwing NoClassDefFoundError.

The open question is why it is working sometimes without such collision. What we know is that problem takes place when OUR_SERVICE_APP has been invoked before our WEB_APP. My hints here are:

- It can be specific feature implemented in OUR_SERVICE_APP service that calls com.sun.xml.messaging.saaj.soap.SAAJMetaFactoryImpl implementation and loads static Logger object in memory. That feature can be rarely used, so there are shorter or longer periods of time where WEB_APP could be used without problems.

- Even if the Logger has been loaded – Garbage Collector removes it after some time from memory. WEB_APP can be invoked again…

- If WEB_APP has been invoked as first – classes from rt.jar are loaded into ‘clean’ memory without problems. OUR_SERVICE_APP uses then classes that JVM / class loader has loaded already, so implementation from saaj-impl-1.3.2.jar included in service’s EAR is not used. Both applications are working fine.

- If OUR_SERVICE_APP has been invoked first – it loads classes from saaj-impl-1.3.2.jar library and if Garbage Collector didn’t unload them, WEB_APP invocation leads to an error.

Anyway – the solution is to get rid of saaj-impl-1.3.2.jar and saaj-api-1.3.jar libraries from OUR_SERVICE_APP and ‘force’ it to use rt.jar / JDK implementations instead.
Troubleshooting BindingID, com.sun.xml.internal.messaging.saaj.soap.LocalStrings, com.sun.xml.internal.messaging.saaj.soap.SAAJMetaFactoryImpl, com.sun.xml.internal.ws.api.BindingID, com.sun.xml.messaging.saaj.soap.LocalStrings, com.sun.xml.messaging.saaj.soap.SAAJMetaFactoryImpl, java.lang.IllegalArgumentException: com.sun.xml.messaging.saaj.soap.LocalStrings != com.sun.xml.internal.messaging.saaj.soap.LocalStrings, java.lang.NoClassDefFoundError: Could not initialize class com.sun.xml.internal.ws.api.BindingID, javax.xml.messaging.saaj.soap, saaj-api-1.3.jar, saaj-impl-1.3.2.jar
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值