users@glassfish.java.net

Glassfish and Bouncy Castle having issues after EAR redeploy

From: <glassfish_at_javadesktop.org>
Date: Wed, 01 Apr 2009 21:54:28 PDT

I've got an annoying issue here:

I use WSS4J as part of my application (as far as I'm aware, it's not a part of Glassfish, and thus I need to include it, and it's dependencies, as libraries), and it requires Bouncy Castle.

Quick bit of background: My application is an EAR containing two WAR files - one for a web application, the other a single Web Service servlet endpoint. Running Glassfish V2 UR2, Java 1.5, Ubuntu 7.10.

The problem I'm having stems from including BC as a library in my application, and doing multiple application undeploy/redeploys between server restarts.

I was tracking what classes were registered as Security providers when my application starts up, before it calls into WSS4J (and thus into BC). Initially, it lists only those ones that appear in the java.security file in $JAVA_HOME/jre/lib/security/ directory. However, after the first run of my code, it then adds another provider - BC 1.42. Ok, so BC adds itself as a provider. Seems sensible enough.

I can then continue to make SOAP requests back and forth until I find a bug in my code, at which point I need to undeploy and redeploy my application. If I then try to validate a webservice request (after this deploy), something throws a fit about being unable to find one of the BC classes (stack trace below). But that's very strange - it could find them before the deploy, and I haven't moved the bcprov.*.jar file anywhere, so all the classes are still there, and I can call them without issue. So why can't it find them?

I suspect, and I could be totally off track here, that Glassfish does something funny internally with the classloaders when an application is undeployed, as the code worked fine up until then. I'm not really sure how this security stuff works in Java, in all honesty, so could it be related to the fact that BC is *not* set as a provider when my application is first launched, but it *is* set as a provider when I redeploy my application? The Security Providers obviously being system-wide and held at the Glassfish level, rather than the level of any single application.

Only reason I think it's a strange classloader issue is that in the stacktrace below it's obviously managed to find BC's JDKKeyFactory, which makes me wonder why the hell it can't find all the other BC classes?

<ns2:cause class="java.lang.NoClassDefFoundError" note="To disable this feature, set com.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace system property to false">
<message>org/bouncycastle/asn1/x509/SubjectPublicKeyInfo</message>
<ns2:stackTrace>
<ns2:frame class="org.bouncycastle.jce.provider.JDKKeyFactory" line="unknown" method="createPublicKeyFromDERStream"/>
<ns2:frame class="org.bouncycastle.jce.provider.JDKKeyFactory" line="unknown" method="engineGeneratePublic"/>
<ns2:frame class="org.bouncycastle.jce.provider.JDKKeyFactory$RSA" line="unknown" method="engineGeneratePublic"/>
<ns2:frame class="java.security.KeyFactory" file="KeyFactory.java" line="284" method="generatePublic"/>
<ns2:frame class="sun.security.x509.X509Key" file="X509Key.java" line="206" method="buildX509Key"/>
<ns2:frame class="sun.security.x509.X509Key" file="X509Key.java" line="153" method="parse"/>
<ns2:frame class="sun.security.x509.CertificateX509Key" file="CertificateX509Key.java" line="58" method="&lt;init>"/>
<ns2:frame class="sun.security.x509.X509CertInfo" file="X509CertInfo.java" line="690" method="parse"/>
<ns2:frame class="sun.security.x509.X509CertInfo" file="X509CertInfo.java" line="152" method="&lt;init>"/>
<ns2:frame class="sun.security.x509.X509CertImpl" file="X509CertImpl.java" line="1708" method="parse"/>
<ns2:frame class="sun.security.x509.X509CertImpl" file="X509CertImpl.java" line="179" method="&lt;init>"/>
<ns2:frame class="sun.security.provider.X509Factory" file="X509Factory.java" line="90" method="engineGenerateCertificate"/>
<ns2:frame class="java.security.cert.CertificateFactory" file="CertificateFactory.java" line="271" method="generateCertificate"/>
<ns2:frame class="sun.security.provider.JavaKeyStore" file="JavaKeyStore.java" line="745" method="engineLoad"/>
<ns2:frame class="java.security.KeyStore" file="KeyStore.java" line="1150" method="load"/>
<ns2:frame class="org.apache.ws.security.components.crypto.AbstractCrypto" file="AbstractCrypto.java" line="140" method="load"/>
<ns2:frame class="org.apache.ws.security.components.crypto.AbstractCrypto" file="AbstractCrypto.java" line="116" method="&lt;init>"/>
<ns2:frame class="org.apache.ws.security.components.crypto.Merlin" file="Merlin.java" line="71" method="&lt;init>"/>
<ns2:frame class="sun.reflect.NativeConstructorAccessorImpl" file="NativeConstructorAccessorImpl.java" line="native" method="newInstance0"/>
<ns2:frame class="sun.reflect.NativeConstructorAccessorImpl" file="NativeConstructorAccessorImpl.java" line="39" method="newInstance"/>
<ns2:frame class="sun.reflect.DelegatingConstructorAccessorImpl" file="DelegatingConstructorAccessorImpl.java" line="27" method="newInstance"/>
<ns2:frame class="java.lang.reflect.Constructor" file="Constructor.java" line="494" method="newInstance"/>
<ns2:frame class="org.apache.ws.security.components.crypto.CryptoFactory" file="CryptoFactory.java" line="211" method="loadClass"/>
<ns2:frame class="org.apache.ws.security.components.crypto.CryptoFactory" file="CryptoFactory.java" line="93" method="getInstance"/>

However, the above error isn't always thrown when I redeploy my application... Here's a few examples of when it does or doesn't do it:

Application is currently deployed and working fine. BC is in the EAR's lib folder, as is Xalan 2.6.0 (Xalan is also present in Glassfish's lib dir as well). Undeploy EAR. Recompile/Redeploy. Generates above error. Need to restart Glassfish before it will work again.

Application is currently deployed and working fine. BC is in the EAR's lib folder, Xalan 2.6.0 is only present in Glassfish's lib dir. Undeploy EAR. Recompile/Redeploy. Everything works as expected - no errors at all.

Application is currently deployed and working fine. BC is in the EAR's lib folder, Xalan 2.6.0 is only present in Glassfish's lib dir. Undeploy EAR. Recompile/Redeploy, but with Xalan present in the EAR this time, as well as in the GF lib dir. Boom - above error message.

Application is currently deployed and working fine. BC is in the EAR's lib folder, as is activation.jar. Undeploy EAR. Recompile/Redeploy, but without activation.jar Generates above error. Need to restart Glassfish before it will work again.

I'm well and truely confused by this behaviour, but it seems to only occur when there has been a change in the lib set of libraries present in my application (or possibly the code base as a whole). Anyone have any suggestions, any suggestions at all, as to why this is occuring and some way of fixing it? I've got a really bade feeling that I'm doing a lot things wrong here or something, but I have no idea what. :-(

Thanks all,

- Andrew Thorburn
[Message sent by forum member 'ipsi' (ipsi)]

http://forums.java.net/jive/thread.jspa?messageID=340157