How to use httpcomponents in wildfly 10 with EAR project? - java

I can't get org.apache.httpcomponents to work in Wildfly 10. I didn't try 9. The error I get is, basically.
Caused by: java.lang.ClassNotFoundException: org.apache.http.client.methods.HttpUriRequest from [Module "deployment.opca-ear.ear.opca-ejb.jar:main" from Service Module Loader]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:198)
at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:363)
at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:351)
at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:93)
... 185 more
I looked at Wildfly 8.1 ClassNotFound org.apache.http.conn.ClientConnectionManager, but jboss-deployment-structure.xml described there is not working here.
I tried various combinations of things in the POM file, but I'm not getting anywhere with that.
The class fails when being constructed, so the import statements are causing problems.
I haven't been able to get access to the module or get the needed jar files to be deployed into the ear lib directory.
EDIT: I'm using JBoss Developer Studio. I seem to be making some progress in that if I copy my opca-ear.ear file to the deployment directory manually then the httpclient and httpcore jars get deployed, but they don't if I deploy from jbstudio, so I guess it's an issue with jboss-modules.jar deployments. Not being able to debug/deploy from jbstudio is going to be a pain. Httpclient and httpcore are in my opca-ear.ear file in the lib directory, as well as the ejb/target/opca-ear/lib directory.
If I could get something like jboss-deployment-structure.xml or perhaps an entry in the a manifest file working so that wildfly provides the client access to the org.apache.httpcomponents resources then I wouldn't have to worry about jboss-modules.jar.
SOLUTION: As noted in the accepted answer, jboss-deployment-structure.xml only works on "full" deployments, so I used a manifest.mf entry
Dependencies: org.apache.httpcomponents
and updated the maven-ejb-plugin to use it:
<artifactId>maven-ejb-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<!-- Tell Maven we are using EJB 3.1 -->
<ejbVersion>3.1</ejbVersion>
<archive>
<manifestFile>${basedir}/src/main/resources/META-INF/manifest.mf</manifestFile>
</archive>
</configuration>

It all depends on which code needs it. The jboss-deployment-structure.xml you are mentionning isn't going to work if you don't declare your 'full' application.
Maybe you should just add a Manifest with the entry Dependencies: org.apache.httpcomponents in the jar/war that needs it.
Tkae a look at https://docs.jboss.org/author/display/WFLY10/Class+Loading+in+WildFly

Related

How to use OSGI Embed-Dependency for common 3rd party JAR-s

