Book Home Enterprise JavaBeans Search this book

10.6. Describing Bean Assembly

At this point, we've said just about all that can be said about the bean itself. We've come to the end of the enterprise-beans element, and are now ready to describe how the beans are assembled into an application. That is, we are ready to talk about the other major element inside the ejb-jar element: the assembly-descriptor element.

The assembly-descriptor element is optional, though it's difficult to imagine a bean being deployed successfully without an assembly-descriptor. When we say that the assembly-descriptor is optional, we really mean that a developer whose only role is to create enterprise beans (for example, someone who is developing beans for use by another party and who has no role in deploying the beans) can omit this part of the deployment descriptor. The descriptor is valid without it--but someone will almost certainly have to fill in the assembly information before the bean can be deployed.

The assembly descriptor serves three purposes. It describes the transactional attributes of the bean's methods; it describes the logical security roles that are used in the method permissions; and it specifies method permissions (i.e., which roles are allowed to call each of the methods). To this end, an assembly-descriptor can contain three kinds of elements, each of which is fairly complex in its own right. These are:

<container-transaction> (zero or more)

This element declares which transactional attributes apply to which methods. It contains an optional description element, one or more method elements, and exactly one trans-attribute element. Entity beans must have container-transaction declarations for all remote and home interface methods. Session beans that manage their own transactions will not have container-transaction declarations. This element is discussed in more detail in Section 10.6.1, "Specifying a Bean's Transactional Attributes".

<security-role> (zero or more)

The security-role element defines the security roles that are used when accessing a bean. These security roles are used in the method-permission element. A security-role element contains an optional description and one role-name. This element and the method-permission element are described in more detail in Section 10.6.2, "Specifying Security Roles and Method Permissions".

<method-permission> (zero or more)

This element specifies which security roles are allowed to call one or more of a bean's methods. It contains an optional description, one or more role-name elements, and one or more method elements. It is discussed in more detail in the Section 10.6.2, "Specifying Security Roles and Method Permissions" along with the security-role element.

The container-transaction and method-permission elements both rely on the ability to identify particular methods. This can be a complicated affair, given features of the Java language like method overloading. The method element is used within these tags to identify methods; it is described at length in Section 10.6.3, "Identifying Specific Methods".

10.6.1. Specifying a Bean's Transactional Attributes

The container-transaction elements are used to declare the transaction attributes for all the beans defined in the deployment descriptor. A container-transaction element maps many bean methods to a single transaction attribute, so each container-transaction specifies one transaction attribute and one or more bean methods.

The container-transaction element includes a single trans-attribute element, which can have one of six values: NotSupported, Supports, Required, RequiresNew, Mandatory, and Never. These are the transactional attributes that we discussed in Chapter 8, "Transactions". In addition to the trans-attribute, the container-transaction element includes one or more method elements.

The method element itself contains at least two subelements: an ejb-name element, which specifies the name of the bean, and a method-name element, which specifies a subset of the bean's methods. The value of the method-name can be a method name or an asterisk (*), which acts as wildcard for all the bean's methods. There's a lot more complexity to handle overloading and other special cases, but that's enough for now; we'll discuss the rest later.

Here's an example that shows how the container-transaction element is typically used. Let's look again at the Cabin bean, which we've used as an example throughout. Let's assume that we want to give the transactional attribute Mandatory to the create() method; all other methods use the Required attribute:

  <container-transaction>
     <method>
        <ejb-name>CabinBean</ejb-name>
        <method-name>*</method-name>
     </method>
     <trans-attribute>Required</trans-attribute>
  </container-transaction>
  <container-transaction>
     <method>
        <ejb-name>CabinBean</ejb-name>
        <method-name>create</method-name>
     </method>
     <trans-attribute>Mandatory</trans-attribute>
  </container-transaction>

In the first container-transaction, we have a single method element that uses the wildcard character (*) to refer to all of the Cabin bean's methods. We set the transactional attribute for these methods to Required. Then, we have a second container-transaction element that specifies a single method of the Cabin bean: create(). We set the transactional attribute for this method to Mandatory. This setting overrides the wildcard setting; in container-transaction elements, specific method declarations always override more general declarations.

