Precedence of EJB Deployment Descriptors - java-ee-6

If I have an EJB packaged in a WAR because it is exposed as a REST web service, according to this link, I need to have the ejb-*.xml files at the root of the WEB-INF directory. My current environment is Websphere 8.5 and EJB 3.1
If I later add multiple EJBs ( in separate EJB projects ) in the same application and define its deployment descriptors in the respective projects, those seem to be ignored. It appears that ALL of my descriptors should be defined in the descriptors in the WEB-INF directory - or in other words, it seems that I should augment the descriptors in WEB-INF directory even for EJBs that are defined as separate projects.
Is this how it needs to be or am I missing something that is forcing me to do this? I could not find any documentation explaining this part.
More Details:
This is how my application.xml looks like
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/application_7.xsd"
version="7">
<display-name>MyApp</display-name>
<module id="Module_1395346343165">
<web>
<web-uri>MyWeb.war</web-uri>
<context-root>myapp</context-root>
</web>
</module>
<module id="Module_1395346304194">
<ejb>ejb1.jar</ejb>
</module>
<module id="Module_1424684968934">
<ejb>ejb2.jar</ejb>
</module>
<module id="Module_1431010943758">
<ejb>ejb3.jar</ejb>
</module>
</application>
The ejb1 is the one that will live in the webapp. The other two, ejb2 and ejb3 are separate ejb projects that are supposed to be in EAR's root.

For EJBs in a WAR module, the files go in WEB-INF, so .ear!/MyWeb.war!/ejb-jar.xml, .ear!/MyWeb.war!/ibm-ejb-jar-bnd.xml, etc.
For EJBs in separator EJB modules outside a WAR, the files go in META-INF. So, .ear!/ejb1.jar!/META-INF/ejb-jar.xml, .ear!/ejb1.jar!/META-INF/ibm-ejb-jar-bnd.xml, etc.

Related

JBoss EAR deployment fails because WAR classes are unable to find jars from EAR/lib folder