I have a Liferay system with several portlets. Most of these portlets have redundant JSF related JAR-s in them so I would like to remove the redundancy, and create an OSGI bundle for the commonly used JAR-s.
The idea would be that all of my portlets would use this common bundle as a dependency.
After some reading about I ended up with something similar in my maven pom:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.4</version>
<extensions>true</extensions>
<configuration>
<remoteOBR>true</remoteOBR>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.name}</Bundle-Name>
<Bundle-Vendor>${project.organization.name}</Bundle-Vendor>
<Import-Package>
!sun.reflect,......,*
</Import-Package>
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
<Embed-Transitive>true</Embed-Transitive>
</instructions>
</configuration>
</plugin>
And I ended up with the following bundle jar:
My Manifest:
Manifest-Version: 1.0
Bundle-SymbolicName: my-common-bundle
Built-By: pjaloveczki
Bundle-ManifestVersion: 2
Bnd-LastModified: 1537882770915
Embed-Dependency: *;scope=compile|runtime
Import-Package: com.liferay.portal.kernel.exception,com.liferay.portal
.kernel.language,com.liferay.portal.kernel.model,......,org.w3c.dom.styleshe
ets,sun.misc
Tool: Bnd-1.15.0
Bundle-Name: my-common-bundle
Bundle-Version: 1.0.0
Bundle-ClassPath: .,sac-1.3.jar,...all..my..dependecies...,com.liferay.faces.bridge.api-4.1.0.jar
Ignore-Package: net.sf.cglib.proxy,..all..ignored..packages...javax.ejb
Embed-Transitive: true
Created-By: Apache Maven Bundle Plugin
Build-Jdk: 1.8.0_171
Content:
From what I can see, this is exactly what I needed, at least this is how I pictured it.
In my consuming portlet I added the following to my manifest:
Require-Bundle: my-common-bundle;bundle-version="1.0.0"
I figured something like this should work, however I am obviously wrong as when I try to deploy my portlet one of the classes is not being found provided by the common bundle:
java.lang.ClassNotFoundException: org.richfaces.webapp.ResourceServlet cannot be found by MyPortlet
On the other hand if I add the following to my common bundle:
<Export-Package>org.richfaces.webapp</Export-Package>
The class is found, but I am ended up with this:
So essentially I have the class twice once in the JAR and once flattened out, even though it's kind of starting to work.
There are several reason I don't like this approach:
I would prefer using structured jars because I consider it cleaner
Most of these jars contain configuration files that could overlap if I flatten everything out
There must be a way to use embedded jars properly since otherwise this feature would not exist
Can anyone help, what it the proper way to use these embedded jars in an OSGI without having to flatten them out?
Thank!
Peter
EDIT:
It seems that classes are being deployed fine and are resolved after I've added
<_exportcontents>!org.apache.commons.logging,*</_exportcontents>
however I am getting different types of errors which I am not getting when I put my JARs in my portlets.
Previously I was getting ClassNotFoundErrors and such, now I am getting:
java.lang.NullPointerException
at javax.faces.CurrentThreadToServletContext.getFallbackFactory(CurrentThreadToServletContext.java:79)
at javax.faces.FactoryFinderInstance.getFactory(FactoryFinderInstance.java:551)
at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:283)
at javax.faces.webapp.FacesServlet.init(FacesServlet.java:358)
java.lang.NullPointerException
at javax.portlet.faces.GenericFacesPortlet.getBridgeClassName(GenericFacesPortlet.java:193)
at javax.portlet.faces.GenericFacesPortlet.getBridge(GenericFacesPortlet.java:762)
at javax.portlet.faces.GenericFacesPortlet.init(GenericFacesPortlet.java:448)
at com.liferay.portlet.InvokerPortletImpl.init(InvokerPortletImpl.java:297)
It seems to me classes are loaded, but the JAR manifests are not being processed or something similar. Any ideas?
you can use <_exportcontents> instruction to export the content without duplication, more about it here
I would like to point out that creating fat jars is against the very idea of OSGi, also, this is going to be a nightmare to maintain when your code evolves.
Ideally you would want to have a separate bundle for each dependency. They should be deployed and maintained separately.

eclipse: external CDI in EJB module: NoClassDefFoundError

My current project consisting of a war and ejb module, is using a jar (incorperated via maven). This jar contains a CDI component which, when I inject this in the war module it works as expected, but when I inject this in my ejb module I get a NoClassDefFoundError during startup from my WAS 8.5 in eclipse (full profile).
When I start the server first, add the inject later and republish it seems to work. Also when I use Liberty profile it works. Also on Z/os and IPAS it works as expected.
I think it might has something todo with classloading, but have no idea how to solve this properly.
Using Eclipse Neon, WAS 8.5.5.11 full profile , jee6
Project is using java 8 while the component is using java 6
This is the first part of the stacktrace:
[13-9-17 14:54:26:589 CEST] 0000003e InjectionProc W CWNEN0047W: Resource annotations on the fields of the BestelFacade class will be ignored. The annotations could not be obtained because of the exc
eption : Logger
at java.lang.Class.getDeclaredFieldsImpl(Native Method)
Thanks
I found a way to get the job done, but I'm not sure if this is a proper solution or just a workaround while masking the real problem.
When I take a look at the ear module assembly I see in the source column c:/ws/.../jar and in the deploy path lib/jar
when I change the source into /..ear/target/../jar it works
Try setting the <bundleDir>/</bundleDir>
This will place the external jar/ejb not in lib, but in the root.
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
...........
<defaultLibBundleDir>lib</defaultLibBundleDir>
<modules>
<jarModule>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<bundleDir>/</bundleDir>
</jarModule>
</modules>
</configuration>
</plugin>

Wildfly Class Loading issue with jca resourceadapter

