Defining 3rd-party library in Wildfly as Module without including its dependencies - java

I am developing a web application for Wildfly 9 using a quite standard stack (Java 8, JAX-RS, Hibernate etc).
Now I have to use a third-party library, which has various dependencies to libraries version of Log4j etc. Since I don't want to analyze if these dependencies are compatible with the libraries in the current web-app, I thought it would be a good idea to define a Module in Wildfly. Something like
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="foo.md">
<resources>
<resource-root path="foo-1.0.jar" />
<resource-root path="log4j-1.2.12" />
<resource-root path="concurrent-1.0.jar" />
<!-- etc -->
</resources>
</module>
Then I could include the module using jboss-deployment-structure.xml
<?xml version="1.0"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<dependencies>
<module name="foo.md" >
<imports>
<include path="foo" />
<exclude path="bar" />
</imports>
</module>
</dependencies>
</deployment>
This way, I could isolate the dependencies of the third-party library and don't have to analyze if they are compatible with my app without using (imo heavy-weight) approaches like OSGi which would require more changes to the app or waiting for Jigsaw.
Is this a valid approach?

Related

Jboss EAP 7 - How to exclude implicit modules from deployment (javax.jms)?

I didn't think I would end up here but after a lot of Google and StackOverflow searches here I'm.
This is my exact problem except that I can't afford to make code changes.
The WAR I'm trying to deploy includes a JMS library (i.e. javax.jms, which I cannot exclude form the WAR.) which is already loaded by Jboss EAP 7 by default. The path to jar is something like this jboss/modules/system/layers/base/javax/jms/api/ain/jboss-jms-api_2.0_spec-1.0.0.Final-redhat-1.jar. Because of this two different versions of the same classes loading I'm getting ClassCastException.
org.apache.activemq-ra.ActiveMQConnectionFactory cannot to be cast to javax.jms.ConnectionFactory
So, I want Jboss to NOT load javax.jms so that my application can use the JAR included with the WAR.
So, I was wondering if there was any way to exclude the module globally (for all WAR deployments).
Excluding it per deployment would work too. And I do realize it can be acheivd using jboss-deployment-structure.xml but I can't get it to work.
Here is what I tried:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure
xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<exclude-subsystems>
<subsystem name="javax" />
<subsystem name="javax.jms" />
</exclude-subsystems>
</deployment>
</jboss-deployment-structure>
and
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure
xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<exclusions>
<module name="javax" />
<module name="javax.jms" />
<module name="javax.jms.api" />
</exclusions>
</deployment>
</jboss-deployment-structure>
I placed the file in WEB-INF directory. It didn't work. It still loaded the JMS class from modules folder of Jboss EAP. So, how do I correctly do this?
The correct jboss-deployment-structure.xml is here:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<exclude-subsystems>
<subsystem name="messaging-activemq"></subsystem>
</exclude-subsystems>
<exclusions>
<module name="javax.jms.api"></module>
</exclusions>
</deployment>
</jboss-deployment-structure>
This way you exclude both messaging subsystem and the JMS api.
You should remove the JMS API JAR from your deployment. You can still keep the JMS implementation JAR in your deployment but that should probably end up in a RAR, preferably outside your deployment.
This link has some things you could try.
Notably:
I think the problem is that activemq-all-5.4.2.jar contains javax.jms.*. Your deployment already gets this implicitly from the javaee.api module (see more information about implicity module dependencies here). I don't think it is appropriate for an application module/jar to package Java EE interfaces. You can try simply deleting the javax directory from activemq-all-5.4.2.jar or using a different set of ActiveMQ jars in your module to limit it to only what you need.
and/or altering your module.xml for ActiveMQ
<module xmlns="urn:jboss:module:1.0" name="activemq">
<resources>
<resource-root path="activemq-all-5.4.2.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
</dependencies>
</module>
There appears to be a method to embed ActiveMQ in Jboss as well, if you're interested. I won't pull out information from that article, as it doesn't answer the original question.

JBoss - How can to exclude javax.validation in jboss-deployment-structure?

