XPath class resolution in JBoss5 - java

I'm having a hard time figuring out where the problem is coming from, so I'm posting this in the hopes that others might have found something similar to this elsewhere and are kind enough to share their insight.
I'm using a JBoss 5.0.1.GA application server running on top of a Sun Java 1.6.0-13 JDK. For the WAR file in the generated Web Service, I use a Axis2 1.4 WS engine whose JAR files are inserted by Eclipse Galileo into the project's WEB-INF/lib directory when creating the Webservice from the given "worker" class in the Dynamic Web Project. The relevant code snippet follows:
String sUrl = "http://example.com/datafile.xml";
String sPath = "/some/xpath/string";
InputStream input = new URL(sUrl).openStream();
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();
// error occurs here:
String result = (String) xpath.evaluate(path,doc,XPathConstants.STRING);
input.close();
This is the error I'm getting from the JBoss log:
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
I could use the XPath.evaluate(String,Document) — however there are occasions where I need to get (for example) a XPathConstants.NODESET instead, so it's a no-go. I have also tried to fumble a little by littering some jboss-web.xml files here and there in the WAR file, but with no effect.
What I'm trying to understand is:
Where could the error be coming from? The JBoss class loader? Some weird interaction between JBoss and the Sun JDK? Some weirdness introduced by Eclipse when creating the Web Service? Maybe some confusion introduced by the Axis2 libraries deployed within the WAR?
I've found instances of compiled class files in what looks like a triple-whammie:
Sun JDK (file rt.jar);
JBoss libraries ($JBOSS_HOME/lib/endorsed/stax-api.jar); and
Axis2-deployed libraries ($JBOSS_HOME/server/deploy/MyProject.ear/MyProject.war/WEB-INF/lib/axis2-saaj-api-1.4.jar and woden-impl-dom-1.0M8.jar).
How exactly am I supposed to configure JBoss to tell it which classes it's OK to load from "other" libraries from? Specifically, the jaxax.xml.namespace.QName is is causing the grief.
Thank you in advance.

JBoss will throw a LinkageError when the application's classpath contains classes which JBoss considers "protected", i.e. it does not permit the application to contain its own copies of certain key APIs.
In this case, it looks like your appcontains its own copies of the javax.xml.xpath API, and possibly some others as well, as you mentioned.
You need to remove anything from your EAR/WAR's lib directories that clashes with JBoss's own libraries (e.g. axis2-saaj-api-1.4.jar).

It seems that the problem was solved by removing the javax.xml.namespace.* package and respective classes from the deployed Axis2 JAR files. Namely, using Axis2 1.4.1 (instead of 1.4), I repackaged these JAR files:
axis2-saaj-api-1.4.1.jar, by removing javax.xml.namespace
woden-impl-dom-1.0M8.jar, by removing javax
Also, Eclipse is extremely picky at the project configuration. So far, I've found that the Project Facet for the Dynamic Web Project has to be created with a Dynamic Web Module of version 2.4 (and not 2.5 as it suggests by default), but with a Java version 6 (same as the branch of the used JDK). I don't know why this happens, I suppose the Dynamic Web Module version 2.4 tying up by default with Java 1.4 in Eclipse is where all the confusion comes from. Some googling led me to believe that package javax.xml didn't become incorporated into the JDK until Java 5 or Java 6 -- hence the possible mixup! However, I'm not knowledgeable enough to investigate if the problem comes from how Eclipse packages the archive files for deployment so this is just a suspicion I have so far.

Related

JDBC driver not found (servlet, DAO, mariaDB) [duplicate]