I am trying to deploy an ear application on wildfly 9 that tries to connect to MQ and to a JCA resource adapter.
Structure of my ear file
myApp.ear
|--lib/
|----Spring.jar (Multiple jars for different modules needed)
|----META-INF/
|--myAppEJB.jar (EJB project)
|--myAppWeb.war
|--jboss-deployment-structure.xml
The JCA resource adapter (myCompConnector.rar) is packaged as a rar and deployed with an ra.xml inside it. myCompConnector uses two jars supportingjar1.jar and supportingjar2.jar and are packaged inside the rar file.
Structure of my MyCompConnector.rar:
MyCompConnector.rar
|--META-INF
|--supportingjar1.jar
|--supportingjar2.jar
|--MyCompConnector.jar
my application also uses the classes that are in myCompConnector but is compiled with myCompConnector.jar. I make the build using maven 3 and I do not package the myCompConnector.jar or any depending jars.
If i deploy it says that NoClassDefFoundError for a class in supportingjar1.jar, So i add ONLY the supporting jars by putting in the lib of the ear myApp.ear (making the war a skinny war as well supporting jars are only used in the EJB project's pom file not in WAR)
Then If i deploy it on wildfly it says NoClassDefFoundError MyCompConnectorInspector.java and ClassNotFoundError MyCompConnectorInspector.java. MyCompConnectorInspector is a class in the MyCompConnector.jar which is also present in MyCompConnector.rar.
Caused by: java.lang.NoClassDefFoundError: Lcom/myComp/MyCompConnector/MyCompConnectorInspector ;
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2317)
at java.lang.Class.getDeclaredFields(Class.java:1762)
at org.jboss.as.server.deployment.reflect.ClassReflectionIndex.<init>(ClassReflectionIndex.java:57)
at org.jboss.as.server.deployment.reflect.DeploymentReflectionIndex.getClassIndex(DeploymentReflectionIndex.java:66)
... 10 more
Caused by: java.lang.ClassNotFoundException: com.mycomp.MyCompConnector.MyCompConnectorInspector from [Module "deployment.myApp-1.3.ear.myAppEJB-1.3.jar:main" from Service Module Loader]
at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:205)
at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:455)
at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:404)
at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:385)
at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:130)
... 15 more
So I add MyCompConnector.jar as well in the lib folder of the ear file
(So now my MyCompConnector.rar is loaded and MyCompConnector.jar is loaded from the lib folder in the ear file)
If i deploy now it says ClassCastException: com.comp.MyCompConnector.MyCompConnectorInspector.java cannot be cast to com.comp.MyCompConnector.MyCompConnectorInspector.java
which is true as it is loaded from two sides. Now i cannot remove the rar resource adapter so if i remove the jar file from the lib of the ear it says the above mentioned error: NoClassDefFoundError MyCompConnectorInspector.java and ClassNotFoundError MyCompConnectorInspector.java.
So now i am in a fix. If i add the jar to remove the NoClassDefFoundError it will give me classcast exception.
In the event of the class cast exception I see that MyCompConnectorInspector is loaded from the RAR's MyCompConnector.jar (when i do -verbose=class) but when i remove the jar file from the myApp/lib/ then i do not see MyCompConnectorInspector being loaded from the RAR's MyCompConnector.jar.
my jboss-deployment-structure in the ear file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="MyCompConnector.rar" />
<module name="javax.api"/>
<module name="javax.transaction.api"/>
<module name="javax.jms.api"/>
<!--<module name="com.compConnector.supportingjar1"/>
<module name="com.compConnector.supportingjar2"/> -->
</dependencies>
</deployment>
</jboss-deployment-structure>
How can I make the rar deployment seen as something that my ear file should refer to as a library as well as all he dependent libraries included in the RAR.
one more question: when i deploy a RAR, is it technically a module. (Modules are a new concept for me from Jboss 5 or websphere which i have worked with before)
One funny thing that I have seen, If i use
<module name="deployment.MyCompConnector.rar" />
that I have seen in some expamples in any Resource Adapter definition it does not load at all. if i remove the deployment. then it creates the jndi name for it and binds it. I dont know if it is related tough.
Any help will be appreciated. I am new to Wildfly so I am still learning its tricks.
Thanks.
P.S : I even tried to do
<global-modules>
<module name="deployment.MyCompConnector.rar" />
</global-modules>
but it only gave me Failed to load module: deployment.MyCompConnector.rar:main
Then ModuleNotFoundException : deployment.MyCompConnector.rar:main
i deployed the rar through the console and not through creating a module in the modules folder and then added a connection definition in the resourceAdppaters in the standalone-full.xml . this is the same I deployed the wmq.jmsra.rar file and then made the connection definition.
It seems there is an issue in Wildfly when a resource adapter is being referenced from within a jar (in modules) or from a jar inside an ear. In a war it works fine.
I may be mistaken when i assume there is an issue in WF9. but i made it to work. I had this issue in case of an ear as well as a jar.
in case of ear I simply converted the ear into a war and pluggged my EJBs into the War's WEB-INF/lib folder as a jar. and it worked without any issues.
Hopefully it will help some one who has a RAR resource adapter and is using the resource adapter'sconnection classes as library inside the EJBs of an ear project.

