Packaging EJB 3 Applications, Page 3
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.
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  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  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  determines the type of session bean. This value can be either stateless or stateful. You can use transaction-type  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  and .
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|
|@Transaction-Management||Transaction management type at bean level||transaction-type|
|@Transaction-Attribute||Transaction settings method||container-transaction trans-attribute|
|@RunAs||Security setting||security-identity run-as|
(DataSource, JMS, Environment, mail, etc.)
|Resource injection||Setter/field injection||injection-target|
|@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.
Page 3 of 4