I have .war using Jersey REST, and it works in tomCat. But I need to run my .war in JBoss 6.4.0 which causes an exception
java.lang.RuntimeException: java.lang.NoSuchMethodError:
javax.validation.spi.ConfigurationState.getParameterNameProvider()
because JBoss uses old version javax.validation, and I need to exclude javax.validation from deployment of JBoss.
I create jboss-deployment-structure.xml in WEB-INF of .war:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<exclude-subsystems>
<subsystem name="resteasy" />
<subsystem name="jpa"/>
<subsystem name="org.hibernate" />
<subsystem name="org.hibernate.validator" />
</exclude-subsystems>
<exclusions>
<module name="javaee.api" />
<module name="javax.ws.rs.api"/>
<module name="org.jboss.resteasy.resteasy-jaxrs"/>
<module name="javax.validation.api"/>
<module name="org.hibernate"/>
<module name="org.hibernate.validator"/>
</exclusions>
</deployment>
</jboss-deployment-structure>
This helped me to exclude javax.ws.rs, but How can to exclude javax.validation? Help me, please
Ok, so You need to exclude not only
<module name="javax.validation.api"/>
itself, but also modules that are dependent on javax.validation.api module. The easiest way to see which modules are dependent on javax.validation.api and force it to be included, even though it was excluded, is to search your .xml files in
JBOSS_DIRECTORY/modules for javax.validation.api, the modules that are dependent have something like that in module.xml:
<dependencies>>
<module name="javax.validation.api"/>
...
And those modules need to be excluded as well. For me - I also needed to exclude:
<module name="javax.faces.api"/>
<module name="org.jboss.resteasy.resteasy-hibernatevalidator-provider"/>
And then, javax validation eclusion was working :)
So, it is something! May be help to someone:
Library javax.validation.api in JBoss - belongs to Implicit module, documentation about implicit module: implicit module dependencies
So implicit modules are Automatic Dependencies, and their can exclusion, about this: class lading and automatic dependencies - part about Automatic Dependencies:
Automatic dependencies can be excluded through the use of jboss-deployment-structure.xml. But this is not work! :(, and JBoss has bug with similar library javax.persistence, and it bug open in tasks.
So - what can to do?
Update JBoss to 7.0.0 version, but now just Alpha and Beta versions :(
Replace old javax.validation.api .jar on new version .jar
(in EAP-6.4.0/modules/system/layers/base/javax/faces/api/main)
Add custom version, and it tangled:
change default config in EAP-6.4.0/modules/system/layers/base/javax/faces/api/main module.xml file, in line <module name="javax.validation.api" export="true"/> remove option export="true", result: <module name="javax.validation.api"/> This changed to allow you add a new custom library javax.validation.
And create custom folder with name 1.1 in EAP-6.4.0/modules/system/layers/base/javax/validation/api, put in 1.1 folder new javax.validation .jar and model.xml.
model.xml:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="javax.validation.api" slot="1.1">
<resources>
<resource-root path="validation-api-1.1.0.Final.jar"/>
</resources>
<dependencies>
<module name="org.jboss.logging"/>
</dependencies>
</module>
params:
slot - name custom folder (1.1),
path - path to .jar library
Last: add module to jboss-deployment-structure.xml in project:
<dependencies>
<module name="javax.validation.api" slot="1.1" export="true"/>
</dependencies>

are ejb and jars subdeployments in an EAR

I've been having problems with jboss/logback and I made a jboss-deployment-structure.xml and it looks like this
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<ear-subdeployments-isolated>false</ear-subdeployments-isolated>
<deployment>
<!-- Exclusions allow you to prevent the server from automatically adding
some dependencies -->
<exclusions>
<module name="org.apache.commons.logging" />
<module name="org.slf4j" />
<module name="org.slf4j.ext" />
<module name="org.slf4j.impl" />
<module name="org.apache.log4j" />
</exclusions>
</deployment>
</jboss-deployment-structure>
this is in the META-INF folder of the EAR, but now I've been thinking... the EAR also has a lib folder that has:
slf4j-api.jar,
logback-classic.jar,
logback-core.jar, and
log4j-over-slf4j.jar
as well as the other two other ejb projects wrapped up in it during deployment time.
my question is, do I have to specify the jars and other other ejb projects as sub-deployments in the jboss-deployment-structure.xml??
also, the jboss-deployment-structure.xml has been basically ignored everytime I deploy the ear and start the server, i know this because the server still is accessing the exclusions i have declared, is the xml in the right spot in the meta-inf of the ear?
thank you for the help
Yes I added the jars as subdeployments and fixed errors

How to configure Oracle AQ library as a Wildfly 8 module?

I'm currently stuck in the middle of a JBoss migration project from version 4.2.2GA to Wildfly 8.0.0.Final. The project uses the Oracle OCI driver for database access and Oracle AQ with it. Now, I'm starting Wildfly with the environment variable 'LD_LIBRARY_PATH' set to the location where the OCI native implementations reside and everything works fine, except AQ. This is the error I get when the AQ API is used: oracle.jms.AQjmsSession.ociinit([JIIZSII)J: java.lang.UnsatisfiedLinkError: oracle.jms.AQjmsSession.ociinit([JIIZSII)J
This is my module:
path: ${WILDFLY_HOME}/modules/oracle/aq/api/main
contents: aqapi.jar, module.xml
module.xml:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="oracle.aq.api">
<resources>
<resource-root path="aqapi.jar" />
</resources>
<dependencies>
<module name="javax.api" />
<module name="javax.jms.api" />
<module name="oracle.jdbc" />
</dependencies>
</module>
So the question now is, what is the reason Wildfly does not propagate the 'LD_LIBRARY_PATH' to the module classloader?
For older JBoss versions I found this issue: https://issues.jboss.org/browse/SOA-3570 which propagates to put the aqapi.jar into the server lib folder as we are doing so for JBoss 4. But how can I solve this issue for Wildfly? Any Ideas?
Thanks!
After a long journey through the shallows of the internet and many tries a colleague of mine finally found a solution.
The solution was to combine both modules to one jdbc/aq module looking so:
path: ${WILDFLY_HOME}/modules/oracle/jdbcaq/main
contents: ojdbc5.jar, aqapi.jar, orai18n.jar, module.xml
module.xml:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="oracle.jdbcaq">
<resources>
<resource-root path="aqapi.jar" />
<resource-root path="ojdbc5.jar"/>
<resource-root path="orai18n.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.jms.api" />
<module name="javax.transaction.api"/>
</dependencies>
</module>
I think this is somehow related to the module classloaders of wildfly. Maybe the communication between both modules (jdbc and aq) requires the native implementations to be loaded by the same classloader which causes this error when using two modules instead of a single one.
Instead of setting LD_LIBRARY_PATH, a JBoss/WildFly module can also automatically look for native libraries in a module: https://docs.jboss.org/author/display/MODULES/Native+Libraries
So you can load your shared libraries in ${WILDFLY_HOME}/modules/oracle/jdbcaq/main/lib/linux-x86_64/ either by copying .so files or thanks a symbolic link.

Differences between Jboss EAP6 and Weblogic 11 XML responses

I have a problem with a Webservice deployed in JBoss EAP 6.
I have a war file, that war contains a WS, but, that war originally was developed and tested in a Weblogic 11 AS; and everything works fine BUT
my boss said that my war can deploys in other server (JBoss) that he has mounted in other computer.
Everything is normal, but in the response, the date is different, i mean, in Weblogic, it appears like this:
<birthday class="com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl">
<year>1952</year>
<month>4</month>
<day>17</day>
<timezone>-360</timezone>
<hour>0</hour>
<minute>0</minute>
<second>0</second>
<fractionalSecond>0.000</fractionalSecond>
</birthday>
So, in JBoss EAP 6, the date appears whit more fields, like this:
<birthday class="org.apache.xerces.jaxp.datatype.XMLGregorianCalendarImpl">
<orig__year>1944</orig__year>
<orig__month>3</orig__month>
<orig__day>1</orig__day>
<orig__hour>0</orig__hour>
<orig__minute>0</orig__minute>
<orig__second>0</orig__second>
<orig__fracSeconds>0.000</orig__fracSeconds>
<orig__timezone>-300</orig__timezone>
<year>1944</year>
<month>3</month>
<day>1</day>
<timezone>-300</timezone>
<hour>0</hour>
<minute>0</minute>
<second>0</second>
<fractionalSecond>0.000</fractionalSecond>
</birthday>
My question is, how can i switch the implementation of the de/serializer for this data type?
It seems, Weblogic uses the JDK interal classes to make the job, but JBoss uses it's own implementation.
I read about to add a xml file (jboss-deployment-structure.xml) to the war archive, i integrate one xml, like this:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
<deployment>
<exclusions>
<module name="org.apache.xerces" />
</exclusions>
<dependencies>
<module name="sun.jdk" >
</module>
<system>
<paths>
<path name="com/sun/org/apache/xerces/internal/jaxp/datatype"/>
</paths>
</system>
</dependencies>
</deployment>
</jboss-deployment-structure>
If i understood well, that xml avoids the use of the JBoss XML implementation (xerces) then i can use the internal classes of the JDK; but the result is the same, any ideas?
I resolve my issue in this form:
I change the default xerces implementation, in this path
{JBOSS_HOME}\modules\system\layers\base\org\apache\xerces\main
I add two files: jaxp-api-1.4.5.jar and jaxp-ri-1.4.5.
And in the module.xml i made a change for the jar declared as a resource root, like this:
<module xmlns="urn:jboss:module:1.1" name="org.apache.xerces">
<resources>
<!--<resource-root path="xercesImpl-2.9.1-redhat-4.jar"/> -->
<resource-root path="jaxp-ri-1.4.5.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
</dependencies>
</module>
Now, my xml comes with the desired XMLGregorianCalendar implementation.
Cheers.

Categories