Glassfish 3.1b41 - JDO83008: CMP Compilation failed: class file not found

we have an "old" JavaEE Application, which we want to port from the old Sun Application Server 9.1 to the current Glassfish 3.1. We updated the deployment descriptor xml files (renamed them, updated DocType, validated against DTD, nothing else). But when we try to the deploy into the GF3.1 we get this error:
JDO83008: CMP Compilation failed:
C:\workspace\glassfish31eclipsedefaultdomain\generated\ejb\archivetool-app-1.9.5\archivetool-ejb-1.9.5_jar\de\ems\archivetool\ejb\metadata\cd\eb\CdBean_821611534_ConcreteImpl.java:10:
cannot access de.ems.archivetool.ejb.framework.AbstractCMPBean
class file for de.ems.archivetool.ejb.framework.AbstractCMPBean not found
C:\workspace\glassfish31eclipsedefaultdomain\generated\ejb\archivetool-app-1.9.5\archivetool-ejb-1.9.5_jar\de\ems\archivetool\ejb\productdata\product\eb\ProductionLibraryBean40992531_ConcreteImpl.java:416:
cannot find symbol
symbol : class EBSBusinessException
location: package de.ems.archivetool.ejb.framework
WARNUNG: JDO83004: CMP Compilation failed. See log for details.
SCHWERWIEGEND: Exception while invoking class org.glassfish.ejb.startup.EjbDeployer prepare method
SCHWERWIEGEND: Exception while invoking class org.glassfish.javaee.full.deployment.EarDeployer prepare method
SCHWERWIEGEND: Exception while preparing the app
SCHWERWIEGEND: JDO83004: CMP Compilation failed. See log for details.
org.glassfish.deployment.common.DeploymentException: JDO83004: CMP Compilation failed. See log for details.
But we can still deploy in the old SUN App Server.
The application consists of 4 modules and a build module. Generally, the .ear file, consisting of the two EJB modules, one WAR module and one JAR module, is build with Maven without problems (UnitTest succeed etc).
(pom.xml and the resulting application.xml)
So, everything builds fine, but when we try to deploy the application to GF3.1 we get the "class file not found" error. The classes which are not found are within the JAR module and contain base classes for the EJB modules.
Does anyone has a starting point?
Regards,
Andreas
Ok, after hours of googeling, I finally found the exact answer to this problem here.
The important part is:
The Java EE 6 specification imposes strict rules about which JAR files
are visible from an enterprise archive (EAR) file. Refer to section
EE.8.3.3; specifically, application client modules should not have
access to any EJB JAR file unless the application client JAR file's
manifest Class-Path refers to the EJB JAR file(s) explicitly.
This is a change from GlassFish Server v2, in which application
clients automatically had access to all EJB JAR files in the EAR file
and all JAR files at the top level of the EAR file. To comply with the
stricter specification language, GlassFish Server 3.0.1 cannot
automatically provide application clients with access to these JAR
files.
What you have to do is, let maven put the jar (and other dependencies) into a library folder in the ear container. You do this by adding this to your ear pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
//here starts the important part
<defaultLibBundleDir>lib</defaultLibBundleDir>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
//end of important part
<modules>
<jarModule>
<groupId>gID</groupId>
<artifactId>aID</artifactId>
</jarModule>
//etc some more ebjs, war, ...
</modules>
This will put the jar module into a folder lib, and all depending ejbs will get the Class-Path entry in their MANIFEST.MF.
Hope that helps some of you with the same problem.

