Describing Bean Assembly

At this point, we have said just about all that can be said about the bean itself. We 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>.

The <assembly-descriptor> element is optional, though it is difficult to imagine a bean being deployed successfully without one. 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 transaction attributes of the bean’s methods; it describes the logical security roles that are used in the method permissions; and it specifies the 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 transaction 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 the next section.

<security-role> (zero or more)

This element defines the security roles that are used to access the 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 the “Specifying Security Roles and Method Permissions” section.

<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> element, one or more <role-name> elements, and one or more <method> elements. It is discussed in more 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 such as method overloading. The <method> element is used within these tags to identify methods; it is described at length in the “Identifying Specific Methods” section.

Specifying a Bean’s Transaction 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 one or more 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 transaction attributes we discussed in Chapter 14. In addition to <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. A lot more complexity is involved in handling overloading and other special cases, but we’ll discuss the rest later.

To see how the <container-transaction> element is typically used, let’s look again at the Cabin EJB. Assume that we want to give the transaction attribute Mandatory to the create( ) method; all other methods use the Required attribute:

<container-transaction>
    <method>
        <ejb-name>CabinEJB</ejb-name>
        <method-name>*</method-name>
    </method>
    <trans-attribute>Required</trans-attribute>
</container-transaction>
<container-transaction>
    <method>
        <ejb-name>CabinEJB</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 EJB’s methods. We set the transaction attribute for these methods to Required. Then, we have a second <container-transaction> element that specifies a single method of the Cabin EJB: create( ). We set the transaction attribute for this method to Mandatory. This setting overrides the wildcard setting; in <container-transaction> elements, specific method declarations always override more general declarations.

For entity beans, the following methods must be assigned transaction attributes:

  • All business methods defined in the remote interface (and all superinterfaces)

  • Create methods defined in the home interface

  • Find methods defined in the home interface

  • Home methods defined in the home interface

  • Remove methods defined in the EJBHome and EJBObject interfaces

And for session beans, the following methods must be assigned transactional attributes:

  • All business methods defined in the remote interface (and all superinterfaces)

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

The ejbSelect( ) methods do not have their own transaction attributes. ejbSelect( ) methods always propagate the transaction of the methods that call them.

Specifying Security Roles and Method Permissions

Two elements define logical security roles and specify which roles can call particular bean methods. The <security-role> 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 is important to realize that the security role names 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 EJBs.
    </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 EJBs. This role may also be a member 
        of 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 in everyone that gives it fewer (or greater) privileges than an administrator. It is up to the deployer to map one or more roles from the target environment to the logical roles in the deployment descriptor. For example, the deployer may find that the target environment has two roles, DBA (database administrator) and CSR (customer service representative), which map to the administrator and everyone roles defined in the <security-role> element.

Assigning roles to methods

Security roles would not 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 roles to methods in the remote and home interfaces of the bean. A <method-permission> is a flexible declaration that allows a many-to-many relationship between methods and roles. It 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 EJB:

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

In this example, the administrator role has access to all methods in the Cabin EJB. The everyone role has access only to the getDeckLevel( ) method—it cannot access any of the other methods of the Cabin EJB. 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. Once again, we still do not know what administrator and everyone mean. The person deploying the bean, who must map these logical security roles to real security roles defined in the target environment, defines them.

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.

Unchecked methods

A set of methods can be designated as unchecked , which means that security permissions are not checked before the method is invoked. Any client can invoke an unchecked method, no matter what role it is using.

To designate a method or methods as unchecked, use the <method-permission> element and replace the <role-name> element with an empty <unchecked> element:

<method-permission>
    <unchecked/>
    <method>
        <ejb-name>CabinEJB</ejb-name>
        <method-name>*</method-name>
    </method>
    <method>
        <ejb-name>CustomerEJB</ejb-name>
        <method-name>findByPrimaryKey</method-name>
    </method>
</method-permission>
<method-permission>
    <role-name>administrator</role-name>
    <method>
        <ejb-name>CabinEJB</ejb-name>
        <method-name>*</method-name>
    </method>
</method-permission>

This declaration tells us that all the methods of the Cabin EJB, as well as the Customer EJB’s findByPrimaryKey( ) method, are unchecked. Although the second <method-permission> element gives the administrator permission to access all the Cabin EJB’s methods, this declaration is overridden by the unchecked method permission. Unchecked method permissions always override all other method permissions.

The runAs security identity

In addition to specifying the Principals that have access to an enterprise bean’s methods, the deployer can also specify the runAs Principal for the entire enterprise bean. The runAs security identity was originally specified in EJB 1.0, but was abandoned in EJB 1.1. It has been reintroduced in EJB 2.0 and modified so that it is easier for vendors to implement.

While the <method-permission> elements specify which Principals have access to the bean’s methods, the <security-identity> element specifies the Principal under which the method will run. In other words, the runAs Principal is used as the enterprise bean’s identity when it tries to invoke methods on other beans—and this identity isn’t necessarily the same as the identity that’s currently accessing the bean. For example, the following deployment descriptor elements declare that the create( ) method can be accessed only by JimSmith, but that the Cabin EJB always runs under the Administrator security identity:

