EJB 3.x module packaging overview

This topic describes application packaging when you use Enterprise JavaBeans (EJB) 3.x beans.

Packaging applications that use EJB 3.x beans is similar to the assembly requirements for Java™ Platform, Enterprise Edition (Java EE) 1.4 applications: components are packaged into modules, and modules are packaged into application enterprise archive (EAR) files. The components and modules both have describing metadata provided in an Extensible Markup Language (XML) deployment descriptor. The EJB 3.x specifications support an additional method to describing metadata and for packaging persistence units.

The EAR file is a package file format similar to a .zip or .tar file format. The EAR file can be visualized as a collection of logical directories and files that are packaged together into a simple file. Each EAR file includes one or more Java EE module files, which can include the following modules:
  • Java application archive (JAR) files for EJB modules. Java EE application client modules and utility class modules.
  • Web application archive (WAR) files for web modules, or EJB content. The WAR file must be version 2.5 or later to contain EJB content.
  • Other technology-specific modules such as resource application archive (RAR) files and other types of modules.

EJB modules without deployment descriptors

You can package EJB modules without a deployment descriptor if you are using EJB 3.x beans. To do this, you must create a JAR file or WAR file with metadata in an annotation which is located in the EJB component. EJB 3.x beans do not need an entry in the ejb-jar.xml file for metadata that you have defined through annotations.

With EJB 3.0, the default was to scan annotations during the installation of an EJB 3.0 module. For WebSphere® Application Server, Version 8.5, the default is not to scan pre-Java EE 5 modules during the application installation or at server startup.

To preserve backward compatibility with both the Feature Pack for EJB 3.0 and the Feature Pack for Web Services, you have a choice whether to scan legacy web modules for additional metadata. A server level switch is defined for each feature pack scan behavior. If the default is not appropriate, the switch must be set on each server and administrative server that requires a change in the default. The switches are server custom properties com.ibm.websphere.webservices.UseWSFEP61ScanPolicy={true|false} and com.ibm.websphere.ejb.UseEJB61FEPScanPolicy={true|false}. To define these properties in the administrative console click Application servers > server name > Process definition > Java Virtual Machine > Custom properties.

EJB modules with deployment descriptors

You can continue to use EJB modules with deployment descriptors. Modules with deployment descriptors can support any EJB specification version level, including EJB 3.x, but generally these descriptors should reflect the implementation requirements of the components in the module.

An EJB module can have an EJB 3.x, 2.x, or 1.x deployment descriptor.

For EJB 2.x or 1.x deployment descriptors, it is assumed that the deployment descriptor contains the full metadata for the module, and no additional scanning of annotation metadata occurs.

The EJB container annotation scanning is performed on EJB modules that either have no deployment descriptor or have an ejb-jar.xml deployment descriptor at the EJB 3.0 schema level with the metadata-complete XML attribute set to false or omitted. See the Annotation scanning behavior section for the complete set of rules used by the server to determine if annotation scanning is performed.

Note: You cannot scan for component annotation metadata contained within shared libraries defined using the WebSphere Application Server system management shared library feature. However, content defined as a BLA Asset is scanned for annotation data.

Annotation scanning behavior

The server can inspect the class files in the module for annotation content. The server searches for annotation content that might define a component, a reference to a resource, or a particular behavior. For example, annotations might be used to define an EJB component, or to declare a reference to a data source that must be used by an EJB component, or to declare the transactional or security attributes that are associated with an EJB method. This inspection process is referred to as annotation scanning. If the class files in the module contain annotations that must be respected by the server, then the server must be configured so that annotation scanning occurs. If the class files in the module do not contain annotations, then for performance reasons you can configure the server so that annotation scanning does not occur.

The server uses the following criteria to determine whether it scans content for annotations:
  • Whether the ejb-jar.xml deployment descriptor file exists
  • Version of the ejb-jar.xml deployment descriptor, when it is exists
  • Value of the metadata-complete setting in the ejb-jar.xml deployment descriptor, when it exists
  • Version of the web.xml deployment descriptor, when the EJB content is packaged in a WAR module, and the ejb-jar.xml deployment descriptor does not exist
  • Value of the metadata-complete setting in the web.xml deployment descriptor, when the EJB content is packaged in a WAR module, and the ejb-jar.xml deployment descriptor does not exist

