JavaEJBPackaging EJB 3 Applications

Packaging EJB 3 Applications

The real success of Java EE applications lies in assembly and deployment, as this is the key to delivering on Java’s promise of write once, run anywhere (WORA). If you fail to fully grasp this step, your application may not realize this level of portability.

Java platform roles: it’s all about juggling hats

The Java EE platform defines different roles and responsibilities relating to development, assembly, and deployment of Java EE applications. In this article we are mainly interested in the Developer, Assembler, and Deployer roles, but we introduce you to all the roles so that you can be familiar with them. The roles defined by the specifications are

  • Enterprise Bean Provider
  • Application Assembler
  • Deployer
  • EJB Server Provider
  • EJB Container Provider
  • Persistence Provider
  • System Administrator

The database administrator is not one of the defined Java EE roles. The database administrator may not even understand a line of Java code. However, the importance of this role cannot be overlooked, especially in large corporations where relational databases are outside the control of the application developers. Developers, Assemblers, and Deployers may need to work with the DBAs in order to successfully build and release Java EE applications.

It’s all about the division of labor. Many believe that the difficulties of earlier EJB practices were a result of the division of the EJB roles. In reality, the previous EJB specifications were not the real culprit—the source of all the confusion is the Java EE specification. While the Java EE and EJB specifications define seven roles, the problem is that many project teams do not even have seven people—how can a two- or three-person team wear that many hats?

A typical application has a handful of Java classes, and maintenance can be a nightmare if you are shipping your applications from one environment to another. To simplify maintenance you can create a Java archive (JAR) file. Typically, a JAR file is a file in zip format that contains classes. However, enterprise Java applications are packaged as specialized versions of JAR files—EAR, WAR, and EJB-JAR modules—before they can be deployed to a Java EE.compliant application server.

In this article we begin with a discussion of application packaging and deployment. The article also provides critical information on class loading, so that you can appreciate why the archives are packaged as they are. This is intended to provide you a better understanding of the packaging requirements for EJB that include entities. We explain the need for deployment descriptors, and look at how to use them. Finally, we look at a persistence unit and how to per form object-relational (O/R) mapping using XML.

Packaging your applications

A typical enterprise Java application may contain several Java classes of different types, such as EJBs, servlets, JavaServer Faces (JSF) classes, as well as static files such as JSPs and HTML files. EJBs run in the EJB container whereas web applications such as servlets and JSF managed beans run in the web container. To run your application you have to make it available to the Java EE application server. This is known as deployment. Since EJB is a core part of the Java EE specification, you have to follow the Java EE standard for deployment.

To understand packaging, you must consider how it fits into the bigger picture of Java EE packaging and know what constitutes a complete enterprise Java application. Up to this point we have focused on using EJB components such as session beans and MDBs to build business logic and JPA entities to implement your persistence code. However, your application will not be complete without a presentation tier that accesses the business logic you built with EJBs. For example, the EJBs we built for ActionBazaar do not make sense unless we have a client application accessing them. Most likely, you’ve used standard technologies such as JSP or JSF to build the web tier of your applications. These web applications, together with EJBs, constitute an enterprise application that you can deploy to an application server.

To deploy and run an application, you have to package the complete application together—the web module and EJBs—and deploy to an application server. Usually you will group similar pieces of the application together in modules. Java EE defines a standard way of packaging these modules in JAR files, and specifies the formats for these JARs. One of the advantages of having these formats defined as part of the specification is that they are portable across application servers.

Table 1 lists the archives or modules supported by Java EE 5 and their contents. Note that each archive type is used for packaging a specific type of module, such as EJB or web. For instance, a WAR is used to package a web-tier application module, and the EAR file is intended to be the |über archive containing all the other archives so that in the end, you’re only deploying one file. The application server will scan the contents of the EAR and deploy it. We discuss how an EAR is loaded by the server in section 1.2.

