JBoss5 class loader and Axis2
jbatista Jul 13, 2010 7:37 AMDear all,
I'm having some troubles that seem to trace back to class loading.
I've created a bottom-up webservice example in Eclipse Galileo to illustrate. I am using:
- Sun Java 1.6.0-13, 32-bit.
- JBoss 5.0.1.GA. (I've tried both in MS Windows XP and in Linux, makes no difference.)
- Apache Axis2 1.4.
Code, server-side
/**
* 1. Server-side class.
* This is in a Dynamic Web Project (here called "MobilePhoneInfo") and is deployed as a Web Service, all done in Eclipse.
*/
package mobile.test;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class MobilePhoneInfo {
public String getMobilePhoneInfo(String url, String path) {
String result=null;
try {
if(url==null || url.length()==0) throw new Exception("null/empty URL");
if(path==null || path.length()==0) throw new Exception("null/empty XPath");
InputStream input = new URL(url).openStream();
if(input!=null) {
InputSource source = new InputSource(input);
DocumentBuilderFactory docFact = DocumentBuilderFactory.newInstance();
docFact.setNamespaceAware(false);
DocumentBuilder parser = docFact.newDocumentBuilder();
Document doc = parser.parse(source);
XPath xpath = XPathFactory.newInstance().newXPath();
// server-side call fails here
result = (String) xpath.evaluate(path,doc,XPathConstants.STRING);
input.close();
} else throw new Exception("null InputStream from given URL "+url);
}
catch (XPathExpressionException e) { e.printStackTrace(); }
catch (SAXException e) { e.printStackTrace(); }
catch (ParserConfigurationException e) { e.printStackTrace(); }
catch (MalformedURLException e) { e.printStackTrace(); }
catch (IOException e) { e.printStackTrace(); }
catch (Exception e) { e.printStackTrace(); }
return result;
}
//
public static void main(String[] args) {
MobilePhoneInfo info = new MobilePhoneInfo();
String url = "http://wap.samsungmobile.com/uaprof/GT-B7300.xml";
String xpath1 = "/RDF/Description/component/Description[@ID='HardwarePlatform']/Vendor";
String xpath2 = "/RDF/Description/component/Description[@ID='HardwarePlatform']/Model";
String vendor; String model;
vendor = info.getMobilePhoneInfo(url,xpath1);
model = info.getMobilePhoneInfo(url,xpath2);
System.out.println("Result:\t"+vendor+" "+model);
}
}
Code, client-side
/**
* 2. Client-side class.
* Stub class is built from the WSDL specification of the deployed web service.
*/
package mobile.test;
import java.rmi.RemoteException;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.ConfigurationContext;
import mobile.test.MobilePhoneInfoStub.GetMobilePhoneInfo;
import mobile.test.MobilePhoneInfoStub.GetMobilePhoneInfoResponse;
public class MobilePhoneInfoClient {
private static final String strEndpoint = "http://localhost:8080/MobilePhoneInfo/services/MobilePhoneInfo.MobilePhoneInfoHttpSoap12Endpoint";
public static void main(String[] args) {
try {
MobilePhoneInfoStub stub = new MobilePhoneInfoStub(strEndpoint);
GetMobilePhoneInfo input = new GetMobilePhoneInfo();
String url = "http://wap.samsungmobile.com/uaprof/GT-B7300.xml";
String path_vendor = "/RDF/Description/component/Description[@ID='HardwarePlatform']/Vendor";
String path_model = "/RDF/Description/component/Description[@ID='HardwarePlatform']/Model";
input.setUrl(url);
GetMobilePhoneInfoResponse output;
input.setPath(path_vendor);
// call fails here
output = (GetMobilePhoneInfoResponse) stub.getMobilePhoneInfo(input);
String vendor = output.get_return();
input.setPath(path_model);
output = (GetMobilePhoneInfoResponse) stub.getMobilePhoneInfo(input);
String model = output.get_return();
System.out.println(vendor+" "+model);
}
catch (AxisFault e) { e.printStackTrace(); }
catch (RemoteException e) { e.printStackTrace(); }
}
}
Logged error, server side
INFO [STDOUT] [ERROR] loader constraint violation: when resolving field "STRING" the class loader (instance of org/jboss/classloader/spi/base/BaseClassLoader) of the referring class, javax/xml/xpath/XPathConstants, and the class loader (instance of <bootloader>) for the field's resolved type, javax/xml/namespace/QName, have different Class objects for that type
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.axis2.rpc.receivers.RPCUtil.invokeServiceClass(RPCUtil.java:194)
at org.apache.axis2.rpc.receivers.RPCMessageReceiver.invokeBusinessLogic(RPCMessageReceiver.java:102)
at org.apache.axis2.receivers.AbstractInOutMessageReceiver.invokeBusinessLogic(AbstractInOutMessageReceiver.java:40)
at org.apache.axis2.receivers.AbstractMessageReceiver.receive(AbstractMessageReceiver.java:100)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:176)
at org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:275)
at org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:131)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:601)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.LinkageError: loader constraint violation: when resolving field "STRING" the class loader (instance of org/jboss/classloader/spi/base/BaseClassLoader) of the referring class, javax/xml/xpath/XPathConstants, and the class loader (instance of <bootloader>) for the field's resolved type, javax/xml/namespace/QName, have different Class objects for that type
at mobile.test.MobilePhoneInfo.getMobilePhoneInfo(MobilePhoneInfo.java:39)
... 33 more
15:57:18,615 INFO [STDOUT] [ERROR] loader constraint violation: when resolving field "STRING" the class loader (instance of org/jboss/classloader/spi/base/BaseClassLoader) of the referring class, javax/xml/xpath/XPathConstants, and the class loader (instance of <bootloader>) for the field's resolved type, javax/xml/namespace/QName, have different Class objects for that type
org.apache.axis2.AxisFault: loader constraint violation: when resolving field "STRING" the class loader (instance of org/jboss/classloader/spi/base/BaseClassLoader) of the referring class, javax/xml/xpath/XPathConstants, and the class loader (instance of <bootloader>) for the field's resolved type, javax/xml/namespace/QName, have different Class objects for that type
at org.apache.axis2.rpc.receivers.RPCMessageReceiver.invokeBusinessLogic(RPCMessageReceiver.java:158)
at org.apache.axis2.receivers.AbstractInOutMessageReceiver.invokeBusinessLogic(AbstractInOutMessageReceiver.java:40)
at org.apache.axis2.receivers.AbstractMessageReceiver.receive(AbstractMessageReceiver.java:100)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:176)
at org.apache.axis2.transport.http.HTTPTransportUtils.processHTTPPostRequest(HTTPTransportUtils.java:275)
at org.apache.axis2.transport.http.AxisServlet.doPost(AxisServlet.java:131)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:601)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.axis2.rpc.receivers.RPCUtil.invokeServiceClass(RPCUtil.java:194)
at org.apache.axis2.rpc.receivers.RPCMessageReceiver.invokeBusinessLogic(RPCMessageReceiver.java:102)
... 27 more
Caused by: java.lang.LinkageError: loader constraint violation: when resolving field "STRING" the class loader (instance of org/jboss/classloader/spi/base/BaseClassLoader) of the referring class, javax/xml/xpath/XPathConstants, and the class loader (instance of <bootloader>) for the field's resolved type, javax/xml/namespace/QName, have different Class objects for that type
at mobile.test.MobilePhoneInfo.getMobilePhoneInfo(MobilePhoneInfo.java:39)
... 33 more
Further details
The javax.xml.namespace.QName class used by the static XPathConstants.STRING object seems to be in many different .jar files.
For example, the relevant ones seem to be the Java JDK's rt.jar and, specific of Axis2, in axis2-saaj-api-1.4.jar. So at some point one version of QName is used somewhere and this collides with the attempted loading of QName from Axis2.
I've found some posts elswhere explaining that the creation/inclusion of a jboss-web.xml file in the project's WEB-INF directory should allow the control of exactly how the class loader (only one?!) will pick the classes, but I'm not exactly sure if this is the correct way (I haven't met much success) and whether this is a dead-end. I've tried something like this:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 5.0//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd">
<jboss-web>
<class-loading java2ClassLoadingCompliance="false">
<loader-repository>mobile.test:loader=MobilePhoneInfoEAR.ear</loader-repository>
</class-loading>
</jboss-web>
I'm not even too sure if, given the projects' layouts, the XML contains the correct information.
I would very much like to thank in advance for people able to share some insight on this matter.
Regards,
jbatista