miércoles, 21 de julio de 2010

Classloading issues when working with Procrun and Prunsrv (Apache Commons Daemon)

I was trying to configure a standalone Java program to run as a Windows service (an standalone Web service client using Axis2) using Apache Commons Daemon.

I used a great post by Christopher Pierce as guide: http://blog.platinumsolutions.com/node/234

The program ran OK when I launched it from the command line console, but when I tried to run it as a Windows service with exactly the same configuration (jvm, classpath, etc.), the program failed with errors like these:

for Java 6:
java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at javax.xml.ws.spi.FactoryFinder.safeLoadClass(FactoryFinder.java:148)
at javax.xml.ws.spi.FactoryFinder.newInstance(FactoryFinder.java:30)
at javax.xml.ws.spi.FactoryFinder.find(FactoryFinder.java:128)
at javax.xml.ws.spi.Provider.provider(Provider.java:83)
at javax.xml.ws.Service.init(Service.java:56)
at javax.xml.ws.Service.create(Service.java:691)
at ...
Caused by: javax.xml.ws.WebServiceException: Error creating JAXBContext for W3CEndpointReference.
at com.sun.xml.internal.ws.spi.ProviderImpl$2.run(ProviderImpl.java:211)
at com.sun.xml.internal.ws.spi.ProviderImpl$2.run(ProviderImpl.java:206)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.xml.internal.ws.spi.ProviderImpl.getEPRJaxbContext(ProviderImpl.java:206)
at com.sun.xml.internal.ws.spi.ProviderImpl.clinit(ProviderImpl.java:77)
... 13 more
Caused by: javax.xml.bind.JAXBException
- with linked exception:
[java.lang.ClassNotFoundException: com/sun/xml/bind/v2/ContextFactory]
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:187)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:363)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:522)
at com.sun.xml.internal.ws.spi.ProviderImpl$2.run(ProviderImpl.java:209)
... 17 more
Caused by: java.lang.ClassNotFoundException: com/sun/xml/bind/v2/ContextFactory
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at javax.xml.bind.ContextFinder.safeLoadClass(ContextFinder.java:479)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:185)
... 21 more
java.lang.NoClassDefFoundError: Could not initialize class com.sun.xml.internal.ws.spi.ProviderImpl
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at javax.xml.ws.spi.FactoryFinder.safeLoadClass(FactoryFinder.java:148)
at javax.xml.ws.spi.FactoryFinder.newInstance(FactoryFinder.java:30)
at javax.xml.ws.spi.FactoryFinder.find(FactoryFinder.java:128)
at javax.xml.ws.spi.Provider.provider(Provider.java:83)
at javax.xml.ws.Service.init(Service.java:56)
at javax.xml.ws.Service.create(Service.java:691)
at ...

for Java 5:
java.lang.NullPointerException
at org.apache.axis2.jaxws.catalog.impl.OASISCatalogManager.determineFileName(OASISCatalogManager.java:124)
at org.apache.axis2.jaxws.catalog.impl.OASISCatalogManager.init(OASISCatalogManager.java:80)
at org.apache.axis2.jaxws.description.impl.ServiceDescriptionImpl.init(ServiceDescriptionImpl.java:165)
at org.apache.axis2.jaxws.description.impl.ServiceDescriptionImpl.init(ServiceDescriptionImpl.java:141)
at org.apache.axis2.jaxws.description.impl.DescriptionFactoryImpl.createServiceDescription(DescriptionFactoryImpl.java:129)
at org.apache.axis2.jaxws.description.impl.DescriptionFactoryImpl.createServiceDescription(DescriptionFactoryImpl.java:76)
at org.apache.axis2.jaxws.description.DescriptionFactory.createServiceDescription(DescriptionFactory.java:75)
at org.apache.axis2.jaxws.spi.ServiceDelegate.init(ServiceDelegate.java:208)
at org.apache.axis2.jaxws.spi.Provider.createServiceDelegate(Provider.java:59)
at javax.xml.ws.Service.init(Service.java:36)
at javax.xml.ws.Service.create(Service.java:120)
at ...

After some hours of searching, I found this bug:
Thread.currentThread().getContextClassLoader() == null when the program is runned by Prunsrv

I checked my program and this was the cause of my problem:

Running from Command line:
21/07/2010 12:44:05,281 - this.getClass().getClassLoader(): sun.misc.Launcher$AppClassLoader@e39a3e
21/07/2010 12:44:05,281 - Thread.currentThread().getContextClassLoader(): sun.misc.Launcher$AppClassLoader@e39a3e
Running as service with Procrun:
21/07/2010 12:44:29,359 - this.getClass().getClassLoader(): sun.misc.Launcher$AppClassLoader@11b86e7
21/07/2010 12:44:29,359 - Thread.currentThread().getContextClassLoader(): null

I applied the workaround described there, and my service is now working OK.
ClassLoader defaultClassLoader = APISalidaServicioWindows.class.getClassLoader();
Thread.currentThread().setContextClassLoader(defaultClassLoader)

The configuration of the current configured Procrun Windows services can be edited/visualized in this Windows registry location:
HKEY_LOCAL_MACHINE/SOFTWARE/Apache Software Foundation/Procrun 2.0/(service name)/Parameters

jueves, 8 de julio de 2010

Unicode Java codes for spanish characters

0x00E1 225 LATIN SMALL LETTER A WITH ACUTE á
0x00E9 233 LATIN SMALL LETTER E WITH ACUTE é
0x00ED 237 LATIN SMALL LETTER I WITH ACUTE í
0x00F3 243 LATIN SMALL LETTER O WITH ACUTE ó
0x00FA 250 LATIN SMALL LETTER U WITH ACUTE ú
0x00F1 241 LATIN SMALL LETTER N WITH TILDE ñ
0x00C1 193 LATIN CAPITAL LETTER A WITH ACUTE Á
0x00C9 201 LATIN CAPITAL LETTER E WITH ACUTE É
0x00CD 205 LATIN CAPITAL LETTER I WITH ACUTE Í
0x00D3 211 LATIN CAPITAL LETTER O WITH ACUTE Ó
0x00DA 218 LATIN CAPITAL LETTER U WITH ACUTE Ú
0x00D1 209 LATIN CAPITAL LETTER N WITH TILDE Ñ

Java:

á - \u00E1

é - \u00E9
í - \u00ED
ó - \u00F3
ú - \u00FA
Á - \u00C1
É - \u00C9
Í - \u00CD
Ó - \u00D3
Ú - \u00DA
ñ - \u00F1
Ñ - \u00D1