I have a pretty standard java application which uses maven some pretty common libraries including
The application is composed of two war modules which share lot of common dependencies.
During development we've used both jetty and tomcat and everything is working fine. Now we're about to deploy in production and we have some constraints on this environment:
The final structure of the ear produced by maven is
application.ear
├── META-INF
│ ├── application.xml
│ └── jboss-classloading.xml
├── lib
│ ├── long list of shared jars
│ ├── ...
│ ├── // some of key libraries which also are in AS lib folder
│ ├── hibernate-validator-4.3.1.Final.jar
│ ├── jaxb-impl-2.1.10.jar
│ ├── log4j-1.2.17.jar
│ ├── slf4j-api-1.5.5.jar
│ ├── slf4j-log4j12-1.5.5.jar
│ └── validation-api-1.0.0.GA.jar
├── webapp1.war
└── webapp2.war
In our pom the only two artifacts marked as provided are these, so we need them provided in the container.
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb.version}</version>
<scope>provided</scope>
</dependency>
However when we deploy the ear in jboss we encounter lot of classloading problems (I'll list some of them later). What we'd like to obtain is to have jboss load libraries in this order WAR->EAR->Server. In this way we can use newer libraries and safely exclude from deployment libraries shared with application server. To obtain this I created a maven jboss profile which list common libraries (log4j, slf4j, resteasy, and some other) as provided and include in the ear all the others including newer versions of jars present on the AS.
After reading lot of posts about jboss classloading isolation in JBoss 5.x the confguration I'm trying is the one contained in this article which is linked in lot of different sources and it's supposed to work.
Another attempt I've made is to deploy as two WARs to see if something changes. In that case I'm using this configuration in one of the war modules and I'm trying to deploy only that war
<classloading xmlns="urn:jboss:classloading:1.0"
domain="myapp.war"
parent-domain="DefaultDomain"
parent-first="false"
export-all="NON_EMPTY"
top-level-classloader="true"
import-all="true">
</classloading>
The error remain the same.
I don't know how to do, also because I can't find any official documentation about jboss-classloading.xml
file with parameters explained and concrete use cases.
My question is does classloading isolation works in JBoss 5.1.x? Is it reliable? If yes how to obtain WAR->EAR->Server
classloading?
Alternatively how can I completely exclude server lib and use only JARs contained in my archive? In that case do I need to include also the original provided dependencies, i.e. servlet-api, jaxb-api and maybe xml-apis?
With current config the first error we encounter is this one (stack trace omitted)
13:10:11,972 INFO [STDOUT] 13:10:11,969 ERROR [ContextLoader] Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from ServletContext resource [/WEB-INF/applicationContext.xml]; nested exception is java.lang.ClassCastException: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl cannot be cast to javax.xml.parsers.DocumentBuilderFactory
By looking at some posts we're able to solve this by putting this in our maven jboss profile
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.0.b2</version>
<scope>provided</scope>
</dependency>
After that we're getting lot of errors about instantiation of hibernate validator object which are declared as bean using this line in spring context
<!-- Hibernate validator stuff -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
Here's the error
16:52:58,430 ERROR [ContextLoader] Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'validator' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.jboss.logmanager.LogContext.getAttachment(Ljava/lang/String;Lorg/jboss/logmanager/Logger$AttachmentKey;)Ljava/lang/Object;
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)
If I remove bundled version of hibernate validator I loose some useful validators used in application code and I'm getting errors about missing annotations
java.lang.NoClassDefFoundError: [Ljavax/validation/constraints/Pattern$Flag;
So I'm stuck with this problem, please advise.
Class loading isolation works very smoothly in Jboss 5. Refer https://community.jboss.org/wiki/ClassLoadingConfiguration?_sscc=t for more details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With