ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Developing Your First Enterprise Beans, Part 1
Pages: 1, 2, 3, 4

The callback methods

The CabinHomeRemote interface defines one create( ) method, so there is only one corresponding ejbCreate( ) method and one ejbPostCreate( ) method defined by the CabinBean class. When a client invokes the create( ) method on the remote home interface, it is delegated to a matching ejbCreate( ) method on the entity bean instance. The ejbCreate( ) method initializes the fields; in the case of the CabinBean, it sets the id field.

TIP: Although it's not required by the EJB specification, some J2EE application vendors insist that ejbCreate( ) throw a javax.ejb.CreateException - this is true of the J2EE 1.4 SDK. This has never been a requirement, but it's an issue that continues to crop up every time there is a new edition of this book.

The ejbCreate( ) method always returns the primary key type; with container-managed persistence, this method returns the null value. It's the container's responsibility to create the primary key. Why does it return null? This convention makes it easier for EJB vendors that support container-managed persistence using bean-managed persistence - it's a technique that is more common in EJB 1.1. Bean-managed persistence beans, which are covered in Chapter 10, always return the primary key type.



Once the ejbCreate( ) method has executed, the ejbPostCreate( ) method is called to perform any follow-up operations. The ejbCreate( ) and ejbPostCreate( ) methods must have signatures that match the parameters and (optionally) the exceptions of the home interface's create( ) method. The ejbPostCreate( ) method is used to perform any postprocessing on the bean after it is created, but before it can be used by the client. Both methods will execute, one right after the other, when the client invokes the create( ) method on the remote home interface.

The findByPrimaryKey( ) method is not defined in container-managed bean classes. Instead, find methods are generated at deployment and implemented by the container. With bean-managed entity beans, find methods must be defined in the bean class. In Chapter 10, when you develop bean-managed entity beans, you will define the find methods in the bean classes you develop.

The CabinBean class implements javax.ejb.EntityBean, which defines seven callback methods: setEntityContext( ), unsetEntityContext( ), ejbActivate( ), ejbPassivate( ), ejbLoad( ), ejbStore( ), and ejbRemove( ). The container uses these callback methods to notify the CabinBean of certain events in its life cycle. Although the callback methods are implemented, the implementations are empty. The CabinBean is simple enough that it doesn't need to do any special processing during its life cycle. When we study entity beans in more detail in Chapter 6 through Chapter 11, we will take advantage of these callback methods.

The Deployment Descriptor

You are now ready to create a deployment descriptor for the Cabin EJB. The deployment descriptor performs a function similar to a properties file. It describes which classes make up an enterprise bean and how the enterprise bean should be managed at runtime. During deployment, the deployment descriptor is read and its properties are displayed for editing. The deployer can then modify and add settings as appropriate for the application's operational environment. Once the deployer is satisfied with the deployment information, she uses it to generate the entire supporting infrastructure needed to deploy the enterprise bean in the EJB server. This may include resolving enterprise bean references, adding the enterprise bean to the naming system, and generating the enterprise bean's EJB object and EJB home, persistence infrastructure, transactional support, and so forth.

Although most EJB server products provide a wizard for creating and editing deployment descriptors, we will create ours directly so that the enterprise bean is defined in a vendor-independent manner. This requires some manual labor, but it gives you a much better understanding of how deployment descriptors are created. Once the deployment descriptor is finished, the enterprise bean can be placed in a JAR file and deployed on any EJB-compliant server of the appropriate version. An XML deployment descriptor has been created for every example in this book; they are available from the download site.

TIP: Vendors often require that you include vendor-specific deployment files along with the standard ones. This is an unfortunate situation that impacts portability, but something you need to be aware of. Consult your vendor's documentation to discover what additional configuration files they require.

Throughout this book, we show both the EJB 2.1 and EJB 2.0 code when they are different. In many cases, the component interfaces are the same; however, XML deployment descriptors will be different because EJB 2.1 uses XML Schema, while EJB 2.0 uses an XML DTD. This is the case with the Cabin EJB.

