Application structure description: Ear application with ejb module (.jar), jboss-seam (.jar) and war module (.war).
I have a StartupAction.class (seam component) annotated with org.jboss.seam.annotations.Startup. During application deployment I need to get the resource from application.war module root (application.war/pages/page.xhtml) and WEB-INF/classes (application.war/WEB-INF/classes/file.properties)
Jboss 4.2
Thread.currentThread().getContextClassLoader().getResourceAsStream("file.properties") would fetch the file from application.war/WEB-INF/classes/file.properties.
Jboss 7.1.1
Code from above doesn't work with Jboss 7.
I know that the class loading changed but I can't figure it out how to get into application.war in jboss 7.
Is it possible to do this? Are there any example of this?
Thanks in advance.
As mentioned by #BalusC, you will not be able to read a properties file that is embedded in a web module from any other modules (EJB or otherwise) that are packaged in your EAR.
The fact that this works in JBoss 4.x is a consequence of it providing backwards compatibility for even earlier versions of JBoss. Additional configuration is required in JBoss 4.x in order for it to use specification compliant class loading. JBoss 7.x and newer use specification compliant class loading by default.
If your properties file contains external configuration that is intended to be accessible after deployment then you might consider the approach described in How to put an external file in the classpath.
However, if it is effectively static data then you should package the properties file in a jar module and place it in the the lib directory of your EAR.
In jboss7, you have a classloader for each subdeploy.
In your case, Thread.currentThread().getContextClassLoader() will return the classloader of the current deployment.
To fix your problem, you could try this:
SomeRandomClassContainedInsideTheWAR.class.getClassLoader()
Check this guide to learn more about JBoss7 ClassLoader
https://docs.jboss.org/author/display/AS7/Class+Loading+in+AS7
Related
I have a war that uses the errai-bus, which depends on guava 14.0.1. I'm deploying the app with Jboss, but when I do, Jboss is using its weld version of guava, which is guava r6 (very old). This causes horrible class loading issues and the errai-bus completely fails to work.
Even when I declare guava 14.0.1 as a top-level dependency in my pom, it still uses guava r6. How can I stop Jboss from loading the wrong guava version for my war?
I've tried to look up info about how to do this with the class loader files in Jboss AS 6, but I can't seem to find any documentation.
You can try add the following jboss-classloading.xml to your WEB-INF folder:
<classloading xmlns="urn:jboss:classloading:1.0"
name="mywar.war"
domain="mywar_domain"
parent-domain="Ignored"
export-all="NON_EMPTY"
import-all="true">
</classloading>
In this case, put the war's classloader in the mywar_domain which is shared with all other applications that don't define their own domain. Also choose to look at all other classes exported by other applications import-all and to expose all our classes to other classes export-all.
What you get when you deploy this file, is that the Web application classloader will act as top-level Classloader so there will be no conflict with the same classes in the server's library.
See also:
JBoss 5 - ClassLoading
Demystifying the JBoss5 jboss-classloading.xml file
Anyway JBoss AS 6 is out of date, and have a lot of de bugs unresolved. You would have to see the possibility of using a newer version (Wildfly or JBoss EAP 6).
I'm aware that this is a very simple issue, but as I'm new to Wildfly I haven't had success trying to accomplish it.
In the old days of JBoss 4.2, when I wanted to share an ejb jar file with multiple war files I just deployed the ejb jar file to the application server and configured jndi in my war projects with a file 'jndi.properties' placed in some source directory in the war files, like this:
jndi.properties
---------------
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=jnp://localhost:1099
Now, with Wildfly 8.1, this approach is not working anymore. I don't know if the contents of the jndi properties file changed or if I have to do something else. So, I ask: how do I share an ejb jar file with multiple wars in Wildfly 8.1 (I don't want to use ear files for this)?
Thank you in advance.
Marcos
PS.: Cross-posted: https://developer.jboss.org/thread/249133
just deploy the jar file and add adependency to your war file (either in Manifest.MF or in jboss-deployment-structure.xml from your war to your jar. Then you should be able to do JNDI-lookups using java:global/... or using CDI for injecting the beans using #Inject (for this approach you will need to activate CDI using beans.xml)
see also:
Wildfly class loading
Wildfly deployment descriptors
CDI reference
Application deployment
I use JBoss 5.1 and I deploy an ear on it.
In my ear, few webapps are using some jars which are using by JBoss to.
For example, jboss use slf4j in version 1.5.6 and my webapps uses version 1.7.1
This two versions of slf4j are not compatible (see Logging framework incompatibility).
Is there any way to say to JBoss to use his own lib but webapp have to use theirs ?
Edit : I don't want to change the version of JBoss I use.
Thanks for help !
Create jboss-deployment-structure.xml file in WEB-INF folder with deployment exclusions of jars which you want to attach.
How do I disable app server embedded library(jar) for a particular WAR or EAR?
I have a .war application module, that can be successfully deployed without any exotic changes and server tuning. However, i was unable to deploy this app to GF 3.1.2: server throws following exception:
java.lang.Exception: java.lang.IllegalStateException: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: org.apache.catalina.LifecycleException: java.lang.NoSuchFieldError: theInstance
What i am doing wrong? Has anyone suggest me something? Is there any additional settings that i should perform to deploy .war module successfully?
Thanks a lot in advance.
UPD
More precise log entry:
javax.xml.bind.JAXBException: Provider com.sun.xml.bind.ContextFactory_1_0_1 could not be instantiated: javax.xml.bind.JAXBException
- with linked exception:
[java.lang.NoSuchFieldError: theInstance]
- with linked exception:
[javax.xml.bind.JAXBException
- with linked exception:
[java.lang.NoSuchFieldError: theInstance]]
Sounds like a class loader issue.
You need your WEB-INF/lib JAXB jars used ahead of the GlassFish JAXB jars.
Or change your app to use the versions GlassFish 3.1.2 is bundled with.
Servlet spec says that web applications should use the local class loader before delegating to the parent. I think GlassFish delegates to the the parent class loader for web applications by default. Use <class-loader delegate="false"/> in web.xml or glassfish-web.xml.
Note there may be other ways to modify the class loader in GlassFish if this does not work.
This type of issue is common during deployment to many application servers.
I've used GlassFish daily for the last 5+ years and see this every so often.
Recently saw a similar issue when deploying to JBoss on CloudBees, and modified a deployment descriptor accordingly.
Googling "glassfish prefer web-inf/lib jars".
Response To psed comment below
EJB interfaces must reside in the class path hierarchy shared by the Web module and EJB module. If you have an EJB interface jar in WEB-INF/lib and another copy of the EJB interface jar on the EJB module classpath, you would get a ClassCastException when injecting/locating the EJB in your web application. I assume WebServices have the same issue. Sharing the EJB interface jar though an EAR should resolve this issue though. Note there may be other issues I am unaware of
You should not bundle JAXB jars with your application - Glassfish already has them, and it seems this is causing a conflict (incidentally, I've been digging through JAXB code recently, and theInstance is part of a static class defined by MarshallerImpl)
You should place your all jar files to your runtime server lib...
This instruction is for GlassFish 3.1.2
The issue is runtime classes from JAXB 2.2.5 are not backward compilable with JAXB 1 code.
This issue was fixed with JAXB 2.2.6, however, it's not in latest GlassFish release. So, either you wait until the next GlassFish upgrade or you do it manually.
Here is how i did,
I removed the 2 bundle files from GlassFish module
C:\glassfish3\glassfish\modules\jaxb-osgi.jar
C:\glassfish3\glassfish\modules\endorsed\jaxb-api-osgi.jar
Clear the osgi-cache by deleting all the subfolder in
C:\glassfish3\glassfish\domains\domain1\osgi-cache
Download JAXB 2.2.6 from ORACLE JAXB
Extract the zip file to a temp location [C:\Java\jaxb-ri-2.2.6\jaxb-ri-2.2.6\osgi]
copy C:\Java\jaxb-ri-2.2.6\jaxb-ri-2.2.6\osgi\jaxb-osgi.jar to C:\glassfish3\glassfish\modules\
copy C:\Java\jaxb-ri-2.2.6\jaxb-ri-2.2.6\osgi\jaxb-api-osgi.jar to C:\glassfish3\glassfish\modules\endorsed\
restart your server ... i hope this will help. Good Luck
So I am working on a project whereby we needed to create a custom Tomcat Realm implementation to read authentication credentials from a mongo backed datastore.
This has been pretty painless, but the implementation we have come up with has several dependencies on external libs i.e. scala libs, the java mongo-db driver, spring, salat (a mongodb ORM) etc....
Now in order for Tomcat to use this Realm we must deploy our Jar (and all the dependent jars) to tomcats lib folder.
Being pretty new to Java, I have no idea how much of an issue this is, but it doesn't seem nice to me. So really, my question is what issues would I have with dumping a load of JARs into Tomcats lib directory?
Cheers, Chris.
Most likely dependencies will become a problem. All JARs you place in tomcat/lib are visible to the WARs you deploy at a later time. I suppose your Realm implementation is the base for one or more web applications.
Let's say your Realm depends on Spring 2.0 and you're required to place those libs in tomcat/lib and afterwords you deploy a WAR using Spring 3.0. The WAR will see all classes available in tomcat/lib - the Spring 2.0 classes. So your WAR ships the 3.0 classes in WEB-INF/lib, at runtime it can see the Spring 2.0 libs in tomcat/lib as well as its own Spring 3.0 libs in WEB-INF lib. This is going to cause trouble...
I'm not aware of a simple solution for this, maybe you should have a look at OSGI and Tomcat integration. No question, it won't make life easier...