Developing Your First EJBs, Part 2
Pages: 1, 2
The TravelAgent EJB's Deployment Descriptor
The TravelAgent EJB uses an XML deployment descriptor similar to the one used for the Cabin entity bean. The following sections contain the ejb-jar.xmlfile used to deploy the TravelAgent bean in EJB. Chapter 11 describes how to deploy several beans in one deployment descriptor, but for now the TravelAgent and Cabin EJBs are deployed separately.
EJB 2.1: Deployment descriptor
In EJB 2.1, the deployment descriptor for the TravelAgent EJB looks like this:
<?xml version="1.0" encoding="UTF-8" ?>
<ejb-jar
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd"
version="2.1">
<enterprise-beans>
<session>
<ejb-name>TravelAgentEJB</ejb-name>
<home>com.titan.travelagent.TravelAgentHomeRemote</home>
<remote>com.titan.travelagent.TravelAgentRemote</remote>
<ejb-class>com.titan.travelagent.TravelAgentBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-ref>
<ejb-ref-name>ejb/CabinHomeRemote</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<home>com.titan.cabin.CabinHomeRemote</home>
<remote>com.titan.cabin.CabinRemote</remote>
</ejb-ref>
<security-identity><use-caller-identity/></security-identity>
</session>
</enterprise-beans>
<assembly-descriptor>
...
</assembly-descriptor>
</ejb-jar>
EJB 2.0: Deployment descriptor
In EJB 2.0, the deployment descriptor for the TravelAgent EJB looks like this:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise
JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>TravelAgentEJB</ejb-name>
<home>com.titan.travelagent.TravelAgentHomeRemote</home>
<remote>com.titan.travelagent.TravelAgentRemote</remote>
<ejb-class>com.titan.travelagent.TravelAgentBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-ref>
<ejb-ref-name>ejb/CabinHomeRemote</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<home>com.titan.cabin.CabinHomeRemote</home>
<remote>com.titan.cabin.CabinRemote</remote>
</ejb-ref>
<security-identity><use-caller-identity/></security-identity>
</session>
</enterprise-beans>
<assembly-descriptor>
...
</assembly-descriptor>
</ejb-jar>
EJB 2.0 and 1.1: Defining the XML elements
The only significant difference between the 2.1 and 2.0 deployment descriptors is that EJB 2.1 declares the use of an XML Schema for validation while EJB 2.0 uses a DTD.
Other than the <session-type> and
<ejb-ref> elements, the TravelAgent
EJB's XML deployment descriptor should be familiar:
it uses many of the same elements as the Cabin
EJB's. The <session-type>
element can be Stateful or
Stateless, to indicate which type of session bean
is used. In this case, we are defining a stateless session bean.
The <ejb-ref> element is used at deployment
time to map the bean references used within the TravelAgent EJB. In
this case, the <ejb-ref> element describes
the Cabin EJB, which we already deployed. The
<ejb-ref-name> element specifies the name
that must be used by the TravelAgent EJB to obtain a reference to the
Cabin EJB's home. The
<ejb-ref-type> tells the container what kind
of bean it is, Entity or
Session. The <home> and
<remote> elements specify the fully
qualified interface names of the Cabin's home and
remote bean interfaces.
When the bean is deployed, the <ejb-ref>
will be mapped to the Cabin EJB in the EJB server. This is a
vendor-specific process, but the outcome should always be the same.
When the TravelAgent EJB does a JNDI lookup using the context name
"java:comp/env/ejb/CabinHomeRemote",
it obtains a remote reference to the Cabin EJB's
home. The purpose of the <ejb-ref> element
is to eliminate network-specific and implementation-specific use of
JNDI to obtain remote bean references. This makes a bean more
portable, because the network location and JNDI service provider can
change without affecting the bean code or even the XML deployment
descriptor.
While we haven't yet created a local interface for
our beans, it's always preferable to use local
references instead of remote references when beans access each other
within the same server. Local references are specified using the
<ejb-local-ref> element, which looks just
like the <ejb-ref> element.
The <assembly-descriptor> section of the
deployment descriptor is the same for EJB 2.1 and EJB 2.0:
<assembly-descriptor>
<security-role>
<description>
This role represents everyone who is allowed full access
to the TravelAgent EJB.
</description>
<role-name>everyone</role-name>
</security-role>
<method-permission>
<role-name>everyone</role-name>
<method>
<ejb-name>TravelAgentEJB</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<container-transaction>
<method>
<ejb-name>TravelAgentEJB</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
Deploying the TravelAgent EJB
Once you've defined the XML deployment descriptor, you are ready to place the TravelAgent EJB in its own JAR file and deploy it into the EJB server. Use the same process to JAR the TravelAgent EJB as you used for the Cabin EJB. Shrink-wrap the TravelAgent EJB class and its deployment descriptor into a JAR file and save the file to the com/titan/travelagent directory:
\dev % jar cf travelagent.jar com/titan/travelagent/*.class META-INF/ejb-jar.xml
F:\..\dev>jar cf travelagent.jar com\titan\travelagent\*.class META-INF\ejb-jar.xml
You might have to create the META-INF directory first, and copy ejb-jar.xml into that directory. The TravelAgent EJB is now complete and ready to be deployed.
To make your TravelAgent EJB available to a client application, you
need to use the deployment utility or wizard of your EJB server. The
deployment utility reads the JAR file to add the TravelAgent EJB to
the EJB server environment. Unless your EJB server has special
requirements, it is unlikely that you will need to change or add any
new attributes to the bean. You will not need to create a database
table, since the TravelAgent EJB is using the Cabin EJB and is not
itself persistent. However, you will need to map the
<ejb-ref> element in the TravelAgent
EJB's deployment descriptor to the Cabin EJB. Your
EJB server's deployment facilities provides a
mechanism for accomplishing this task (see Exercise 4.2 in the
Workbook).
Creating a Client Application
To show that our session bean works,
we'll create a simple client application that uses
it. This client produces a list of cabins assigned to ship 1 with a
bed count of 3. Its logic is similar to the client we created earlier
to test the Cabin EJB: it creates a context for looking up
TravelAgentHomeRemote, creates a TravelAgent EJB,
and invokes listCabins( ) to generate a list of
the cabins available. Here's the code:
import com.titan.travelagent.TravelAgentRemote;
import com.titan.travelagent.TravelAgentHomeRemote;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.ejb.CreateException;
import java.rmi.RemoteException;
import java.util.Properties;
import javax.rmi.PortableRemoteObject;
public class Client_3 {
public static int SHIP_ID = 1;
public static int BED_COUNT = 3;
public static void main(String [] args) {
try {
Context jndiContext = getInitialContext( );
Object ref = jndiContext.lookup("TravelAgentHomeRemote");
TravelAgentHomeRemote home = (TravelAgentHomeRemote)
PortableRemoteObject.narrow(ref,TravelAgentHomeRemote.class);
TravelAgentRemote travelAgent = home.create( );
// Get a list of all cabins on ship 1 with a bed count of 3.
String list [] = travelAgent.listCabins(SHIP_ID,BED_COUNT);
for(int i = 0; i < list.length; i++){
System.out.println(list[i]);
}
} catch(java.rmi.RemoteException re){re.printStackTrace( );}
catch(Throwable t){t.printStackTrace( );}
}
static public Context getInitialContext( ) throws Exception {
Properties p = new Properties( );
// ... Specify the JNDI properties specific to the vendor.
return new InitialContext(p);
}
}
When you have successfully run Client_3, the
output should look like this:
1,Master Suite ,1
3,Suite 101 ,1
5,Suite 103 ,1
7,Suite 105 ,1
9,Suite 107 ,1
12,Suite 201 ,2
14,Suite 203 ,2
16,Suite 205 ,2
18,Suite 207 ,2
20,Suite 209 ,2
22,Suite 301 ,3
24,Suite 303 ,3
26,Suite 305 ,3
28,Suite 307 ,3
30,Suite 309 ,3
You have now successfully created the first piece of the TravelAgent session bean - a method that obtains a list of cabins by manipulating the Cabin EJB entity.
Return to ONJava.com.