EJB 2.1: The Cabin EJB's deployment descriptor

Here's the deployment descriptor for the Cabin bean in EJB 2.1:

<?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>
        <entity>
            <ejb-name>CabinEJB</ejb-name>
            <home>com.titan.cabin.CabinHomeRemote</home>
            <remote>com.titan.cabin.CabinRemote</remote>
            <ejb-class>com.titan.cabin.CabinBean</ejb-class>
            <persistence-type>Container</persistence-type>
            <prim-key-class>java.lang.Integer</prim-key-class>
            <reentrant>False</reentrant>
            <abstract-schema-name>Cabin</abstract-schema-name>
            <cmp-field><field-name>id</field-name></cmp-field>
            <cmp-field><field-name>name</field-name></cmp-field>
            <cmp-field><field-name>deckLevel</field-name></cmp-field>
            <cmp-field><field-name>shipId</field-name></cmp-field>
            <cmp-field><field-name>bedCount</field-name></cmp-field>
            <primkey-field>id</primkey-field>
            <security-identity><use-caller-identity/></security-identity>
        </entity>
    </enterprise-beans>
    <assembly-descriptor>
    ...
    </assembly-descriptor>
</ejb-jar>

The ejb-jar element declares its namespace, the XSI namespace, and the location of the XML Schema that is used to validate it. The meaning of namespaces and XML schemas are described in more detail in Chapter 16.

EJB 2.0: The Cabin EJB's deployment descriptor

In EJB 2.0, the deployment descriptor is based on an XML DTD and 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>
        <entity>
            <ejb-name>CabinEJB</ejb-name>
            <home>com.titan.cabin.CabinHomeRemote</home>
            <remote>com.titan.cabin.CabinRemote</remote>
            <ejb-class>com.titan.cabin.CabinBean</ejb-class>
            <persistence-type>Container</persistence-type>
            <prim-key-class>java.lang.Integer</prim-key-class>
            <reentrant>False</reentrant>
            <abstract-schema-name>Cabin</abstract-schema-name>
            <cmp-field><field-name>id</field-name></cmp-field>
            <cmp-field><field-name>name</field-name></cmp-field>
            <cmp-field><field-name>deckLevel</field-name></cmp-field>
            <cmp-field><field-name>shipId</field-name></cmp-field>
            <cmp-field><field-name>bedCount</field-name></cmp-field>
            <primkey-field>id</primkey-field>
            <security-identity><use-caller-identity/></security-identity>
        </entity>
    </enterprise-beans>
    <assembly-descriptor>
    ...
    </assembly-descriptor>
</ejb-jar>

The <!DOCTYPE> element describes the purpose of the XML file, its root element, and the location of its DTD. The DTD is used to verify that the document is structured correctly. This element is discussed in detail in Chapter 16. EJB 2.0 specifies the ejb-jar_2_0.dtd as its DTD.

EJB 2.1 and 2.0: Defining the XML elements

One important difference between EJB 2.1 and EJB 2.0 is that they use different types of validation for deployment descriptors. EJB 2.0 uses XML DTDs, which have been employed for the past few years to validate the structure of the XML deployment descriptor. XML Schema is a new mechanism for validating deployment descriptors. XML Schema can validate not only the structure but also the values used in the deployment descriptor - something DTDs couldn't do well. On the other hand, XML Schema is complex and takes time to master, so there is a price to be paid for the added precision it offers.

The rest of the XML elements are nested one within another and delimited by beginning and ending tags. The structure is not complicated. If you have done any HTML coding, you already understand the format. An element always starts with a <name_of_tag> tag and ends with a </name_of_tag> tag. Everything in between - even other elements - is part of the enclosing element.