I am using JBoss EAP 7 and want to deploy an EAR file in standalone mode (using standalone-ha.xml).
I went through almost everything available on StackOverflow/JBoss forums but couldn't make my deployment to work (correctly). I have followed the docs to the best of my abilities but still the deployment of EAR gives Exception on console because the jar files inside WAR/WEB-INF/lib are not able to see the jar files present int EAR/lib folder. I can't figure out what I am doing wrong.
Structure
myEAR.ear
|- lib (contains a.jar)
|- META-INF
|--- maven (folder with pom)
|--- application.xml
|--- jboss-deployment-structure.xml
|--- MANIFEST.MF
|- myWar.war
|--- WEB-INF
|----- lib (contains b.jar)
|----- jboss-deployment-structure.xml (which should be ignored per the docs)
|----- (WEB-INF contains other files/folders such as classes,jsp etc
EAR- application.xml:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/application_7.xsd" version="7">
<display-name>myear</display-name>
<module>
<web>
<web-uri>myWAR.war</web-uri>
<context-root>/mywar</context-root>
</web>
</module>
<library-directory>lib</library-directory>
</application>
EAR- jboss-deployment-structure.xml:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<deployment>
<dependencies>
<module name="com.organization.global" export="true" />
</dependencies>
</deployment>
<!-- Having/Not having below sub-deployment has no effect -->
<sub-deployment name="myWAR.war">
<dependencies/>
</sub-deployment>
</jboss-deployment-structure>
Deployment succeeds if I copy a.jar inside WAR/WEB-INF/lib/ folder, otherwise gives an exception: Caused by: java.lang.NoClassDefFoundError related to a class specific to a.jar. I want my WAR to be able to get access to all the jars put together inside EAR/lib.
I read in one of the forums that the jar/classes in lib folder should be available to all modules within the EAR but sometimes they are not added automatically but I couldn't find the solution on how to add them.
Any guidance would be appreciated. Thanks in advance!
In JBoss EAP 7, to access lib files present in ear inside war you could try by adding a context param in your war's web.xml.
To create env variable try below in terminal:
export JAR_HOME=../jboss-eap-7.1/standalone/deployments/example.ear(Please add value equivalent to your environment and ear's path)
export PATH=$PATH:$JAR_HOME
Add this variable to web.xml as file:${JAR_HOME}/lib/example.jar
Read this context param inside your classes present inside war.

Glassfish v3: Web application not finding JAR in the same EAR

I created a EAR application in Eclipse to run in Glassfish 3.1. The used projects are: BibliotecaEAR2 (the main EAR. 'Biblioteca' means 'Library'), BibliotecaEJB (with EJBs), BibliotecaModel (with entities and DAOs) and BibliotecaWeb (The Web application). The application.xml has this structure:
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" id="Application_ID" version="6">
<display-name>BibliotecaEAR2</display-name>
<module>
<web>
<web-uri>BibliotecaWeb.war</web-uri>
<context-root>biblioteca</context-root>
</web>
</module>
<module>
<ejb>BibliotecaEJB.jar</ejb>
</module>
</application>
In BibliotecaWeb, the META-INF/MANIFEST.MF is written this:
Manifest-Version: 1.0
Class-Path: lib/google/guava-18.0.jar
// other JARs in BibliotecaEAR2 project
BibliotecaEJB.jar
When I start the glassfish I get this warning message:
2014-10-20T14:34:31.691-0200|WARNING: PWC6351: In TLD scanning, the supplied resource file:/C:/dev/glassfish3/glassfish/domains/biblioteca-glass3/eclipseApps/BibliotecaEAR2/BibliotecaEJB.jar does not exist
java.io.FileNotFoundException: C:\dev\glassfish3\glassfish\domains\biblioteca-glass3\eclipseApps\BibliotecaEAR2\BibliotecaEJB.jar (O sistema nao pode encontrar o arquivo especificado)
Although it does not stop me from running the application, I would like to eliminate it.
Googling for PWC6351 warning, I perceived that it happens when a used JAR is not found in the Manifest File. However the request JAR is not simply a external library, but a sub-project in same EAR. Is there any additional configuration that should I do?
Thanks,
Rafael Afonso
From Packaging libraries with EARs:
When packaging applications in an EAR file, the library JARs need to
be placed in the archive lib directory (jars at the archive root level
are not added to the classpath and thus available from other EAR
artifacts.)
The library jars placed in the "/lib" directory of the EAR (the
directory name can be overridden in application.xml) will be visible
to all sub-modules (JARs, WARs, and RARs) with no further
configuration. No need to add Class-Path entries in the EAR manifest.
In fact you don't need to reference the jars in the lib folder, and it looks like it will not work if you reference a jar on the EAR root level, like your BibliotecaEJB.jar.
If you don't have a real dependency from your WAR module classes to your EJB module classes you can just remove all the entries from the MANIFEST.MF and it should work.
If you instead have a real dependency from WAR to EJB, you may have to think about your project structure and if you really need an EAR. You can also package all the stuff into a single WAR.
The right way to use an EAR with WAR and EJB modules requires a little bit of work if your current WAR classes directly depend on classes from the EJB module:
1. Step
You have to create interfaces for all your "service" classes which should be available to classes in the web application (WAR).
Here is a simple example:
public interface FileService {
public void showFileInformation(File file);
}
and
#Stateless
#Local(FileService.class)
#Remote(FileService.class)
public class FileServiceImpl implements FileService {
#Override
public void showFileInformation(File file) {
// here
// is
// the
// real
// stuff
}
}
2. Step
The next step is to package all your new interfaces into a new jar. Your model jar looks similar to this approach. If this can't be used for this purpose, create a simple java application project which gets packaged as jar and put all the interfaces into this project. This jar has to be in the lib folder of the EAR.
BibliotecaEAR2
-- BibliotecaEJB
-- BibliotecaWeb
-- /lib/interfaces.jar
Then you have to add a dependency to this new jar in your WAR and EJB modules, so that they can find the interface classes.
3. Step
The services can be injected into the managed classes of your web applications (and into other service classes) like this:
#RequestScoped
public class FileHandler {
// make sure to use the interface
#EJB
FileService fileService;
}
Maybe you already have something similar to this, but then it should work without any entries in the MANIFEST.MF.
See also:
Maven2: Best practice for Enterprise Project (EAR file)
Java EE - EAR vs separate EJB+WAR
Packaging EJB in JavaEE 6 WAR vs EAR
I had a similar issue and solved by customizing module location, like this
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" id="Application_ID" version="6">
<display-name>BibliotecaEAR2</display-name>
<module>
<web>
<web-uri>BibliotecaWeb.war</web-uri>
<context-root>biblioteca</context-root>
</web>
</module>
<module>
<ejb>BibliotecaEJB.jar</ejb>
<bundleDir>/lib</bundleDir> <!-- ADD THIS OPTION TO THE MODULE -->
</module>
</application>
This solution is taken from the Maven EAR plugin documentation, which uses Maven 3 syntax, but I think you can use it too (or you can migrate to Maven 3).
Hope that helps.

How to define a custom EAR file name for a specific application?

Here is my setup
SDK: Eclipse Ganymede (3.4.2)
App Server: jBoss 4.2.3GA
I got three projects:
MYAPP, which is the main project, with only libraries and log4j configurations. This is where application.xml and jboss-app.xml resides.
MYAPPEJB, which is my business logic project in which I have my entity beans, sessions beans.
MYAPPWeb, which is my client logic project in which I have my Struts Forms, Struts Actions, JSPs and Jasperreports reports.
When I publish my project to my jBoss server on my laptop, I got the following EAR file name: MYAPP.ear, which make sense.
I would like to define a different custom name for the final EAR, let's say ACCOUNTMANAGER.ear
Here is my application.xml file
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:application="http://java.sun.com/xml/ns/javaee/application_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd" id="Application_ID" version="5">
<display-name>MYAPP</display-name>
<module>
<ejb>MYAPPEJB.jar</ejb>
</module>
<module>
<web>
<web-uri>MYAPPWeb.war</web-uri>
<context-root>/manager/myapp</context-root>
</web>
</module>
<library-directory>/lib</library-directory>
</application>
Any idea?
Thank you
Charles
You can specify your ear file name in application.xml file under web -> web-uri tag. Please check this link for your reference. web-uri
You can specify in application.xml file. It will pick up this name instead of ear file name.
MyEarName

Injecting beans into filter packaged in a shared library

I've got an JavaEE6 app with following structure:
app.ear
META-INF
application.xml
lib
commmon-server-lib.jar
webapp1.war
webapp2.war
services-ejb.jar
Both webapps have common-server-lib.jar in Class-Path entry of their MANIFEST.MF (skinny war's).
application.xml:
<application>
<module>
<ejb>services-ejb.jar</ejb>
</module>
<module>
<web>
<web-uri>webapp1.war</web-uri>
<context-root>/webapp1</context-root>
</web>
</module>
<module>
<web>
<web-uri>webapp2.war</web-uri>
<context-root>/webapp2</context-root>
</web>
</module>
<library-directory>lib</library-directory>
</application>
In common-server-lib.jar there is a web filter that should have few EJBs and other CDI managed beans injected. This filter is defined in web.xml's of both webapps.
common-server-lib.jar and war's have beans.xml in appropriate place.
Now the problem is, that when I try to deploy this app to Glassfish I get errors like this:
Class [ Lcom/acme/UserService; ] not found. Error while loading
[ class com.acme.filter.MyFilter ]
UserService service is located in services-ejb.jar
So my question is: what am I doing wrong...? Is there something wrong in defining web components (that use injections for it's dependencies) in a shared library?
Edit:
In section 15.5 of JSR-315 (Servlets 3.0 final spec) one can find:
In a web application, classes using resource injection will have their annotations
processed only if they are located in the WEB-INF/classes directory, or if they are
packaged in a jar file located in WEB-INF/lib.
I've moved common-server-lib.jar to WEB-INF/lib directories of both webapps but I'm still having same issue ;/...
After many hours of struggling with this puzzle I've found a solution:
Add web-fragment.xml to commmon-server-lib.jar with my filter
Remove filter specification from webapps web.xml's
Change maven fonfiguration to remove all jar's from WEB-INF/lib
directory except commmon-server-lib.jar
Remove commmon-server-lib.jar from EAR /lib directory

class def not found in jboss as 7.X

I have a project structure as
eardirectory.Ear
lib/
my-custom-classes.jar
.....
.....
my-custom-ejb.jar
META-INF/
....
//Now I tried to load classes from classloader as
ClassLoader cl = Thread.currentThread().getContextClassLoader();
clazz = Class.forName(my-custom-classes.class1.class.getName(), true, cl);
but this will not work as current thread is of jboss and jboss has not any identification of my-custom-classes.jar.So my question is how this can be done with jboss? I have to have to load class definition at runtime.
Is there any way in "jboss-deployment-structure" I can define how to load classes before deploying EAR?
Follow the steps to create module it should work
Step-1
In jboss-as-7.1.1.Final/modules/com/company/gyani/main/
-module.xml
-my-custom-classes.jar
Content of module.xml
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="com.company.gyani">
<resources>
<resource-root path="my-custom-classes.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
</dependencies>
</module>
Step-2 Now IN my.ear/META-INF/
-jboss-deployment-structure.xml
-MANIFEST.MF
Content of MANIFEST.MF
Manifest-Version: 1.0
Dependencies: com.company.gyani
You need to use concept of module(s) provided by JBoss AS7.
Here you configure your classes/jars/property files as modules and these are loaded while starting JBoss at server scope and are accessible to any deployed application that carries a dependency on this module.
Read through How to configure module