How to dynamically load Java classes at Runtime in OSGI framework?

We are performing a POC in our project, where in we send SOAP based request and correspondingly get a SOAP response from a web service. We aim to leverage webservices template (client side API) provided by spring framework in our application. As per our architecture, we create an OSGI compliant bundle (for our code that uses webservices template API to interact with the web service) which is then deployed into the Apache Felix container. We have also installed all the dependent OSGI compliant bundles in the Felix container so that all the dependencies are resolved.
As per the webservices template, the default Web Service Message sender is HttpUrlConnectionMessageSender which is dynamically loaded at run time by the class loader. As per my understanding, we are getting the below exception because the Felix container is not able to load the class from the dependent OSGI bundle (web services bundle contains the HttpUrlConnectionMessageSender).Please refer to the exception logs below.
* org.springframework.beans.factory.BeanInitializationException: Could not find default strategy class for interface [org.springframework.ws.transport.WebServiceMessageSender]; nested exception is java.lang.ClassNotFoundException:org.springframework.ws.transport.http.HttpUrlConnectionMessageSender at org.springframework.ws.support.DefaultStrategiesHelper.getDefaultStrategies(DefaultStrategiesHelper.java:126)
at org.springframework.ws.support.DefaultStrategiesHelper.getDefaultStrategies(DefaultStrategiesHelper.java:90)
at org.springframework.ws.client.core.WebServiceTemplate.initMessageSenders(WebServiceTemplate.java:320)
at org.springframework.ws.client.core.WebServiceTemplate.initDefaultStrategies(WebServiceTemplate.java:306)
at org.springframework.ws.client.core.WebServiceTemplate.<init>(WebServiceTemplate.java:143)
at test.soapservice.service.SOAPServiceImpl.<init>(SOAPServiceImpl.java:40)
at test.soapservice.service.SOAPServiceActivator.start(SOAPServiceActivator.java:17)
at org.apache.felix.framework.util.SecureAction.startActivator(SecureAction.java:641)
at org.apache.felix.framework.Felix.activateBundle(Felix.java:1977)
at org.apache.felix.framework.Felix.startBundle(Felix.java:1895)
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:944)
at org.apache.felix.gogo.command.Basic.start(Basic.java:729)
Caused by: java.lang.ClassNotFoundException: org.springframework.ws.transport.http.HttpUrlConnectionMessageSender
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:211)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:164)
at org.springframework.ws.support.DefaultStrategiesHelper.getDefaultStrategies(DefaultStrategiesHelper.java:114)
As per my understanding,Felix container is unable to dynamically load the class using ClassUtils.forName() which exists in another bundle. I see this as a collaboration issue where the current bundle has a different class loader as opposed to class loader of dependent bundle.
Did someone from this community have encountered the same exception? If yes, then what were steps taken by you to resolve the run time class dependency? Please share your thoughts/pointers to resolve the above issue.A quick response would be highly appreciated and may help us to make our POC successful.
Thanks in advance,
Mridul Chopra
Classloading in the form of Class.forName() is not a problem in any OSGi container. You problem here is that the MANIFEST.MF file does not contain the right import declarations. One bundle should export the org.springframework.ws.transport package, while your bundle should import the same package.
If you are using Maven to build your bundle, you can use the Felix Bundle Plugin to generate the right manifest information.
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Private-Package>my.private.package.*</Private-Package>
</instructions>
</configuration>
</plugin>
</plugins>
This should inspect your code and add imports for anything that is not inside your "private" package scope. One other thing you should do to make this work is to set the packaging type to bundle.
<packaging>bundle</packaging>
But, the examples above is when you are using Maven as a build tool. If you are using Gradle, you can use the Gradle OSGi plugin to build manifest. Or, if using Ant you can use SpringSource Bundlor project (btw, which also has a Maven plugin).

Categories

Resources