Table 1 Enterprise Java applications need to be assembled into specific types of JAR files before they can be deployed to an application server. These are the available module types as specified by Java EE.

Type Description Descriptor Contents
CAR Client application archives application-client .xml Thick Java client for EJBs
EAR Enterprise application archive application.xml Other Java EE modules such as EJB-JARs.
EJB-JAR EJB Java archive ejb-jar.xml Session beans, message-driven beans, and optionally entities. Needs a persistence.xml if entities are packaged.
RAR Resource adapter archives ra.xml Resource adapters.
WAR Web application archives web.xml Web application artifacts such as servlets, JSPs, JSF, static files, etc. Entities can also be packaged in this module. Needs a persistence.xml if entities are packaged.

To create these files, you can use the jar utility that comes with JDK. The final step is to assemble all the JAR files into one EAR file for deployment. In 3.1 we show you a build script that creates a JAR file. Each of these JAR types contains an optional deployment descriptor that describes the archive. As we have been discussing throughout this article, you can use metadata annotations instead of a deployment descriptor.

In this article, we focus primarily on the EAR file and the EJB-JAR file, which contains the session and message-driven beans, as well as entities.

It’s worth mentioning that entities can be packaged in most archive types. For example, the ability to package entities in WARs allows you to use the EJB 3 JPA in simple web applications or with lightweight frameworks such as Spring. Note that entities are not supported in RAR modules. This statement, however, begs the question of why Java does not have a different archive type to package EJB 3 entities, just as JBoss has the Hibernate Archive (HAR) to package persistence objects with Hibernate’s O/R framework.

You may know the answer to this question if you have followed the evolution of the EJB 3 specification. For those who haven’t, we now regale you with Tales from the Expert Group (cue spooky music)…

During the evolution of the EJB 3 Public Draft, the PAR (Persistence Archive) was introduced, which mysteriously vanished in the Proposed Final Draft. A huge, emotional battle was fought in the EJB and Java EE expert groups over whether to introduce a module type for a persistence module at the Java EE level, and suggestions were sought from the community at large, as well as from various developer forums. Many developers think a separate persistence module is a bad idea because entities are supported both outside and inside the container. Considering that persistence is inherently a part of any enterprise application, it makes sense to support packaging entities with most module types, instead of introducing a new module type specialized for packaging entities.

Now that you know what modules are supported and a little about how they were arrived at, shall we take a quick peek under the hood of an EAR module?

Dissecting the EAR file

To understand how deployment works, let’s take a closer look at the EAR file, the top-level archive file that contains other Java EE archives when it is deployed to the application server. For instance, the ActionBazaar application contains an EJB module, a web module, a JAR containing helper classes, and an application client module. The file structure of the EAR file that ActionBazaar uses looks like this:

META-INF/application.xml
actionBazaar-ejb. jar
actionBazaar .war
actionBazaar-client.jar

lib/actionBazaar-commons.jar

application .xml is the deployment descriptor that describes the standard Java EE modules packaged in each EAR file. The contents of application.xml look something like listing 1.

Listing 1: Deployment descriptor for the ActionBazaar EAR module

If you review the EAR file descriptor in listing 1, you’ll see that it explicitly identifies each of the artifacts as a specific type of module. When you deploy this EAR to an application server, the application server uses the information in the deployment descriptor to deploy each of the module types.

Java EE 5 made the deployment descriptor optional, even in the EAR. This is a departure from previous versions of Java EE, where it was mandatory. The Java EE 5.0.compliant application servers deploy by performing automatic detection based on a standard naming convention or reading the content of archives; see http://java.sun.com/blueprints/code/namingconventions.html.

Next, let’s take a look at how application servers deploy an EAR module.

Loading the EAR module

During the deployment process, the application server determines the module types, validates them, and takes appropriate steps so that the application is available to users. Although all application servers have to accomplish these goals, it’s up to the individual vendor exactly how to implement it. One area where server implementations stand out is in how fast they can deploy the archives.

