JBoss 7.x SAR archive class loading issue - java

I am trying to build a sar archive that contains an MXBean and deploy it in JBoss 7.
Until recently I had a problem referencing classes from other libraries in my MXBean class because JBoss wouldn't load those libraries no matter where in the SAR archive I'd put them.
I found out that one can configure the classpath of a SAR through the jboss-deployment-structure.xml file placed in META-INF. My version of this file looks like this:
<jboss-deployment-structure>
<deployment>
<resources>
<resource-root path="management.api.jar" />
</resources>
</deployment>
Now the classes from the "management.api.jar" are loaded.
The problem I am now facing is the following: If the interface of the MXBean is stored in the management.api.jar and the class implementing it is directly in the SAR archive, then, when JBoss reads the jboss-service.xml and tries to create the mxbean it yields a ClassNotFoundException pointing to the interface (that is in the management.api.jar). Hence, although classes from the external jar are loaded ok (i tested this by actually invoking a method that referenced a class from the jar and it worked), it seems that when JBoss registers the bean, it doesn't go through the whole classpath as defined in the jboss-deployment-structure.xml.
I am currently stuck and I suspect this to be a bug in the way JBoss handles the class loading. If anyone knows a way around this (other than taking the interface out of the jar and putting it in the SAR archive directly, cause this will break the whole "api" idea) please let me know.
Thanks!

When I understand it right, the management api should be used in different projects and should be global in the server. A simple workaround can be to put your jar in the module-folder of your jboss. Therefor create a module.xml like this below and put it with your jar in a extra-folder main in the jboss7/modules/yourfolder.
(In the module folder the jboss 7.1 stores all libs.)
<!-- defines the name of your lib -->
<module xmlns="urn:jboss:module:1.1" name="yourfolder">
<resources>
<!-- the jar in your main folder-->
<resource-root path="management.api.jar"/>
<!-- Insert resources here -->
</resources>
<dependencies>
...dependencies of your api
</dependencies>
</module>
Then you can load the dependency from your sar-jboss-deployment-structure by
<dependencies>
<module name="yourfolder" slot="main" export="true"/>
</dependencies>
The slot=main means that you use the the folder main, you can add different versions, like 1.1 and so on. Main is also the default slot, you can leave it out.
If your folder-structure goes into deep, simple define and include the modules like packages.
In that way you can define api.jars in the jboss and reference it from several projects.

Related

Choose a library version between Jboss modules and project dependencies

I'm trying to make a sign operation with a XML file. In this process, I use the xmlSec 1.5 library. If I run the code in a local test the process finishes successfully.
However, if I deploy the code in a war in a Jboss 7.1, my dependency with xmlSec 1.5 is override by Jboss by its module dependency "xmlsec-2.0.8.redhat-1", and the sign process fails.
For client's petition, I can exclude the xmlsec Jboss module, but I cannot use it to sign.
So, the problem is: how could I specify a given library version to be used only in a part of the code?.
In this case, the path of both dependencies are the same: org.apache.santuario, so, I cannot use it in order to specify the library.
I'm trying to use a provider for signing, but, again, Jboss override my xmlsec-1.5 security provider for its xmlsec-2.0.8 security provider. There exists some way to instanciate a provider and adds it to the set of java providers in order to replace the Jboss one?
You can exclude the JBoss provided dependency using jboss-deployment-structure.xml file which you need to place under the WEB-INF directory of your war. You have to specify the exclusion dependencies something like below.
<jboss-deployment-structure>
<deployment>
<exclusions>
<module name="$LIBRARY_OR_MODULE_YOU_WANT_TO_EXCLUDE"/>
</exclusions>
</deployment>
e.g. <module name="org.apache.santuario.xmlsec"/>

JBoss: Native Library sqljdbc_auth.dll already loaded in another classloader

UPDATE: This unanswered question on jboss forums, is another way of describing my exact problem: https://developer.jboss.org/thread/199888
Original post:I am trying to make integrated authentication work on web applications deployed to JBoss 7.x. I have successfully made one work, by copying sqljdbc_auth.dll into either Windows/System32, or {java location}/jre/bin. However, if two or more applications are running, I will get an error saying that Native Library sqljdbc_auth.dll already loaded in another classloader
I know why this error is happening, and this question and answer has a Tomcat solution. But I can't make it work in JBoss. Actually, putting the dll inside the jboss/bin folder gives the exact same error as before:
Failed to load the sqljdbc_auth.dll cause :
Native Library C:\Jboss-eap-7.0\bin\sqljdbc_auth.dll already loaded in another classloader
How do I configure JBoss, and/or place the sqljdbc_auth.dll?
My deployments are not located under any module, or named server instance. I think it's simply called standalone
I have tried this approach as well, but I can not figure out where to put the jar file, in the JBoss directories. I tried deploying it as a deployment like the web applications, and I tried copying it into the lib folder, under standalone. No success.
EDIT:
I am trying to implement a global module, as per the answer posted, but get following error now:
14:00:25,333 ERROR [stderr] (ServerService Thread Pool -- 121)
java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver from
[Module "deployment.MyWebapp.war:main" from Service Module Loader]
I assume you must have created a module for sql jdbc driver something like this.
<module xmlns="urn:jboss:module:1.3" name="com.microsoft.sqlserver">
<resources>
<resource-root path="sqljdbc.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.transaction.api"/>
</dependencies>
</module>
And added this module as dependency to each of your deployed application.
I would suggest to declare this module as global module by editing the standalone.xml file like this ..
<subsystem xmlns="urn:jboss:domain:ee:4.0">
<global-modules>
<module name="com.microsoft.sqlserver" slot="main"/>
.
.
</global-modules>
.
.
</subsystem>
And remove the dependency to this module from your individual applications.