The following tables indicate how the decision to scan, or not scan, annotations is made for EJB content that is packaged in an EJB JAR module or a WAR module.

Table 1. Annotation scanning for EJB content packaged in an EJB JAR module . Annotation scanning for EJB content packaged in an EJB JAR module
ejb-jar.xml metadata-complete value in ejb-jar.xml Are annotations scanned?
Exists, with a version of 2.x or earlier NA No
Exists, with a version of 3.x or later true No
Exists, with a version of 3.x or later false (or omitted) Yes
Does not exist NA Yes
Table 2. Annotation scanning for EJB content packaged in a WAR module . Annotation scanning for EJB content packaged in a WAR module
ejb-jar.xml file metadata-complete value in ejb-jar.xml web.xml file metadata-complete value in web.xml Are annotations scanned?
Exists, with a version of 3.x or later true NA NA No
Exists, with a version of 3.x or later false (or omitted) NA NA Yes
Exists, with a version of 2.x or earlier NA NA NA No
Does not exist NA Exists, with a version of 2.5 or later true No
Does not exist NA Exists, with a version of 2.5 or later false (or omitted) Yes
Does not exist NA Exists, with a version of 2.4 or earlier NA No
Does not exist NA Does not exist NA Yes
Note:

It is important to understand the distinction between the metadata-complete attribute of the ejb-jar element of the ejb-jar.xml deployment descriptor, and the metadata-complete install setting that may be specified during the application or module installation process.

The metadata-complete attribute of the ejb-jar element of the ejb-jar.xml file is an XML attribute. It is used by the server to determine if classes must be scanned for annotation data, as just described by the rules in the Annotation Scanning For EJB Content tables.

In contrast, the metadata-complete setting that may be specified at install time is used by the server to help generate the ejb-jar.xml file. If no ejb-jar.xml file exists in the module, and the metadata-complete install setting is assigned a value of true, then the server scans for annotation content and uses that to generate an ejb-jar.xml file, and then sets the metadata-complete XML attribute in that file to a value of true.

Persistence units

Persistence units, including the persistence.xml file and the classes associated with it, can be packaged in the module for which they are required. They can also be packaged in the separate utility JAR file that is packaged in the EAR file with its dependent module.

When a separate utility JAR file is packaged, it is necessary for the module that desires it to use the persistence units to declare a dependency on the utility JAR file using the typical MANIFEST. MF Class-Path: declarations. See the example scenario for this packaging method under the Session facades used for persistence scenario section in this topic.
Note: Packaging of persistence units contained within shared libraries defined using the WebSphere Application Server system management shared library feature is not supported at this time.

Application packaging

You can mix EJB 2.x and earlier beans with EJB 3.x beans in the same application. However, EJB 3.x beans are not recognized in EJB 2.x or EJB 1.x modules.

In the case that the EAR file only contains the JAR and web application archive (WAR) files, and no application.xml file, the product provides a default J2EE 1.4 deployment descriptor that is based on the following defaults that are outlined in the Java EE specification:
  • The application name is assumed to be the name of the EAR file, but with the EAR file extension removed.
  • Files that are ending in .war are assumed to be web modules. The context root of the web module is the name of the file that is relative to the root of the application package, but with the WAR file extension removed.
  • Files that are ending in .jar that are not in the /lib directory, and that contain either an ejb-jar.xml file or at least one class that defines a @Stateful, @Stateless, @Singleton, or @MessageDriven annotation, are assumed to be EJB modules.
  • Other JAR files that are not in the /lib directory are not assumed to be EJB modules.
If the application archive file contains an application.xml descriptor, processing occurs according to the directives in that descriptor.

AutoLink

AutoLink provides the ability to attempt to automatically resolve EJB references to components contained with an EAR file, without having to specify a JNDI binding name. This simplifies application deployment with large numbers of beans and references if they are unique and unambiguous.
Restriction: AutoLink should not be used for references to components deployed on a cluster.