While vendors are free to optimize their specific implementation, they all follow the specification’s rules when it comes to what is required to be supported and in what order the loading occurs. This means that your application server will use the algorithm from figure 1 when attempting to load the EAR file that contains modules or archives from table 1.

Before we delve into how EJB components and entities are packaged, let’s briefly discuss what class loading is and how it works in the Java EE environment.

Figure 1: Rules followed by application servers to deploy an EAR module. Java EE 5 does not require a deployment descriptor in the EAR module that identifies the type of modules packaged. It is the responsibility of Java EE container to determine the type of module based on its name (extension) and its content. It does so by following this algorithm.

Exploring class loading

There is a misconception among many developers that all classes are loaded into memory when the JVM starts up; this is not true. Classes are loaded dynamically as and when they are needed at runtime. This process of locating the byte code for a given class name and converting that code into a Java class instance is known as class loading. Your application may have hundreds of EJBs and other resources; loading all these classes into the JVM consumes a lot of memory. Most application servers use a sophisticated mechanism to load classes as and when needed. Therefore, your EJB class will be loaded into memory only when a client accesses it. However, it is implementation specific. Application servers support the bean pooling mechanism, so EJB classes would be loaded into memory while some instances would be instantiated and put into the pool during deployment time.

When you build an application using EJB 3, you may use third-party libraries such as Log4J or you may depend on an in-house shared library configured in the application server. You may have web applications that depend on your EJB components and entities. As you can see, a complex application may depend on libraries available at several places. This means that you may run into many deployment errors such as ClassNotFoundException or ClassNoDefException. Understanding the class-loading concepts will educate you on effectively packaging your EJB 3 applications and help you troubleshoot any deployment-related issues.

In this section, we introduce the concept of class loading and look at the class-loader hierarchy in an application server. We then expose the parent delegation model. Finally, we examine class loading in Java EE and explore the dependencies between different modules.

Class-loading basics

If you’ve built simple applications with Java, you must be aware that when you run your application, the classes that make it up (often packaged in a standard JAR file) are made available to the JVM through the CLASSPATH environment variable. When a particular class is invoked, the JVM loads that class into memory by locating it from the available byte code files provided either via JAR files in the CLASSATH or a specified directory structure.

Class loading is initially performed by the JVM when it starts up. It loads the essential classes required, and then subclasses of the java.lang.ClassLoader class take the lead. These class loaders allow applications to load classes dynamically that may not be required during the compilation process. By default, the JVM utilizes a few different class loaders. As an illustration, the Sun JVM has a hierarchy of three loaders, as shown in figure 2.

The boot class loader loads all platform classes that the Java language requires, such as classes in the java.lang or java.util package. You can optionally use the bootclasspath command-line option of the JVM to instruct the boot class loader to load additional classes from other JAR files.

The extension class loader is a child class loader of the boot class loader, and loads classes from any JARs placed in the $JAVA_HOME/jre/lib/ ext directory, or in a separate directory specified with the .Dj ava.ext.dir system property. By default, it loads the Java cryptography library, as well as the security classes.

The system class loader actually loads application classes as specified by an application, and is also known as the application class loader. You can use several mechanisms to specify the location from which the system class loader loads classes. One way is to specify the CLASSPATH environment variable. Another is to specify the manifest Class-Path entry of a JAR file that is being executed or that is in the CLASSPATH.

For example, the JAR file actionBazaar-client.jar has a Manifest.mf file in the META-INF directory that has this entry:

Class-Path: lib/actionBazaar-utility.jar.

When the class loader loads the classes, it will search not only for the required class in the actionBazaar-client.jar, but also in the actionBazaar-utility.jar. The location of the JAR specified in the manifest Class-Path is relative to the JAR file that contains it.

For a simple Java application, this process is probably as simple as packaging the classes in a JAR and making the file available in the CLASSPATH. However, in a sophisticated environment such as Java EE, the application servers utilize several mechanisms to load the classes from a variety of locations, such as an application module, a library module, or a shared library configured in the application server environment.