I developer a web application using Java. When I deploy it to my application server (Jetty, Tomcat, JBoss, GlassFish, etc.) throws an error. I can see this error message in the stacktrace:
java.lang.ClassNotFoundException
Or
java.lang.NoClassDefFoundError
What does this mean and how can I fix it?
What does this mean?
First, let's see the meaning of java.lang.ClassNotFoundException:
Thrown when an application tries to load in a class through its string name using:
The forName method in class Class.
The findSystemClass method in class ClassLoader.
The loadClass method in class ClassLoader.
but no definition for the class with the specified name could be found.
Usually, this happens when trying to open a connection manually in this form:
String jdbcDriver = "...'; //name of your driver
Class.forName(jdbcDriver);
Or when you refer to a class that belongs to an external library and strangely this class cannot be loaded when the application server tries to deploy the application.
Let's see the meaning of java.lang.NoClassDefFoundError (emphasis mine):
Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found.
The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.
The last part says it all: the class existed at compile time i.e. when I compiled the application through my IDE, but it is not available at runtime i.e. when the application is deployed.
how can I fix it?
In Java web applications, all third party libraries used by your application must go in WEB-INF/lib folder. Make sure that all the necessary libraries (jars) are placed there. You can check this easily:
- <webapp folder>
- WEB-INF
- lib
+ jar1
+ jar2
+ ...
- META-INF
- <rest of your folders>
This problem usually arises for JDBC connectivity jars (MySQL, Derby, MSSQL, Oracle, etc.) or web MVC frameworks libraries like JSF or Spring MVC.
Take into account that some third party libraries rely on other third party libraries, so you have to add all of them in WEB-INF/lib in order to make the application work. A good example of this is RichFaces 4 libraries, where you have to download and add the external libraries manually.
Note for Maven users: you should not experience these problems unless you have set the libraries as provided, test or system. If set to provided, you're responsible to add the libraries somewhere in the classpath. You can find more info about the dependency scopes here: Introduction to the Dependency Mechanism
In case the library must be shared among several applications that will be deployed on your application server e.g. MySQL connector for two applications, there's another alternative. Instead of deploying two war files each with their own MySQL connector library, place this library in the common library folder of the server application, this will enable the library to be in the classpath of all the deployed applications.
This folder vary from application server.
Tomcat 7/8: <tomcat_home>/lib
JBoss 7/Wildfly: <jboss_home>/standalone/lib
The class must exist under WEB-INF/classes or be inside a .jar file under WEB-INF/lib. Make sure it does.
Same problem happen with me.
Might be possible one of your libraries are using some classes internal which is not available
in your lib or maven dependency pom.xml.
Thats means you have analyze your error logs and identify these classes and then import all dependencies in maven or lib folder.
I have fixed this error by the same way.
because some of my libraries are using activation.jar and json.jar internally.

Hibernate and Jersey dependency conflict (javassist) - can anyone explain how this works?