<enterprise-beans>
...
    <entity>
        <ejb-name>EmployeeService</ejb-name>
        ...
        <security-identity>
            <run-as>
                <role-name>Administrator</role-name>
            </run-as>
        </security-identity>
        ...
    </entity>
...
</enterprise-beans>
<assembly-descriptor>
    <security-role>
        <role-name>Administrator</role-name>
    </security-role>
    <security-role>
        <role-name>JimSmith</role-name>
    </security-role>
    ...
    <method-permission>
        <role-name>JimSmith</role-name>
        <method>
            <ejb-name>CabinEJB</ejb-name>
            <method-name>create</method-name>
        </method>
    </method-permission>
    ...
</assembly-descriptor>

To specify that an enterprise bean will execute under the caller’s identity, the <security-identity> role contains a single empty element, <use-caller-identity/> . The following declarations specify that the Cabin EJB always executes under the caller’s identity, so if Jim Smith invokes the create( ) method, the bean will run under the JimSmith security identity:

<enterprise-beans>
...
    <entity>
        <ejb-name>EmployeeService</ejb-name>
        ...
        <security-identity>
            <use-caller-identity/>
        </security-identity>
        ...
    </entity>
...
</enterprise-beans>

The use of <security-identity> applies to entity and stateless session beans. Message-driven beans have only a runAs identity; they never execute under the caller identity, because there is no “caller.” The messages that a message-driven bean processes are not considered calls, and the clients that send them are not associated with the messages. With no caller identity to propagate, message-driven beans must always have a runAs security identity specified.

Exclude list

The last element of the <assembly-descriptor> is the optional <exclude-list> element. The <exclude-list> element contains a <description> and a set of <method> elements. Every method listed in the <exclude-list> should be considered uncallable, which means that the deployer needs to set up security permissions for those methods so that all calls, from any client, are rejected. Remote clients should receive a java.rmi.remoteException and local clients should receive a javax.ejb.AccessLocalException :

<ejb-jar>
    <enterprise-beans>
        <entity>
            <ejb-name>CabinEJB</ejb-name>
        </entity>
    </enterprise-beans>
    <assembly-descriptor>
        <exclude-list>
            <method>
                <ejb-name>CabinEJB</ejb-name>
                <method-name>getDeckLevel</method-name>
            </method>
            <method>
                ...
            </method>
        </exclude-list>
    </assembly-descriptor>
</ejb-jar>

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-name> element that specifies the bean’s name and a <method-name> element that specifies the method. It may also include a <description> element, <method-params> elements that specify which method parameters will be used to resolve overloaded methods, and a <method-intf> element that specifies whether the method belongs to the bean’s home, remote, local home, or local interface. This last element takes care of the possibility that the same method name might be used in more than one interface.

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>CabinEJB</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 be used only by itself.

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>CabinEJB</ejb-name>
    <method-name>create</method-name>
</method>
<method>
    <ejb-name>CabinEJB</ejb-name>
    <method-name>getDeckLevel</method-name>
</method>

These declarations apply to all methods with the given name in both interfaces. They do not distinguish between overloaded methods. For example, if the home interface for the Cabin EJB 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;
    ...
}

Specific method declarations

Specific method declarations use the <method-params> element to pinpoint a specific method by listing its parameters, allowing you to differentiate between overloaded methods. The <method-params> element contains zero or more <method-param> elements that 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 example, let’s look again at our Cabin EJB, to which we have added some overloaded create( ) methods. Here are three <method> elements, each of which unambiguously specifies one of the create( ) methods by listing its parameters:

<method>
    <description>Method: public Cabin create( ); </description> 
    <ejb-name>CabinEJB</ejb-name>
    <method-name>create</method-name>
    <method-params></method-params>    
</method>
<method>
    <description>Method: public Cabin create(int id);</description>
    <ejb-name>CabinEJB</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>CabinEJB</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>

Remote/home/local differentiation

There’s one problem left. The same method name can be used in the home interface, the local home interface, the remote interface, and the local interface. To resolve this ambiguity, add the <method-intf> element to a method declaration as a modifier. Four values are allowed for a <method-intf> element: Remote, Home, LocalHome, Local, and ServiceEndpoint.

In practice, it is unlikely that a good developer would use the same method names in both home and remote interfaces: it would lead to unnecessarily confusing code. However, you would expect to see the same names in the local, remote, and possibly endpoint interfaces, or the home and local home interfaces. It is also likely that you will need the <method-intf> element in a wildcarded declaration. For example, the following declaration specifies all the methods in the remote interface of the Cabin EJB:

<method>
    <ejb-name>CabinEJB</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 EJB’s home methods (create and find methods). The second <method-permission> specifies that everyone has access to the findByPrimaryKey( ) method. This means both roles (everyone and administrator) have access to the findByPrimaryKey( ) method:

<method-permission>
    <role-name>administrator</role-name>
    <method>
        <ejb-name>CabinEJB</ejb-name>
        <method-name>*</method-name>
        <method-intf>Home</method_intf>
    </method>
</method-permission>
<method-permission>
    <role-name>everyone</role-name>
    <method>
        <ejb-name>CabinEJB</ejb-name>
        <method-name>findByPrimaryKey</method-name>
    </method>
</method-permission>
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.26.22