When you start up an application server, a Java process starts loading classes required for the application server. When you deploy and execute an application in a Java application server, the application server loads the classes dynamically by creating new instances of class loaders.

Exposing the classic parent delegation model

You must be curious as to why JVM always loads the class from the parent class loader. In this section we will uncover the reason.

Let’s review the scenario for ActionBazaar in order to understand the class-loading delegation model. The ActionBazaar website is built with JSP pages that invoke EJBs. When a user visits the ActionBazaar website and browses the items listed for auction, the application server uses class loaders to dynamically load required classes from application modules. All class loaders follow a standard algorithm to load classes, as illustrated in figure 3.

A class loader loads a class dynamically on an as-needed basis. It first looks at its local cache to see if it was loaded earlier. If not, it asks its parent to load the class. If its parent cannot load the class, it attempts to load it from its local code sources. Simply put, a code source is a base location, such as a JAR file, which the JVM searches for classes. This approach is called the Parent First delegation model.

Now that we’ve reviewed the basics of Java class loading, let’s quickly review how class loading works in a Java EE application.

Class loading in Java EE applications

As we discussed earlier, an EJB application may make use of third-party libraries. In order to enable that, most Java EE containers use sophisticated mechanisms to load classes from a variety of places. You may remember from previous discussions that we follow standard practices to package our application components into standard-compliant archives such as EAR, EJB-JAR, WAR, and so forth. Table 2 lists the code sources for commonly used Java EE modules. For simplicity we are ignoring resource adapter (RAR) modules.

Table 2 A standard archive may load classes either packaged inside it or from any other archives it is dependent on.

Module Code Sources
EAR
  1. All JARs in the /lib directory of the EAR
  2. Manifest Class-Path of any JARs in 1
EJB-JAR
  1. EJB-JAR file itself
  2. JARs referenced by manifest Class-Path of EJB-JAR
  3. JARs referenced by manifest Class-Path of above JARs (in 2)
WAR
  1. WEB-INF/classes
  2. JARs in WEB-INF/lib
  3. JARs referenced by manifest Class-Path of WAR
  4. JARs referenced by manifest Class-Path of JARs in 2 and 3

The sooner you develop a good understanding of how the packaging standards work, the easier the whole packaging and deployment process will be.

Dependencies between Java EE modules

Unfortunately, no Java EE specification provides a standard for class loading, and each application server implements class loaders in whatever way seems best to the vendor. However, Java EE defines the visibility and sharing of classes between different modules, and we can depict the dependency between different modules as shown in figure 4.

As illustrated in figure 4, the EAR class loader loads all JARs in the lib directory that is shared between multiple modules. Typically a single EJB class loader loads all EJB packaged in all EJB-JAR modules. The EJB class loader is often the child of the application class loader, and loads all EJB classes. Because the EJB is a child to the EAR class loader, all classes loaded at the> EAR level will be visible to the EJBs.

Figure 4: Illustration of class visibility of an EAR file containing multiple web modules, EJBs, and shared library modules. The EAR class loader loads the classes in the JARs packaged as library modules, and all classes loaded by the EAR class loader are visible to the EJBs. The classes loaded by EJB class loader are typically visible to the web module in most containers because the WAR class loader is a child of the EJB class loader.

EJBs are accessible from WAR modules. Furthermore, the EJB class loader is the parent of the WAR application class loader, and all EJB classes will be visible to the WAR module by default.

So before we move on to packaging EJBs, let's recap how this is going to help in packaging EJB 3 applications. If you package classes in a specific EJB module, it will probably be visible to only that module. If you want your classes (helper and utility) to be visible to all modules in the EAR file, you can package them as a library module in the EAR.

Armed with this knowledge on class loading, we can now return to the discussion on packaging EJBs. First we'll talk about the packaging of session and message-driven beans, and quickly proceed to the packaging of persistence entities.