MongoDB driver as a core module for connection pooling in Jboss

Can anyone help me in configuring MongoDB driver as a core module for connection pooling in JBoss. Please refer to following step which I have tried after reading few posts.
Created a directory EAP_HOME/modules/com/mongodb/main/ and copy the mongodb-driver-3.4.0-rc1.jar (rc1 version because stable version 3.3.0 doesn't contain MongoClientFactory.class) and created module.xml file as below.
<module xmlns="urn:jboss:module:1.3" name="com.mongodb">
<resources>
<resource-root path="mongodb-driver-3.4.0-rc1.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.transaction.api"/>
</dependencies>
</module>
Then, Added MongoDB driver into standalone.xml file, please refer to the following properties I have added into standalone.xml file.
<driver name="com.mongodb" module="com.mongodb">
<xa-datasource-class>com.mongodb.client.jndi.MongoClientFactory</xa-datasource-class>
</driver>
After all these configuration I have started JBoss server and getting "Unable to find driver class name in "com.mongodb" jar" whereas jar is present and also contains MongoClientFactory datasource class.
I did not find a freeware solution to enable xa-datasource driver configuration.
Accordingly to Red Hat JBoss Enterprise Application Platform 7 supported configurations, MongoDB isn't currently being supported:
https://access.redhat.com/articles/2026253
You can try these approaches below (using proprietary drivers):
https://www.progress.com/jdbc
http://www.unityjdbc.com/mongojdbc/mongo_jdbc.php (trial for 15 days)
However, you can try configuring a JNDI interface using MongoDB java driver:
http://mongodb.github.io/mongo-java-driver/3.3/driver/reference/connecting/jndi/#examples
"A MongoClient instance will be accessible via the JNDI name mongodb/MyMongoClient in the java:comp/env context."
Answering your question, maybe you'll need to put the *.jar inside this directory:
modules/system/layers/base/org/mongodb/main

Class loading issue with JBOSS 6.3.0

I'm running the following class loading issue with JBOSS.
My JBOSS's module.xml:
<module xmlns="urn:jboss:module:1.0" name="com.example">
<resources>
...
<resource-root path="spring-amqp-1.4.6.RELEASE.jar"/>
...
</resources>
</module>
When org.springframework.amqp.support.converter.DefaultJackson2JavaTypeMapper:getClassIdType(String classId) is called
MessageConversionException: failed to resolve class name... is thrown by
ClassUtils.forName(classId, getClass()
.getClassLoader())
Debugging getClass().getClassLoader() returns ModuleClassLoader for Module "com.example:main".
So it seems the issue is the class I'm deserializing is not in module com.example (defined in module.xml) so it throws that exception
Myjboss-deployment-structure.xml has com.example as a dependency:
<dependencies>
<module name="com.example">
<imports>
<include path="META-INF**"/>
</imports>
</module>
</dependencies>
I can fix this problem if I remove spring-amqp-1.4.6.RELEASE.jar from module.xml and add spring-amqp to my build.gradle. Problem is module.xml is shared across my org and I can't change that.
So how can I fix this? Appreciate any help.
A stacktrace (and some more code) to reproduce would be nice. I am not familiar with amqp.
In https://github.com/spring-projects/spring-amqp/blob/master/spring-amqp/src/main/java/org/springframework/amqp/support/converter/DefaultJackson2JavaTypeMapper.java at line 56, ClassUtils.forName(classId, getClass().getClassLoader()) gets called, but can't find the class.
In JBoss, module classloaders are seperated from application classloaders. In your application, you can access all classes from the module, but the module can't access your WAR or JAR classes.
So, this is exception is thrown, because your module, tries to load a class from your application, which is not visible in the module classloader. But if you add the amqp-jar to your application, it works, because they share the same classloader.
If you want/need amqp in a module, you need to create a module with your application common-classes and add it to your module as a dependency. But also note, you can't add the common.jar to the application.jar anymore to avoid classCastExceptions.
I don't know, how amqp is used, but probably, you need to create multiple modules to use it with different common.jars.
For more information about jboss classloading, i can refer you to:
http://www.mastertheboss.com/jboss-server/jboss-as-7/discover-jboss-as-7-modularity
https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6/html/Development_Guide/chap-Class_Loading_and_Modules.html

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.

Categories

Resources