The following methods must be assigned transaction attributes for each bean declared in the deployment descriptor:

For entity beans:

For session beans:

For session beans, only the business methods have transaction attributes; the create and remove methods in session beans do not have truncation attributes.

10.6.2. Specifying Security Roles and Method Permissions

Two elements are used to define logical security roles and to specify which roles can call particular bean methods. The security-role element can contain an optional description, plus a single role-name that provides the name. An assembly-descriptor can contain any number of security-role elements.

It's important to realize that the security role names defined here are not derived from a specific security realm. These security role names are logical; they are simply labels that can be mapped to real security roles in the target environment at deployment time. For example, the following security-role declarations define two roles--everyone and administrator:

<security-role>
  <description>
     This role represents everyone who is allowed read/write access 
     to existing cabin beans.
  </description>
  <role-name>everyone</role-name>
</security-role>
<security-role>
  <description>
     This role represents an administrator or manager who is 
     allowed to create new cabin beans.  This role may also be a member
     or the everyone role.
  </description>
  <role-name>administrator</role-name>
</security-role>

These role names might not exist in the environment in which the beans will be deployed. There's nothing inherent about everyone that gives it fewer (or greater) privileges than an administrator. It's up to the deployer to map one or more roles from the target environment to the logical roles in the deployment descriptor. So for example, the deployer may find that the target environment has two roles, DBA (database administrator) and CSR (customer service representative), that map to the administrator and everyone roles defined in the security-role element.

10.6.2.1. Assigning roles to methods

Security roles in themselves wouldn't be worth much if you couldn't specify what the roles were allowed to do. That's where the method-permission element comes in. This element maps the security-role s to methods in the remote and home interfaces of the bean. A method-permission is a very flexible declaration that allows a many-to-many relationship between methods and roles. A method-permission contains an optional description, one or more method elements, and one or more role-name elements. The names specified in the role-name elements correspond to the roles that appear in the security-role elements. Here's one way to set method permissions for the Cabin bean:

<method-permission>
     <role-name>administrator</role-name>
     <method>
         <ejb-name>CabinBean</ejb-name>
         <method-name>*</method-name>
     </method>
</method-permission>
<method-permission>
     <role-name>everyone</role-name>
     <method>
         <ejb-name>CabinBean</ejb-name>
         <method-name>getDeckLevel</method-name>
     </method>
</method-permission>

In this example, the administrator role has access to all methods in the Cabin bean. The everyone role only has access to the getDeckLevel() method--it cannot access any of the other methods of the Cabin bean. Note that the specific method permissions are combined to form a union. The getDeckLevel() method, for example, is accessible by both the administrator and everyone roles, which is the union of the permissions declared in the descriptor. Once again, it's important to note that we still don't know what administrator and everyone mean. That's defined by the person deploying the bean, who must map these logical security roles to real security roles defined in the target environment.

All the methods defined in the remote or home interface and all superinterfaces, including the methods defined in the EJBObject and EJBHome interfaces, can be assigned security roles in the method-permission elements. Any method that is excluded will not be accessible by any security role.

10.6.3. Identifying Specific Methods

The method element is used by the method-permission and container-transaction elements to specify a specific group of methods in a particular bean. The method element always contains an ejb-nameelement that specifies the bean's name and a method-name element that specifies the method. It may also include a description, method-paramselements that specify method parameters used to resolve overloaded methods, and a method-intf element that specifies whether the method belongs to the bean's home or remote interface. This last element takes care of the possibility that the same method name might be used in both interfaces.

10.6.3.1. Wildcard declarations

The method name in a method element can be a simple wildcard (*). A wildcard applies to all methods of the bean's home and remote interfaces. For example:

<method>
    <ejb-name>CabinBean</ejb-name>
    <method-name>*</method-name>
</method>

