I am in the process of migrating a legacy application from weblogic to Tomcat 6.
The application needs to access ejbs; to achieve that, I added wlclient.jar to the classpath.
When the methods in the legacy jars responsible for communicating with the ejbs are called, I get the following exception :
javax.naming.NamingException: Unhandled exception in lookup
[Root exception is org.omg.CORBA.MARSHAL: vmcid: SUN minor code: 211 completed: Maybe]
which cause is :
Caused by: java.lang.IllegalArgumentException: interface com.xxx.xxx.InterfaceName is not visible from class loader
at java.lang.reflect.Proxy.getProxyClass(Proxy.java:353)
at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:581)
at weblogic.iiop.ProxyDesc.readResolve(ProxyDesc.java:45)
That Interface seems to be used to define the method called from the client to return some informations from the server where the ejbs are deployed.
When running with verbose:class, I find that the Interface is actually loaded from the local jar. The corresponding interface on the server is loaded too :
[Loaded com.xx.xx.InterfaceName_t3s99q_InterfaceNameIntf from http://192.168.x.xx:port/path/classes/]
Even though I do not have any idea how that works internally, I assumed the lookup had gone well since it finds the correct class on the server.
When putting breakpoints in Proxy.getProxyClass, I found the used classloader when the exception occurs was a Launcher$AppClassLoader; the URL's it used to lookup were those in my local classpath (a.k.a. src/main/java and such) and not the webapp's path (a.k.a. WEB-INF/lib and such).
So my question is : is it possible that the wrong ClassLoader gets used for that specific lookup (local one instead of Tomcat's webapp level one)?
Can I specify a specific ClassLoader?
Am I looking in the completely wrong direction to resolve that issue ?
Well I lost 1.5 days on this, so I'll post an answer hoping it will eventually be useful to someone.
The problem was that I included wlclient.jar in eclipse classpath, and since the oracle implementation uses super.getClass().getClassLoader() , it would return the ClassLoader used to load the Class in which the call is made a.k.a. the local ClassLoader and not the one from the Webapp, so it did not have visiblity of the webapp dependencies.
I updated my project to include the jar in WEB-INF/lib so it would be loaded by the webapp and thus super.getClass().getClassLoader() would return the right ClassLoader.
An other possibility would have been to modify that line to use Thread.currentThread.getContextClassLoader instead.
Related
I have a very simple POC setup where I deploy a JEE7 webapp on a wildfly 9.
Via a jaxRs Resource endpoint I can trigger a "plugin loader".
The PluginLoader does use a directory and scans for jar files in the directory, which URLs then will be fed into a URLClassLoader.
Afterwards I use the ServiceLoader to load implmementations of a simple interface from those URLs.
When the ServiceLoader starts iterating over the found implementations, I get this error:
Caused by: java.util.ServiceConfigurationError: com.test.MyIface: Provider com.test.MyImpl not a subtype
The structure is also very simple:
MyIface.jar is the interface.
MyImpl.jar is a implementation of MyIface, while it contains a META-INF/services file with the correct naming and content for MyIface..
The webapp itself only knows MyIFace of course.
In JavaSE using a simple main entry point and invoking the loader from there, everything works.
In JavaEE the services file seems to be ignored though..at least that is what I get from the exception.
I put it in src/main/resources/META-INF/services
and in src/main/resource/WEB-INF/classes/META-INF/services (as I read that already in context with SPI and webapps)
In order for this to work, the following 2 steps must be followed:
Instantiate a ClassLoader (the stock URLClassLoader will do) that knows both the targeted jar AND the classloader of the web application.
It needs to know the targeted jar obviously to load the service implementation
It needs to have the classloader of the web app as parent so that all the classloaders share the interface class; otherwise, even if the custom classloader loads the interface, you will run to ClassCastExceptions like "MyIface is not an instance of MyIface"
Specify the classloader you created using the ServiceLoader.load(Class, ClassLoader) method
I am getting the following exception when using javax HTTP client. Any idea why this might be happening?
java.lang.ClassCastException: Cannot cast org.glassfish.jersey.inject.hk2.Hk2InjectionManagerFactory to org.glassfish.jersey.internal.inject.InjectionManagerFactory
at java.lang.Class.cast(Class.java:3369)
at org.glassfish.jersey.internal.ServiceFinder$LazyObjectIterator.hasNext(ServiceFinder.java:714)
at org.glassfish.jersey.internal.inject.Injections.lookupService(Injections.java:112)
at org.glassfish.jersey.internal.inject.Injections.lookupInjectionManagerFactory(Injections.java:97)
at org.glassfish.jersey.internal.inject.Injections.createInjectionManager(Injections.java:68)
at org.glassfish.jersey.client.ClientConfig$State.initRuntime(ClientConfig.java:432)
at org.glassfish.jersey.internal.util.collection.Values$LazyValueImpl.get(Values.java:341)
at org.glassfish.jersey.client.ClientConfig.getRuntime(ClientConfig.java:826)
at org.glassfish.jersey.client.ClientRequest.getConfiguration(ClientRequest.java:285)
at org.glassfish.jersey.client.JerseyInvocation.validateHttpMethodAndEntity(JerseyInvocation.java:143)
at org.glassfish.jersey.client.JerseyInvocation.<init>(JerseyInvocation.java:112)
at org.glassfish.jersey.client.JerseyInvocation.<init>(JerseyInvocation.java:108)
at org.glassfish.jersey.client.JerseyInvocation.<init>(JerseyInvocation.java:99)
at org.glassfish.jersey.client.JerseyInvocation$AsyncInvoker.method(JerseyInvocation.java:706)
at org.glassfish.jersey.client.JerseyInvocation$AsyncInvoker.get(JerseyInvocation.java:566)
Could it be a classloader related issue? As the code that uses the http client is loaded as a plugin with a separate classloader.
It certainly is a classloader issue; I have recently faced the same problem with Jersey 2.35. What In understand, Jersey internals in terms of dependency injection architecture has changed (Refer this post: wypieprz answer).
The above occurs due to 'classloader shadowing' (if there is such a term). the contention is between the container class loader (in my case Tomcat JARClassLoader) and web-app class loader (WebbAppClassLoader of Tomcat).
Since class loaded by different class loaders are not considered same. Therefore, in your case (and as was in mine), the 'Hk2InjectionManagerFactory' class and the 'InjectionManagerFactory' class was loaded by different class loaders and therefore the assignment fails with class cast exception.
In my case, the problem was, I had, 'jersey-common' and 'jersey-client' on both web-app and Tomcat common loader (container class path). This caused the problem.
The solution was to move all the Jersey related classes to WEB-INF/lib and the library which depended upon jersey-client also to WEB-INF lib.
In addition, also check your classpath (container class path), if there are any other older versions of jersey related jars.
[I originally posted this on the websphere forums bot didn't see a timely response. I'm re-posting here with slightly more content]
The Problem
I added a jar (call it "Foo.jar") to our enterprise application (i.e. ".ear"), created the manifest entry, etc., and found, to my surprise, that when my EJB instantiated FooClient, websphere threw a java.lang.LinkageError upon org.slf4j.LoggerFactory
I've added classloader debugging to the trace and did not find much. I was hoping to see "where WAS actually found the slf4j class". Here are the entries:
[9/24/14 16:23:01:417 CDT] 00000067 CompoundClass > loadClass org.slf4j.LoggerFactory this=com.ibm.ws.classloader.CompoundClassLoader#5c2687e4[app:yourappServer] Entry
[9/24/14 16:23:01:418 CDT] 00000067 CompoundClass < loadClass org.slf4j.LoggerFactory java.lang.LinkageError: org.slf4j.LoggerFactory Exit
I've checked my was8 directory and found various copies/versions of the slf4j jar.
/plugins
/osgiappbundles/com.ibm.ws.osgi.applications/aries/slf4j-api-1.5.6.jar
/slf4j-api-1.5.6.jar
/profiles/AppSrv01
/installedConnectors/activemq-rar-5.9.1.rar/slf4j-api-1.7.5.jar
/wstemp
/appdepl14769b0c2de/slf4j-api-1.7.5.jar3472682177251273594.tmp
/appdepl14769b0c2de/slf4j-api-1.7.5.jar7922145899030561292.tmp
Another developer told me "you won't be able to use Foo.jar" because we would need to put "Parent_last" and that's not an option for this project currently.
Additional Context
Websphere 8.0.0.7
RAD 9
Questions
java.lang.LinkageError : is this a 'classloader problem' or 'wrong version of class' problem? My experience with "wrong version of class" problems I usually see "NoSuchMethod" errors, not instantiation exceptions.
Any other way around this?
Updates
I read a bit about shared libraries and "isolated classloader" and this seemed the solution. However for some reason, my RAD/Eclipse UI seems broken as it does not 'save' when I associate the shared library with an application or module. It subsequently disappears.
thanks in advance
if you want to use newer library which is already there in websphere parent_last is the way to go
if not, remove the slf4j jar from the app, and use the version that is given by vendor
Check the version of SL4J expected by Foo.jar and the one you are using: they are surely different. Ensure the correct version has precedence in your classpath: you can put it in WEB-INF/lib but also check that you have just one version of it in WEB-INF/lib.
To discover which SL4J jar you are using you can run
java -verbose:class ....
and the JVM will dump out what it's loading, and from where.
You say "I usually see NoSuchMethod errors" instead of LinkageError; in this case the method exists but has some other incompatibility.
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 :)
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.