The first major element is the <ejb-jar>element, which is the root of the document. All the other elements must lie within this element. Next is the <enterprise-beans> element. Every bean declared in an XML file must be included in this section. This file describes only the Cabin EJB, but we could define several beans in one deployment descriptor.

The <entity> element shows that the beans defined within this tag are entity beans. Similarly, a <session> element describes session beans; since the Cabin EJB is an entity bean, we don't need a <session> element. In addition to a description, the <entity> element provides the fully qualified class names of the remote interface, home interface, bean class, and primary key. The <cmp-field> elements list all the container-managed fields in the entity bean class. These are the fields that will persist in the database and be managed by the container at runtime. The <entity> element also includes a <reentrant> element that can be set as True or False depending on whether the bean allows reentrant loopbacks or not.

The deployment descriptor also specifies the <security-identity> as <use-caller-identity/>, which simply means the bean propagates the calling client's security identity when it accesses resources or other beans. Security identities are covered in Chapter 3.

The section of the XML file after the <enterprise-beans> element is enclosed by the <assembly-descriptor> element, which describes the security roles and transaction attributes of the bean. In this example, this section of the XML file is the same for both EJB 2.1 and EJB 2.0:

<ejb-jar ...>
    <enterprise-beans>
    ...
    </enterprise-beans>
    
<assembly-descriptor>
        <security-role>
            <description>
                This role represents everyone who is allowed full access 
                to the Cabin EJB.
            </description>
            <role-name>everyone</role-name>
        </security-role>

        <method-permission>
            <role-name>everyone</role-name>
            <method>
                <ejb-name>CabinEJB</ejb-name>
                <method-name>*</method-name>
            </method>
        </method-permission>

        <container-transaction>
            <method>
                <ejb-name>CabinEJB</ejb-name>
                <method-name>*</method-name>
            </method>
            <trans-attribute>Required</trans-attribute>
        </container-transaction>
    
</assembly-descriptor>
</ejb-jar>

It may seem odd to separate the <assembly-descriptor> information from the <enterprise-beans> information, since it clearly applies to the Cabin EJB, but in the scheme of things, it's perfectly natural. A single XML deployment descriptor can describe several beans, which might all rely on the same security roles and transaction attributes. To make it easier to deploy several beans together, this common information is grouped in the <assembly-descriptor> element.

There is another (perhaps more important) reason for separating information about the bean itself from the security roles and transaction attributes. Enterprise JavaBeans defines the responsibilities of different participants in the development and deployment of beans. We don't address these development roles in this book because they are not critical to learning the fundamentals of EJB. For now, it's enough to know that the person who develops the beans and the person who assembles the beans into an application have separate responsibilities and therefore deal with separate parts of the XML deployment descriptor. The bean developer is responsible for everything within the <enterprise-beans> element; the bean assembler is responsible for everything within the <assembly-descriptor>. Throughout this book you will play both roles, developing the beans and assembling them. Other roles you will fill are that of the deployer, who actually loads the enterprise beans into the EJB container, and the administrator, who is responsible for tuning the EJB server and managing it at runtime. In real projects, these roles may be filled by an individual, several different individuals, or even teams.

The <assembly-descriptor> contains the <security-role> elements and their corresponding <method-permission> elements. In this example, there is one security role, everyone, which is mapped to all the methods in the Cabin EJB using the <method-permission> element. (The * in the <method-name> element means "all methods.")

The <container-transaction> element declares that all the methods of the Cabin EJB have a Required transaction attribute, which means that all the methods must be executed within a transaction. Transaction attributes are explained in more detail in Chapter 14. The deployment descriptor ends with the closing tag of the <ejb-jar> element.

Copy the Cabin EJB's deployment descriptor into the META-INF directory and save it as ejb-jar.xml. You have now created all the files you need to package your Cabin EJB. Figure 4-2 shows all the files that should be in the dev directory.

Figure 4-2
Figure 4-2. The Cabin EJB files

Pages: 1, 2, 3, 4

Next Pagearrow