Although it's tempting to combine the wildcard with other characters, don't. The value get*, for example, is illegal. The asterisk (*) character can only be used by itself.

10.6.3.2. Named method declarations

Named declarations apply to all methods defined in the bean's remote and home interfaces that have the specified name. For example:

<method>
    <ejb-name>CabinBean</ejb-name>
    <method-name>create</method-name>
</method>
<method>
    <ejb-name>CabinBean</ejb-name>
    <method-name>getDeckLevel</method-name>
</method>

These declarations apply to all methods with the given name in both interfaces. They don't distinguish between overloaded methods. For example, if the home interface for the Cabin bean is modified so that it has three overloaded create() methods as shown here, the previous method declaration would apply to all three methods:

public interface CabinHome javax.ejb.EJBHome {
    public Cabin create() 
        throws CreateException, RemoteException;
    public Cabin create(int id) 
        throws CreateException, RemoteException;
    public Cabin create(int id, Ship ship, double [][] matrix)
        throws CreateException, RemoteException;
    ...
}

10.6.3.3. Specific method declarations

Specific method declarations use the method-params element to pinpoint a specific method by listing its parameters. This allows you to differentiate between overloaded methods. The method-params element contains zero or more method-param elements which correspond, in order, to each parameter type (including multidimensional arrays) declared in the method. To specify a method with no arguments, use a method-params element with no method-param elements nested within it.

For an example, let's look again at our Cabin bean, to which we've added some overloaded create() methods in the home interface. Here are three method elements, each of which specifies unambiguously one of the create() methods by listing its parameters:

<method>
    <description> 
         Method: public Cabin create(); 
    </description> 
    <ejb-name>CabinBean</ejb-name>
    <method-name>create</method-name>
    <method-params>
    </method-params>
</method>
<method>
    <description> 
         Method: public Cabin create(int id); 
    </description>
    <ejb-name>CabinBean</ejb-name>
    <method-name>create</method-name>
    <method-params>
           <method-param>int</method-param>
    </method-params>
</method>
<method>
    <description> 
         Method: public Cabin create(int id, Ship ship, double [][] matrix); 
    </description>
    <ejb-name>CabinBean</ejb-name>
    <method-name>create</method-name>
    <method-params>
           <method-param>int</method-param>
           <method-param>com.titan.ship.Ship</method-param>
           <method-param>double [][]</method-param>
    </method-params>
</method>

10.6.3.4. Remote/home differentiation

There's one problem left. The same method name can be used in both the home and remote interfaces. To resolve this ambiguity, you can add the method-intf element to a method declaration as a modifier. Only two values are allowed for a method-intf element: Remote and Home.

In reality, it's unlikely that a good developer would use the same method names in both home and remote interfaces; that would lead to unnecessarily confusing code. Realistically, it's more likely that you'll need the method-intf element in a wildcarded declaration. For example, the following declaration specifies all of the methods in the remote interface of the Cabin bean:

<method>
    <ejb-name>CabinBean</ejb-name>
    <method-name>*</method-name>
    <method-intf>Remote</method-intf>
</method>

All these styles of method declarations can be used in any combination within any element that uses the method element. The method-permission elements are combined to form a union of role-to-method permissions. For example, in the following listing, the first method-permission element declares that the administrator has access to the Cabin bean's home methods (create and find methods). The second method-permission specifies that the everyone role has access to the findByPrimaryKey() method. This means that both roles (everyone and administrator) have access to the findByPrimaryKey() method.

<method-permission>
     <role-name>administrator</role-name>
     <method>
         <ejb-name>CabinBean</ejb-name>
         <method-name>*</method-name>
         <method-intf>Home</method_intf>
     </method>
</method-permission>
<method-permission>
     <role-name>everyone</role-name>
     <method>
         <ejb-name>CabinBean</ejb-name>
         <method-name>findByPrimaryKey</method-name>
     </method>
</method-permission>


Library Navigation Links

Copyright © 2001 O'Reilly & Associates. All rights reserved.