I'm currently using hibernate-4.1.4 and jersey-2.22. These have javassist-3.15 and javassist-3.18 respectively.
I included both hibernate and jersey in my project and to my surprise, there were no dependency conflicts between the said javassists.
I was wondering how Java tells hibernate to use 3.15 and how it tell jersey to use 3.18 since both are in the build path. Is one javassist not being used?
Follow up question: Let's say that javassist-3.15 and javassist-3.18 have a conflict with each other. How do I resolve this? Do I disable both javassists and include one externally?
EDIT: My app is a web app that runs on Tomcat 7. We don't use Maven/Gradle. We just configure the dependencies by putting the jars in the build path using Eclipse.
JAVA loads classes through ClassLoaders ... Many applications servers, as Tomcat or Wildfly, implement and use their own class loaders (not the regular ones of the common JDK) ... So you must check the Tomcat documentation to read about its classloading behaviour...
After saying that, is very likely that Tomcat is loading libraries in alphabetical order. I Explain...
Suppose that you use a class named: Dummy, and this class is contained at the libraries: dummy-1.0.jar and dummy-1.1.jar ... when the class Dummy is requested, the Tomcat ClassLoader search for that class definition, looking first at dummy-1.0.jar and later at dummy-1.1.jar ... given that dummy-1.0.jar contains that class, Tomcat stops looking a returns that class version ... If dummy-1.0.jar would not have the target class, the dummy-1.1.jar class version would be returned instead...
(I suggest to try this to validate the container behaivour, it's not so hard to implement)...
And yes, if javassist-3.15 and javassist-3.18 conflicts with each other, you should remove them and pick the javassist JAR more
suitable for both libraries (jersey and hibernate).
As thumb rule, I tend to pick the newest library (the one with greater version), but this scheme not always work...

Set the JAXB context factory initialization class to be used

I have updated our projects (Java EE based running on Websphere 8.5) to use a new release of a company internal framework (and Ejb 3.x deployment descriptors rather than the 2.x ones). Since then my integration Tests fail with the following exception:
[java.lang.ClassNotFoundException: com.ibm.xml.xlxp2.jaxb.JAXBContextFactory]
I can build the application with the previous framework release and everything works fine.
While debugging i noticed that within the ContextFinder (javax.xml.bind) there are two different behaviours:
Previous Version (Everything works just fine): None of the different places brings up a factory class so the default factory class gets loaded which is com.sun.xml.internal.bind.v2.ContextFactory (defined as String constant within the class).
Upgraded Version (ClassNotFound): There is a resource "META-INF/services/javax.xml.bind.JAXBContext" beeing loaded successfully and the first line read makes the ContextFinder attempt to load "com.ibm.xml.xlxp2.jaxb.JAXBContextFactory" which causes the error.
I now have two questions:
What sort is that resource? Because inside our EAR there is two WARs and none of those two contains a folder services in its
META-INF directory.
Where could that value be from otherwise? Because a filediff showed me no new or changed properties files.
No need to say i am going to read all about the JAXB configuration possibilities but if you have first insights on what could have gone wrong or help me out with that resource (is it a real file i have to look for?) id appreciate a lot. Many Thanks!
EDIT (according to comments Input/Questions):
Out of curiosity, does your framework include JAXB JARs? Did the old version of your framework include jaxb.properties?
Indeed (i am a bit surprised) the framework has a customized eclipselink-2.4.1-.jar inside the EAR that includes both a JAXB implementation and a jaxb.properties file that shows the following entry in both versions (the one that finds the factory as well as in the one that throws the exception):
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
I think this is has nothing to do with the current issue since the jar stayed exactly the same in both EARs (the one that runs/ the one with the expection)
It's also not clear to me why the old version of the framework was ever selecting the com.sun implementation
There is a class javax.xml.bind.ContextFinder which is responsible for initializing the JAXBContextFactory. This class searches various placess for the existance of a jaxb.properties file or a "javax.xml.bind.JAXBContext" resource. If ALL of those places dont show up which Context Factory to use there is a deault factory loaded which is hardcoded in the class itself:
private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory";
Now back to my problem:
Building with the previous version of the framework (and EJB 2.x deployment descriptors) everything works fine). While debugging i can see that there is no configuration found and thatfore above mentioned default factory is loaded.
Building with the new version of the framework (and EJB 3.x deployment descriptors so i can deploy) ONLY A TESTCASE fails but the rest of the functionality works (like i can send requests to our webservice and they dont trigger any errors). While debugging i can see that there is a configuration found. This resource is named "META-INF/services/javax.xml.bind.JAXBContext". Here are the most important lines of how this resource leads to the attempt to load 'com.ibm.xml.xlxp2.jaxb.JAXBContextFactory' which then throws the ClassNotFoundException. This is simplified source of the mentioned javax.xml.bind.ContextFinder class:
URL resourceURL = ClassLoader.getSystemResource("META-INF/services/javax.xml.bind.JAXBContext");
BufferedReader r = new BufferedReader(new InputStreamReader(resourceURL.openStream(), "UTF-8"));
String factoryClassName = r.readLine().trim();
The field factoryClassName now has the value 'com.ibm.xml.xlxp2.jaxb.JAXBContextFactory'
Because this has become a super lager question i will also add a bounty :)
I will work the entire day on this and let you know if there is any news.
Update/ Solution
This question has been solved. The original problem has occured because misconfiguration of complexly build multi model maven projects which one dependency used a updated version of a customized eclipse link jar that contained a definition for a JAXBFactory not available in the component where the error occured. Setting the JAXB context factory in most cases is configured with a jaxb.propertie file or JAXBContext file that contains the same definition. Detailed loading process of the appropriate JAXBContextFactory happens in javax.xml.bind.ContextFinder.
The error has not yet been solved (during the fact over 4 major EE/SE Applications lead to the error) and there is no general answer but that defined JAXBContextFactorys must exist in your classpath (wow what a wonder...) so you either have a that ClassNotFound Error because youre missing resources (well thats the acctual cause) or because you have a wrong JAXBContextFactory defined in any of the above mentioned propertie files which contain a definition according to the below answer.
Very many thanks for your great comments and support, i realy appreciate!
You can include a jaxb.properties file in the same package as your domain model to specify the JAXB (JSR-222) implementation you wish to use. For example it would look like the following to specify EclipseLink MOXy as your JAXB provider.
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
For More Information
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
Another quick and dirty solution (a workaround, really) that worked for me is to explicitly include a JAXB implementation to the maven build. For example
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.7</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.7</version>
</dependency>
Note that this adds a somehow unnecessary dependency to your build, as JAXB obviously already is part of each JRE >= version 6.
Most likely this will only work when the WAS classloader is set to parent last.

JAXBException caused by generated code