JPA packaging

It is recommend that persistence units be packaged in separate JAR files to make them more accessible and reusable. These can be tested outside the container, with or without actual database persistence occurring. Persistence units can be included in stand-alone applications or into EAR files as utility JAR files. Because of the variety of use cases and potential performance issues when scanning large quantities of classes, it is recommended that the persistence unit defines the classes of the persistence units.

Session facades used for persistence scenario

A common pattern is to use session facades for persistence. Using session bean facades to drive JPA is supported. The EntityManager interface is not thread safe, therefore, servlets should never inject @PersistenceContext. Servlets must either use the facade pattern or use an EntityManagerFactory instance to create an EntityManager on each request.

It is recommended that JPA persistence units be defined in a separate JAR file, apart from the session bean facades. Not only is this a best practice that gives greater flexibility in sharing, it also avoids problems mixing JPA and non-JPA annotated classes.

Typically, a JAR file is created to hold the entity classes and the JPA persistence.xml definition and added to the EAR file as a utility JAR file. The EJB 3.x module adds a dependency on the JAR file by declaring it in the EJB 3.x module MANIFEST.MF. For example, if an EAR contains a TradeApp.ear, TradeWeb.war, EJB3Trade.jar, and TradeInfo.jar file, the EJB3Trade.jar file would have a MANIFEST.MF that looks like the following:

Manifest-Version: 1.0
Class-Path: TradeInfo.jar

The session facade in the EJB3Trade.jar file refers to JPA entity classes and persistence units in the TradeInfo.jar file. The web application defined in the TradeWeb.war file can do the same to work with the JPA entity objects as Data Transfer Objects flowing between the web and EJB container tiers.

Cross-tier and cross version session bean reference scenario

There are several ways to define and use references to EJB 3.x session beans. For EJB 3.x session to session, the @EJB injection target can be used. For cross-tier, for example, web application to EJB 3.x session, or cross-version, for example, EJB 2.1 session to EJB 3.x session, an XML deployment descriptor reference can be used to define ejb-refs and ejb-local-refs. There are two variations of these, depending on whether an EJB 3.x business interface is referred to, or a pre-EJB 3.x component-style interface that also defines an EJBLocalHome is referred to. Web applications and client applications can also use the @EJB annotation if the component being referenced can be resolved using autolink.

For migration scenarios where session beans are being converted from EJB 2.1 beans to EJB 3.x beans, the pattern is typically to edit the Session bean class, replace the implements SessionBean with implements the business interface, remove extends EJBLocalObject from the local interface and non-business throws clauses, and add the @Stateful @Local @LocalHome(<localhome>.class) or similar annotations. Existing ejb-refs and ejb-local-refs are bound to the new implementation of the session bean.
Note: The default binding name does change.

The previous scenario uses an EJB 2.1-style client pattern with an EJB 3.x-style session bean implementation. For a more current client style, the client-side can be cleaned up to look up the session bean business interface directly, rather than going through a home interface. In this case, it is not necessary to define the @LocalHome(<localhome>.class) annotation. You can use a variant definition of ejb-ref and ejb-local-ref to do this. Use a null value for the local-home element value and bind the ejb-local-ref to the session bean's ejblocal: binding rather than the home binding. For example:

<ejb-local-ref id="EJBLocalRef_1154112538064">
	<description>com.ibm.persistence.ejb3.order.facadecom.ibm.persistence.ejb3.order.facade</description>
	<ejb-ref-name>ejb/OrderEJB</ejb-ref-name>
	<ejb-ref-type>Session</ejb-ref-type>
	<local-home></local-home>
	<local>com.ibm.persistence.ejb3.order.facade.OrderProcessor</local>
</ejb-local-ref>

The client code also must be adjusted to do the appropriate casting for the object being looked up. In this case, the business interface instead of the home interface:

try {
	InitialContext ctx = new InitialContext();
	orderProcessor = (OrderProcessor)ctx.lookup("java:comp/env/ejb/OrderEJB");
}
catch(Exception e)  {
	e.printStackTrace(System.out);
	throw new ServletException(e);
}