Packaging session and message-driven beans

A car manufacturer has to assemble all essential parts of a car before it can run. As an EJB developer you build core classes that make your application, and you have to assemble them as an EJB-JAR and deploy them into your application server before your customers can execute the application.

Throughout this article we have used annotations and avoided deployment descriptors. The EJB deployment descriptor (ejb-jar.xml) describes the contents of an EJB-JAR, such as beans, interceptors, the resource they use, security, transaction settings, and so forth. For every annotation we have discussed in this article there is an element in the descriptor. Deployment descriptors can be used to override settings in metadata annotations. Let's now uncover the elements of ejb-jar.xml and explain how you can define default interceptors. We'll conclude this section with a discussion on vendor-specific descriptors and annotations.

Packaging EJB-JAR

Session beans and MDBs can be packaged in a Java standard JAR file as defined in the Java Archive specification at http://java.sun.com/j2se/1.5.0/docs/guide/jar/. To create an EJB-JAR file to package your EJB components, you have to compile your EJB classes and then create a JAR file using the jar tool supplied by JDK. For example, you can use the following command to create the adventure-ejb.jar:

jar cvf adventure-ejb.jar *

This will create a JAR file containing all class files in the current directory, and any subdirectories below the current directory. You can automate building JAR files using several tools. Most modern IDEs support building EJB-JAR modules, and make the creation of JAR modules somewhat transparent to you. A number of specialized utilities in addition to IDEs also support the build process. Today, the most frequently used tool to assist with builds is Apache Ant (http://ant.apache.org/), although there is a strong movement toward Apache Maven (http://maven.apache.org/). Listing 2 shows a sample Ant build script that was created to automate building an EJB-JAR module. Ant build scripts are provided with our code examples and can be downloaded from Manning's (my publisher) website (www.manning.com/panda).

Listing 2 Sample script for building an EJB-JAR file

The EJB-JAR file must include the interfaces and bean classes. It may also include any helper classes. Optionally the helper classes may be packaged in a separate JAR file in the EAR file. You have two options:

  • The JAR containing helper classes may be packaged in the lib directory of the EAR file. Using this approach, the packaged classes will be automatically visible to all modules in the EAR module.
  • If you want to limit the visibility to only a specific EJB-JAR or WAR module, you can create an entry in the Manifest.mf file of the module that contains a Class-Path attribute to the JAR file.

Now that you know the structure of EJB-JAR and how to package it, let's look at the elements of ejb-jar.xml.

Deployment descriptors vs. annotations

An EJB deployment descriptor (ejb-jar.xml) describes the contents of an EJB module, any resources used by it, and security transaction settings. The deployment descriptor is written in XML, and because it is external to the Java byte code, it allows you to separate concerns for development and deployment.

The deployment descriptor is optional and you could use annotations instead, but we don't advise using annotations in all cases for several reasons. Annotations are great for development, but may not be well suited for deployments where settings may change frequently. During deployment it is common in large companies for different people to be involved for each environment (development, test, production, etc.). For instance, your application requires such resources as DataSource JMS objects, and the JNDI names for these resources change between these environments. It does not make sense to hard-code these names in the code using annotations. The deployment descriptor allows the deployers to understand the contents and take appropriate action. Keep in mind that even if the deployment descriptor is optional, certain settings such as default interceptors for an EJB-JAR module require a deployment descriptor. An EJB-JAR module may contain

  • A deployment descriptor (ejb-jar.xml)
  • A vendor-specific deployment descriptor, which is required to perform certain configuration settings in a particular EJB container

The good news is that you can mix and match annotations with descriptors by specifying some settings in annotations and others in the deployment descriptor. Be aware that the deployment descriptor is the final source and overrides settings provided through metadata annotations. To clarify, you could set the TransactionAttribute for an EJB method as REQUIRES_NEW using an annotation, and if you set it to REQUIRED in the deployment descriptor, the final effect will be REQUIRED.

Annotations vs. XML descriptors: the endless debate
Sugar or sugar substitute? It's a matter of choice. Zero calories versus the risk of cancer? The debate may well be endless, and the same applies to the debate between annotations and deployment descriptors. Some people find annotations elegant, while they see XML as verbose, ugly, and hard to maintain. Others find annotations unsightly, and complain that annotations complicate things by making configurations reside closer to the code. The good thing is that you have a choice, and Java EE allows you to override annotation settings in the code with deployment descriptors if you desire. We suggest you weigh the pros and cons of these options with a clear mind.

Although we won't delve deeply into deployment descriptors, let's look at some quick examples to see what deployment descriptors look like so that you can package a deployment descriptor in your EJB module if you need to. Listing 3 shows a simple example of a deployment descriptor for the BazaarAdmin EJB.

Listing 3: A simple ejb-jar.xml

If you are familiar with EJB 2, you may have noticed that the only notable difference between this deployment descriptor and one in EJB 2 is that the version attribute must be set to 3.0, and the home element is missing because EJB 3 does not require a home interface.

Editor's Note: The bracketed numbers in the following paragraph refer to the callouts in listing 3.

If you are using deployment descriptors for your EJBs, make sure that you set the ejb-jar version to 3.0 [1] because this will be used by the Java EE server to determine the version of the EJB being packaged in an archive. The name element [2] identifies an EJB and is the same as the name element in the @Stateless annotation. These must match if you are overriding any values specified in the annotation with a descriptor. The session-type element [3] determines the type of session bean. This value can be either stateless or stateful. You can use transaction-type [4] to specify whether the bean uses CMT (Container) or BMT (Bean). The transaction, security, and other assembly details are set using the assembly-descriptor tag of the deployment descriptor [5] and [6].

Table 3 lists commonly used annotations and their corresponding descriptor tags. Note that as we mentioned earlier there is an element for every annotation. You will need only those which make sense for your development environment. Some of the descriptor elements you'll probably need are for resource references, interceptor binding, and declarative security. We encourage you to explore these on your own.

Table 3 One-to-one mapping between annotations and XML descriptor elements

Annotation Type Annotation Element Corresponding Descriptor Element
@Stateless EJB type   <session-type>Stateless
    name ejb-name
@Stateful EJB type   <session-type>Stateful
      ejb-name
@MessageDriven EJB type   message-driven
    name ejb-name
@Remote Interface type   remote
@Local Interface type   local
@Transaction-Management Transaction management type at bean level   transaction-type
@Transaction-Attribute Transaction settings method   container-transaction trans-attribute
@Interceptors Interceptors   interceptor-binding interceptor-class
@ExcludeClass-Interceptors Interceptors   exclude-class-interceptor
@ExcludeDefault-Interceptors Interceptors   exclude-default-interceptors
@AroundInvoke Custom interceptor   around-invoke
@PreConstruct Lifecycle method   pre-construct
@PostDestroy Lifecycle method   post-destroy
@PostActivate Lifecycle method   post-activate
@PrePassivate Lifecycle method   pre-passivate
@DeclareRoles Security setting   security-role
@RolesAllowed Security setting   method-permission
@PermitAll Security setting   unchecked
@DenyAll Security setting   exclude-list
@RunAs Security setting   security-identity run-as
@Resource Resource references
(DataSource, JMS, Environment, mail, etc.)
  resource-ref
resource-env-ref
message-destination-ref
env- ref
  Resource injection Setter/field injection injection-target
@EJB EJB references   ejb-ref
ejb-local-ref
@Persistence-Context Persistence context reference   persistence-context-ref
@PersistenceUnit Persistence unit reference   persistence-unit-ref

You can find the XML schema for the EJB 3 deployment descriptor at http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd.

Overriding annotations with deployment descriptors

As we explained, you can mix and match deployment descriptors with annotations and use descriptors to override settings originally specified using annotations. Keep in mind that the more you mix the two, the more likely you are to make mistakes and create a debugging nightmare.

NOTE The basic rule to remember is that the name element in stateless, stateful, and message-driven annotations is the same as the ejb-name element in the descriptor. If you do not specify the name element with these annotations, the name of the bean class is understood to be the ejb-name element. This means that when you are overriding an annotation setting with your deployment descriptor, the ejb-name element must match the bean class name.

Suppose we have a stateless session bean that uses these annotations:

@Stateless (name = "BazaarAdmin")
public class BazaarAdminBean implements BazaarAdmin {
...
@TransactionAttribute (TransactionAttributeType.REQUIRES_NEW)
public Item addItem() {
   }
}

The value for the name element specified is BazaarAdmin, which is the same as the value of the ejb-name element specified in the deployment descriptor:

<ejb-name>BazaarAdmin</ejb-name>

If you do not specify the name element, the container will use the name of BazaarAdminBean as the name of the bean class, and in order to override annotations you have to use that name in the deployment descriptor:

<ejb-name>BazaarAdminBean</ejb-name>

We used @TransactionAttribute to specify that the transaction attribute for a bean method be REQUIRES_NEW. If we want to override it to use REQUIRED,1 then we use the following descriptor:

Editor's Note: The bracketed numbers in the following paragraph refer to the callouts in the code snippet above.

In this example, we used the assembly-descriptor element to specify a transaction attribute [2]. In addition, the ejb-name element [1] in the assembly-descriptor matches the original name specified with the @Stateless annotation in the bean class.

Specifying default interceptor settings

Interceptors allow you to implement cross-cutting code in an elegant manner. An interceptor can be defined at the class or method level, or a default interceptor can be defined at the module level for all EJB classes in the EJB-JAR. We mentioned that default interceptors for an EJB module can only be defined in the deployment descriptor (ejb-jar.xml). Listing 4 shows how to specify default interceptors for an EJB module.

Listing 4 Default interceptor setting in ejb-jar.xml

Editor's Note: The bracketed numbers in the following paragraph refer to the callouts in listing 4.

The interceptor-binding [1] tag defines the binding of interceptors to a particular EJB with the ejb-name element. If we want to define the default interceptor or an interceptor binding for all EJBs in the EJB module, then we can specify * as the value for ejb-name [2]. We specify a class to use as the interceptor with the <interceptor-class> tag. As evident from the listing, you can specify multipleinterceptors in the same binding, and the order in which they are specified in the deployment descriptor determines the order of execution for the interceptor. In our example, CheckPermissionInterceptor will be executed prior to ActionBazaarDefaultInterceptor when any EJB method is executed.

Using vendor-specific annotations and descriptors

We've already explained that stateless session beans and MDBs may be pooled. In addition, you can configure passivation for stateful session beans, and you can set up the handling of poisonous messages for MDBs. However, we have not discussed configuration details for either of these scenarios. Unfortunately, these configurations are left to the vendors as proprietary features, and they can be supported with proprietary annotations, proprietary deployment descriptors, or both. Table 4 lists the name of the deployment descriptor file for some popular application servers.

Table 4 Vendor-specific deployment descriptors for popular application servers

Application Server Vendor-Specific Deployment Descriptor
BEA WebLogic weblogic-ejb-jar.xml
IBM WebSphere ibm-ejb-jar.xml
JBoss jboss.xml
Oracle Application Server orion-ejb-jar.xml
Sun GlassFish sun-ejb-jar.xml

Many developers shun deployment descriptors as a matter of inconvenience. Application server vendors will continue to provide support for annotations that match deployment descriptor elements, as developers voice their preference for these features. Chances are that each vendor has a set of proprietary annotations to set configuration information with the code.

For example, you can use the oracle.j2ee.ejb.StatelessDeployment proprietary annotation to provide configuration information such as pooling and transaction management for stateless session beans. Look at the following code, which configures pooling with Oracle's proprietary annotation:

import oracle.j2ee.ejb.StatelessDeployment;

@StatelessDeployment(
   minInstances = 100, maxInstances = 500,
   poolCacheTimeout = 120) @Stateless (name = "BazaarAdmin")
public class BazaarAdminBean implements BazaarAdmin {
}

As other Java EE vendors create their implementations of EJB 3, we anticipate that each vendor will devise its own subset of corresponding annotations as well.

You should review these proprietary annotations with caution for a couple of reasons. First, adding configuration information in the code is not a good idea, although application servers provide the ability to override this information with their proprietary deployment descriptors. This is not desirable because in order to make a change to the setting, the code must be edited and compiled, and in most organizations it must go through a significant quality assurance effort before being released to production. Another reason is that as the code is promoted across different environments (Development, Test, Production, etc.), the deployer may change the configuration to accommodate different servers and environmental configurations.

Second, this defeats the goal of portability of applications. Deployment descriptors serve as a guideline to the deployer to understand the contents, the applications, and the suggested configurations. Deployers manage the deployment to each environment by tweaking the configuration. We recommend using the proprietary deployment descriptors instead of using deployment annotations. If you're using Oracle, you could use the following element in Oracle's proprietary descriptor (orion-ejb-jar.xml) element as follows:

<session-deployment
   name = "BazaarAdmin"
   tx-retry-wait = "60"
   max-instances = "500"
   min-instances = "100"
   pool-cache-timeout = "120"
   location = "BazaarAdmin">
</session-deployment>

Endnotes

1. Keep in mind the impact of changing a transaction attribute from RequiresNew to Required, as shown in this example.

Summary

At the heart of Java EE applications lies the art of assembly and packaging enterprise applications. This article briefly introduced the concepts of class loading and code sources used by various application archives. We also explained how to
package all of the EJB types, including persistence entities. You learned about the deployment descriptor of an EJB-JAR module, and how you can use descriptors to override settings specified in metadata annotations.

About the Authors

Debu Panda is a Lead Product Manager of the Oracle Application Server development team, where he drives development of the Java EE container. He has more than 15 years of experience in the IT industry and has published numerous articles on enterprise Java technologies in several magazines and has presented at many conferences. His J2EE-focused weblog can be found at debupanda.com.

Reza Rahman is an architect with Tripod Technologies, an IT solutions company focusing on Java EE in the Baltimore-NYC corridor. Reza has been working with Java as a language and Java EE as a platform since their inception in the mid-nineties. He has worked with both Enterprise Java Beans and open source tools like Spring and Hibernate, developing enterprise systems in the software, consulting, financial, Telecommunications, and manufacturing industries.

Derek Lane is the CTO of Semantra, Inc. He has worn various hats in his career including mentor, coach, architect, manager, developer, trainer, methodologist, and resident open source zealot. Lane is a contributor to projects of various shape and size as author, presenter, and technical reviewer. Lane is the founder of both the Oklahoma City Java User Group (OKCJUG) and the Dallas/Fort Worth, Texas MicroJava User Group; and has been active as a member, presenter, and mentor for over a decade at various technology user groups across the Midwest and Southern U.S.

Source of This Material

EJB 3 in Action
By Debu Panda, Reza Rahman, Derek Lane
Published: April 4, 2007, Paperback: 712 pages
Published by Manning Publications Co.
ISBN: 1-933988-34-7
Retail price for softbound print book + PDF ebook

PDF ebook: $22.50
This material is from Chapter 11 of the book.
Reprinted with the publisher's permission.

Get the Free Newsletter!
Subscribe to Developer Insider for top news, trends & analysis
This email address is invalid.
Get the Free Newsletter!
Subscribe to Developer Insider for top news, trends & analysis
This email address is invalid.

Latest Posts

Related Stories