I am getting the following JAXBException of the form
class SomeClass nor any of its super class is known to this context.
The full stack trace looks like this:
javax.xml.ws.WebServiceException: javax.xml.bind.JAXBException: class com.myCompany.generatedCode.WebServiceOperationName nor any of its super class is known to this context.
at org.apache.axis2.jaxws.ExceptionFactory.createWebServiceException(ExceptionFactory.java:175)
at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:70)
at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:128)
at org.apache.axis2.jaxws.core.controller.impl.AxisInvocationController.execute(AxisInvocationController.java:586)
at org.apache.axis2.jaxws.core.controller.impl.AxisInvocationController.doInvoke(AxisInvocationController.java:130)
at org.apache.axis2.jaxws.core.controller.impl.InvocationControllerImpl.invoke(InvocationControllerImpl.java:93)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invokeSEIMethod(JAXWSProxyHandler.java:364)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invoke(JAXWSProxyHandler.java:185)
at $Proxy41.deleteAccount(Unknown Source)
at com.myCompany.myPackage.MyWebServiceClient.callSomeWebService(MyWebServiceClient.java:100)
(other classes specific to my application and framework)
...
Caused by:
javax.xml.bind.JAXBException: class com.myCompany.generatedCode.WebServiceOperationName nor any of its super class is known to this context.
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:556)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:452)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:314)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:243)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:75)
at com.ibm.xml.xlxp2.jaxb.marshal.MarshallerProxy.marshal(MarshallerProxy.java:100)
at org.apache.axis2.datasource.jaxb.JAXBDSContext$1.run(JAXBDSContext.java:470)
at org.apache.axis2.java.security.AccessController.doPrivileged(AccessController.java:76)
at org.apache.axis2.datasource.jaxb.JAXBDSContext.marshalByElement(JAXBDSContext.java:455)
at org.apache.axis2.datasource.jaxb.JAXBDSContext.marshal(JAXBDSContext.java:414)
at org.apache.axis2.jaxws.message.databinding.impl.JAXBBlockImpl._outputFromBO(JAXBBlockImpl.java:189)
at org.apache.axis2.jaxws.message.impl.BlockImpl.outputTo(BlockImpl.java:372)
at org.apache.axis2.jaxws.message.impl.BlockImpl.serialize(BlockImpl.java:296)
at org.apache.axiom.om.impl.llom.OMSourcedElementImpl.internalSerializeAndConsume(OMSourcedElementImpl.java:808)
at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:975)
at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerializeAndConsume(OMElementImpl.java:1016)
at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.serializeInternally(SOAPEnvelopeImpl.java:271)
at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.internalSerialize(SOAPEnvelopeImpl.java:233)
at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerializeAndConsume(OMElementImpl.java:1016)
at org.apache.axiom.om.impl.llom.OMNodeImpl.serializeAndConsume(OMNodeImpl.java:488)
at org.apache.axis2.transport.http.SOAPMessageFormatter.writeTo(SOAPMessageFormatter.java:88)
at com.ibm.ws.websvcs.transport.http.SOAPOverHTTPSender.writeMessage(SOAPOverHTTPSender.java:3271)
at com.ibm.ws.websvcs.transport.http.SOAPOverHTTPSender.sendChunkedRequest(SOAPOverHTTPSender.java:888)
at com.ibm.ws.websvcs.transport.http.SOAPOverHTTPSender.sendSOAPRequest(SOAPOverHTTPSender.java:807)
at com.ibm.ws.websvcs.transport.http.SOAPOverHTTPSender.send(SOAPOverHTTPSender.java:611)
at com.ibm.ws.websvcs.transport.http.HTTPTransportSender.invoke(HTTPTransportSender.java:364)
at org.apache.axis2.engine.AxisEngine.send(AxisEngine.java:531)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:401)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:228)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:163)
at org.apache.axis2.jaxws.core.controller.impl.AxisInvocationController.execute(AxisInvocationController.java:581)
... 52 more
What triggers this is attempting to make a call to a web service operation named WebServiceOperationName. I've seen other tips for dealing with this error which usually involve adding a #XmlSeeAlso annotation or making adjustments to how marshalling and unmarshalling are done.
In this case, I am calling a webservice whose code is generated by Maven based on a WSDL (and supporting schemas). I don't have direct control over the code produced by Maven, and I don't have control over the marshall/unmarshall calls. Other webservice calls in the application don't seem to be having any problem.
Even stranger, I can't reproduce this on my local server, though it happens on the development server. The generated JAR for the webservice is the same, as it the rest of the application's code.
This exception has appeared suddenly this week (and consistently), and I suspect that something has changed, environmentally, but I'm not sure what. Any ideas?
A new observation:
The first time I attempt to run this code on the server after it's been started/restarted, it takes a while (About a minute) before it fails and throws an exception. Every time after that, the exception is almost instantaneous...
Further information:
This problem is present in WebSphere 7.0.0.23 (which is on the server), but not in WebSphere 7.0.0.7 (on the workstation).
The issue's been resolved. I was inspecting the jar that contained the class WAS was complaining about and noticed that some of the classes were duplicated at different levels of package hierarchy. It's worth pointing out that the class that was reported in the original error was not actually one of these duplicated classes. Also, the application did not reference different variants of the same class - the classes referenced were in the expected package. The extra duplicates one level up were not referenced anywhere (as far as I can tell).
It looked like a bad Maven configuration, but when I inspected the xjb binding files, I couldn't figure out how the types in that schema namespace got bound to two different packages. Either way, I cleanded up some of the binding files used by Maven, refactored common bindings into one file, had Maven rebuild the jar, and then tested, and suddenly the issue was gone!
Clearly there was a problem in WAS 7.0.0.23 since the original jar worked fine on WAS 7.0.0.7. It may have been caused by a problem with the Maven bindings which resulted in a strange-looking but technically valid jar.
Also interesting: one of our developers upgraded WAS to 7.0.0.25 and used the original "bad" jar and got a "no such operation" error instead of the JAXBException.
I have the same problem in Guidewire ClaimCenter, which is an insurance application that can be configured but the core can't be modified at all, It's Java based it has component included like axis2 but I created a seperate java project that wraps a webservice call, I created all the stub code with wsimport. It works well under my deve enviroment which is windows and jetty because is the Guidewire platform to configure it (no other option). we use WAS 7 as production server.
Caused by: javax.xml.ws.WebServiceException: javax.xml.bind.JAXBException: au.com.mycompany.policyinquiry.retrieveinsurancepolicydetails.v1.RetrieveInsurancePolicyDetailsResp is not known to this context
at org.apache.axis2.jaxws.ExceptionFactory.createWebServiceException(ExceptionFactory.java:175)
at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:70)
at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:128)
at org.apache.axis2.jaxws.marshaller.impl.alt.DocLitBareMinimalMethodMarshaller.demarshalResponse(DocLitBareMinimalMethodMarshaller.java:158)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.createResponse(JAXWSProxyHandler.java:499)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invokeSEIMethod(JAXWSProxyHandler.java:377)
at org.apache.axis2.jaxws.client.proxy.JAXWSProxyHandler.invoke(JAXWSProxyHandler.java:185)
at $Proxy80.retrieveInsurancePolicyDetails(Unknown Source)
I tried to generate and compile the client in the server side just in case it was something related with different JDK platform, but that didn't solve the problem.
I found the next article was 6!
but for WAS 6 , I haven't tried though.
When the JAX-WS web service engine receives a message, it uses
the JAXB engine to convert the message into java beans.
The message indicates a failure occurred while converting xml
into an object of type
com.somecom.lib.business.xml.ComIdentifierXml. The failure
indicates that the JAXB engine was not initialized with
information about this user class.
.
In this use case, the class
com.somecom.lib.business.xml.ComIdentifierXml is packaged in a
JAR at the EAR level. The exception does not happen if the
class is packaged in a JAR located in the WAR module's
WEB-INF/lib directory.
SOLUTION:
Target Environment:
IBM server
IBM JDK 1.6
IBM Webpshere 7.0.0.25
The client to call the webservice is using pure JAVA no dependency on external library JAX-WS RI 2.1.6
In webspehre
1- Set for the application the class loading to parent last
2- Turn off webservice annotations with this: Set the com.ibm.websphere.webservices.DisableIBMJAXWSEngine property to true. this will disabled Websphere own implementation based on a modified Axis2
3- Deploy your application with third-party JAX-WS runtime
in my case i used Glassfish Metro 1.5 which includes JAX-WS RI 2.1.7 and is the same as my local environment with JDK 1.6.0_37
That's it
Cheers
Alex :)

