EJB content in WAR modules
Use this topic to understand the packaging requirements of EJB content in web application archive (WAR) modules.
Supported EJB content
Except for explicitly stated restrictions, the EJB function supported for beans packaged inside EJB Java archive (JAR) modules is also supported for beans packaged inside WAR modules. A bean that is packaged inside a WAR module can have the same behavior as a bean that is packaged inside an EJB JAR module.
All types of EJB 3.x beans are supported in WAR modules, and 2.x and 1.x session beans. See the EJB 3.1 specification for complete details.
Packaging mechanics
The rules for packaging EJB content in a WAR module are different from the rules for packaging EJB content in a JAR module.
The bean class files must be placed in one of two locations within the WAR module:
- Loosely in the WEB-INF/classes directory structure
- Within a JAR file that is placed in the WEB-INF/lib directory
For example, we might loosely place the bean class com.foo.MyBean in the WAR module at this location: WEB-INF/classes/com/foo/MyBean.class.
We might also place this bean class in the myJar.jar file, which is then placed in this location: WEB-INF/lib/myJar.jar.
A WAR module can have some bean code loosely placed in the WEB-INF/classes directory structure, and have other bean code inside JAR files in the WEB-INF/lib directory. It is also valid for a WAR module to have all the bean code in the WEB-INF/classes directory structure and nothing in the WEB-INF/lib directory, or all the bean code in JAR files in the WEB-INF/lib directory and nothing in WEB-INF/classes.
It is valid to have multiple JAR files in the WEB-INF/lib directory, all of which might contain bean code.
If the same bean class is loosely placed in the WEB-INF/classes directory structure and also placed in a JAR file in the WEB-INF/lib directory, then the instance of the class placed loosely in the WEB-INF/classes directory structure is loaded, and the instance placed in a JAR file in the WEB-INF/lib directory is ignored.
If the same bean class is placed in two different JAR files in the WEB-INF/lib directory, it is not known which instance of the class is loaded, and which instance is ignored. At run time, the server arbitrarily picks one class instance and loads it, and ignores the other class instance.
The EJB deployment descriptor files must be placed in the WEB-INF directory. This directory contains the ejb-jar.xml deployment descriptor, and any ibm-ejb-jar-ext and ibm-ejb-jar-bnd XML or XMI bindings and extensions files. EJB descriptor files that are located inside JAR files in the WEB-INF/lib directory are ignored. As with an EJB JAR module, there might be 0 or 1 instance of each EJB descriptor file. There cannot be multiple instances of any EJB descriptor file. This does not include the persistence.xml file, if one exists. Per the Java Persistence API specification, if a persistence.xml file is present, it must remain in a META-INF directory located in either the WEB-INF/classes directory of the WAR module or in a JAR file in the WEB-INF/lib directory of the WAR module. For example:
- WEB-INF/classes/META-INF/persistence.xml
- WEB-INF/lib/MyEntity.jar
The MyEntity.jar contains META-INF/persistence.xml.
If an ejb-jar.xml file is located in a JAR file in the WEB-INF/lib directory, a warning message displays. For example:
IWAE0068W The EJB deployment descriptor META-INF/ejb-jar.xml in the library archive foo.jar file is ignored. The product does not process the META-INF/ejb-jar.xml deployment descriptor in library archives. Move the META-INF/ejb-jar.xml deployment descriptor from the library archive to the WEB-INF directory in the WAR module.A WAR module must be version 2.5 or later to contain EJB content. EJB content placed in a WAR module that is version 2.4 or earlier is ignored.
If a WAR module is version 2.5 or later, the web metadata files containing bindings and extensions information must use the XML version of the files, not the XMI version.
Technical differences for enterprise beans that are packaged in a WAR file
The following list contains key technical differences that exist between beans that are packaged in a WAR module and beans that are packaged in an EJB JAR module:
- Shared component namespace
All components in a WAR module share a single component namespace. This means that each EJB component shares a single component namespace with all other EJB components in the WAR file, and any non-EJB components like servlets. In contrast, an EJB component that is packaged in an EJB JAR module has its own private component namespace, which is not shared with any other component.
The shared component namespace has important impacts. First, one component (EJB or non-EJB) might declare a reference, and a different component might search the component namespace for that reference. Second, references declared by one component might conflict with references declared by another component. In contrast, an EJB packaged in an EJB JAR module cannot look up in the component namespace a reference declared by a different EJB or non-EJB component, and it is impossible for a reference declared by the EJB to conflict in the component namespace with a reference declared by any other component, even if the references have the same name.
When using the shared namespace, it is valid for the same reference to be declared multiple times, as long as these reference declarations do not conflict with each other. If the reference declarations do not conflict, then the server behaves as if the reference had been declared exactly once.
If reference declarations do conflict, then an error message is emitted, and the application fails to start. A warning message is emitted for each conflicted reference. The warning message indicates the name of the conflicted reference, and the multiple values assigned to that reference. After all the warning messages are emitted, an exception is thrown.
- Location of EJB descriptor files
The ejb-jar.xml deployment descriptor file, and any other descriptor file, must be placed in the WEB-INF directory of the WAR. Any instance of an EJB descriptor file elsewhere in the WAR, including in the META-INF directory of a JAR file in the WEB-INF/lib directory, is ignored.
- Determining if annotations are scanned
The rules for determining whether to scan for annotations are different for EJB JAR and WAR modules. See the topic, EJB 3.x module packaging overview, for the complete set of rules.
- Class loading and visibility
The most common usage pattern for EJB classes that are packaged in a WAR module is local method invocations from web components packaged within the same module. However, these EJB classes can also be accessed by remote method invocations or by clients in other modules. In these cases, it is important to understand the visibility rules of EJB classes that are packaged in a WAR module. Visibility rules are different when compared to EJB classes that are packaged in a JAR module.
In the case of remote EJB method invocations, there are no visibility differences introduced by packaging the EJB classes in a WAR module. The EJBs are bound into the global namespace and can be looked up from, or injected into, components in other modules. The remote client must make method invocations with an appropriate stub class. Stub class generation is described in this topic under the section, "Stub generation".
In the case of local EJB method invocations from components in other modules, there are visibility differences because the EJBs are packaged in a WAR module. These visibility differences occur because there are class loader implications that must be considered.
The content that is packaged in all EJB JAR modules for the entire application is loaded by a single application class loader instance.
In contrast, all content that is packaged in a WAR module is loaded on a class loader instance that is specific to that WAR module. The single application class loader instance used to load all the EJB JAR content, is the parent to each of the class loader instances used to load the WAR content.
The visibility of a class is affected by the class loader instance that loaded it. A class loader instance can see classes loaded by itself, or by a parent class loader. However, a class loader cannot see a class loaded on a class loader that is not itself, nor one of its parents.
As a result, classes loaded by a class loader specific to a WAR module can see classes in an EJB JAR module, but they cannot see classes in another WAR module. Classes in an EJB JAR module cannot see classes in any WAR module. For example, if there is EJB content packaged inside EJB JAR module ejb3.jar, and there is also EJB content packaged inside the ejb1.jar file and the ejb2.jar file, then:
- If the ejb1.jar file and the ejb2.jar file are installed as EJB JAR modules, then the content inside the ejb1.jar file, ejb2.jar file, and ejb3.jar file is all loaded on the same class loader instance, which is also used to load any other EJB JAR modules in the application. In this case, the classes in all three JAR files can see each other, because they are all loaded by the same class loader instance.
- If the ejb1.jar file and the ejb2.jar file are both packaged inside the WEB-INF/lib directory of a WAR file, the content inside the ejb1.jar file and the ejb2.jar file is loaded by a single class loader instance. However, this class loader is not the same one used to load the content for the ejb3.jar file and any other EJB JAR in the application. In this case, the classes in the ejb1.jar file and the ejb2.jar file can see each other and can also see the classes in the ejb3.jar file. The classes in the ejb3.jar file cannot see the classes in the ejb1.jar file or the ejb2.jar file.
- If the ejb1.jar file is packaged inside the WEB-INF/lib directory of the firstWar.war file, and the ejb2.jar file is packaged inside the WEB-INF/lib directory of the secondWar.war file, the content in the ejb1.jar file is loaded on one class loader instance, the content in the ejb2.jar file is loaded on a second class loader instance, and the content in the ejb3.jar file and all other EJB JAR in the application is loaded on a third class loader instance. In this case, the classes in the ejb1.jar file and the ejb2.jar file cannot see each other, but they can see the classes in the ejb3.jar file. The classes in the ejb3.jar file cannot see the classes in either the ejb1.jar file or the ejb2.jar file.
One strategy to avoid these class loader complications is to package the EJB interface classes in a shared library.
Do not package the same class, both an EJB JAR module and a WAR module, in the same application. Packaging the same class in multiple locations within the same application might result in confusion regarding which instance of the class is loaded and used at run time. This distinction can matter if the two .class files represent different versions of the class. To avoid this scenario, package the .class file in only one location or change the package structure of the class so that the fully qualified name of the class packaged inside the WAR module is different from the fully qualified name of the class packaged inside the EJB JAR module.bprac
- Application profile extension
The application profile extension is not supported for EJB classes that are packaged in WAR modules.
Stub generation
Remote access of EJB methods requires the use of client-side stub classes. For most client environments, the product runtime automatically generates the required stub classes. One exception is the thin client environment. For thin clients, the stub classes must be manually generated and packaged with the client.
Use the createEJBStubs tool to generate stubs when the EJB content is packaged in a WAR module, regardless of the EJB version.
See the topic, Create stubs command, for more information.
When packaging EJB 2.1 classes in a WAR module, do not include any stub classes generated by the EJBDeploy tool. These stub classes are different than the stub classes automatically generated by the product run time and can cause failures. In most situations the automatically generated stub classes are sufficient. The exception is if a component in the web module must make a remote method invocation on an EJB 2.1 class packaged in another JAR module. In this case, the EJBDeploy generated stub class for the EJB in the other JAR module must be packaged in the WAR module.
EJB 2.x and 1.x content in a WAR module
Except for entity beans, EJB 2.x and 1.x content is supported in a WAR module.
A 2.x or 1.x module packaged inside a WAR file requires an ejb-jar.xml deployment descriptor at version 2.x or 1.x in the WEB-INF directory of the WAR module. If XMI bindings and extension files are present, we must also package these bindings and files in the WEB-INF directory of a WAR module.
Session beans and message driven beans that you implement according to the 2.x or 1.x coding style can be packaged inside a WAR module.
Both bean managed persistence (BMP) and container managed persistence (CMP) entity beans are not supported in a WAR module.
The application profiling and access intent services are not supported in a WAR module. Session beans found in a WAR module cannot access application profiling tasks.
EJB content that you implement according to both the 3.x coding style and the 2.x and 1.x coding styles, can be packaged together in a single WAR module. However, in this case, we must declare any bindings and extensions information with the XML version of the files, not the XMI version.
Move existing EJB content from EJB JAR modules into WAR modules
One approach is to put the existing EJB JAR file in the WEB-INF/lib directory of the WAR file. Then, remove the descriptor files from the META-INF directory of the JAR file and place them in the WEB-INF directory of the WAR file.
A second approach is to put the class files from the EJB JAR file in the correct location under the WEB-INF/classes directory in the WAR module. Then, remove the descriptor files from the META-INF directory of the JAR file and place them into the WEB-INF directory of the WAR file.
If multiple EJB JAR modules are moved into a single WAR module, we must merge the contents of each of the descriptor files previously found in the META-INF directories of the EJB JAR modules into the single version of the descriptor files that are now placed in the WEB-INF directory of the WAR file. Examples of descriptor files that may be merged include, but are not limited to, ejb-jar.xml, ibm-ejb-jar-bnd.xml, ibm-ejb-jar-ext.xml, and ibm-ejb-jar-ext-pme.xml.
We must inspect the references declared by the various components in the WAR module, both EJB and non-EJB, to ensure that they do not conflict with each other, since everything in the WAR module shares a single component name space.
We must modify the bindings and extension XMI files that are moved from an EJB JAR module to a WAR module in several places to remove references to META-INF/ejb-jar.xml and replace them with WEB-INF/ejb-jar.xml.
EJB function supported in EJB JAR modules, but not in WAR modules
The following EJB function is not supported in WAR modules:
- BMP and CMP entity beans
- Pre EJB 3.1 style startup beans
Singleton startup beans defined by EJB 3.1 are supported.
If an entity bean is placed in a WAR module, error messages display, and the application fails to start. For example, the foo entity bean is placed in the foo.war module in the FooApp application. This results in the following messages:
CWMDF0025E: Entity beans in EJB web application archive (WAR) modules are not allowed, per the EJB 3.1 specification.WSVR0039E: Unable to start EJB JAR, foo.war: Entity beans in EJB web application archive (WAR) modules are not allowed, per the EJB 3.1 specification. The foo bean in the foo.war module must be moved to a stand-alone EJB module. Examine the log to see a full list of invalid entity beans in a WAR module.
EJB 3.x module packaging overview Create stubs command