WSDL parsing exception creating Webservice client with CXF JaxWSClientFactoryBean

I've written some code to create and run webservice client using CXF. I used JaxWsClientFactoryBean (not sure it's the best solution) to create client from .wsdl file.
The goal here was to do this programmatically avoiding Spring etc. Just pure code with Java and CXF.
JaxWsClientFactoryBean cfb = new JaxWsClientFactoryBean();
cfb.setAddress(getServiceProperty(intClass, PROPERTY_KEY_URL_SUFFIX));
cfb.setServiceClass(intClass);
cfb.setOutInterceptors(getOutInterceptors(intClass));
cfb.setServiceName(SERVICE_NAME);
cfb.setWsdlURL("classpath:wsdl/" + intClass.getSimpleName() + ".wsdl");
cfb.setEndpointName(ENDPOINT_NAME);
Client client = cfb.create();
ClientProxy cp = new ClientProxy(client);
I intService = (I)
Proxy.newProxyInstance(intClass.getClassLoader(), new Class[] { intClass }, cp);
I'm really not sure if this is done correctly, but it works when I run this code locally and when I deploy it on Tomcat.
Unfortunatelly I need to run this code on Weblogic and this results in strange exception:
Caused by: javax.wsdl.WSDLException: WSDLException: faultCode=PARSER_ERROR: org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was
made to insert a node where it is not permitted.
at org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:235)
at org.apache.cxf.wsdl11.WSDLManagerImpl.getDefinition(WSDLManagerImpl.java:186)
at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:92)
... 26 more
Caused by: org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
at com.sun.org.apache.xerces.internal.dom.ParentNode.internalInsertBefore(ParentNode.java:356)
at com.sun.org.apache.xerces.internal.dom.ParentNode.insertBefore(ParentNode.java:284)
at com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl.insertBefore(CoreDocumentImpl.java:399)
at com.sun.org.apache.xerces.internal.dom.NodeImpl.appendChild(NodeImpl.java:235)
at org.apache.cxf.staxutils.StaxUtils.readDocElements(StaxUtils.java:1019)
at org.apache.cxf.staxutils.StaxUtils.readDocElements(StaxUtils.java:939)
at org.apache.cxf.staxutils.StaxUtils.read(StaxUtils.java:866)
at org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:226)
... 28 more
This happens during application deployment. It looks like there is something wrong with .wsdl file, but wait... It was working on Tomcat!
I think that there could be some difference in com.sun.org.apache.xerces.* classes implementation within Weblogic with its JRockit VM and standard JVM, but I have no idea how to solve it.
I spent many hours trying differend ways of client creation. Most of them worked locally and in Tomcat, but none on WebLogic.
Any hints what to try next? I'm kinda tired of this topic :D
I agree with your suspicion that the problem is related to the used version of Xerces. The stacktrace shows that the Sun implementation of Xerces which is derivative of the Apache Xerces is used in your case.
Please check the Apache CFX Application Server Configuration Guide instructions related to WebLogic.
WebLogic ClassLoading
In WebLogic Server, any .jar file present in the system classpath is loaded by the WebLogic Server system classloader. All applications running within a server instance are loaded in application classloaders which are children of the system classloader. In this implementation of the system classloader, applications cannot use different versions of third-party jars which are already present in the system classloader. Every child classloader asks the parent (the system classloader) for a particular class and cannot load classes which are seen by the parent.
For example, if a class called com.foo.Baz exists in both $CLASSPATH as well as the application EAR, then the class from the $CLASSPATH is loaded and not the one from the EAR. Since weblogic.jar is in the $CLASSPATH, applications can not override any WebLogic Server classes.
In order to use an alternate version of Xerces you have to create a FilteringClassLoader.
Usage of FilteringClassLoader
The FilteringClassLoader provides a mechanism for you to configure deployment descriptors to explicitly specify that certain packages should always be loaded from the application, rather than being loaded by the system classloader. This allows you to use alternate versions of applications such as Xerces and Ant.
The FilteringClassLoader sits between the application classloader and the system. It is a child of the system classloader and the parent of the application classloader. The FilteringClassLoader intercepts the loadClass(String className) method and compares the className with a list of packages specified in weblogic-application.xml file.
In conclusion, check the steps included in the Apache CFX Application Server Configuration Guide and take care to explicitly specify that the org.apache.xerces.* package is loaded from the application, rather than being loaded from the system classloader.
For example the weblogic-application.xml file in the META-INF should look like:
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-application xmlns="http://www.bea.com/ns/weblogic/90">
<application-param>
<param-name>webapp.encoding.default</param-name>
<param-value>UTF-8</param-value>
</application-param>
<prefer-application-packages>
<package-name>javax.jws.*</package-name>
<package-name>org.apache.xerces.*</package-name>
</prefer-application-packages>
</weblogic-application>
I hope this helps.

Categories