Deployment Descriptors and EJB Roles

   

Bean Provider Responsibilities

Responsibility for creating a bean's deployment descriptor starts with the bean provider. Certain information about a bean is independent of how it's assembled into an application and deployed. As the developer, you know, for example, the names of the home and remote interfaces that are associated with a particular bean and the identities of any other entity beans on which it depends. While still playing the role of bean provider, you're expected to supply the required descriptor elements such as these, plus any of the optional ones that you know at this stage.

Before looking at any particular attributes, the first thing to mention is the format of the deployment descriptor. The fact that a descriptor is stored as an XML file makes it easy to edit by hand. It's also easy for vendors to build deployment tools and IDE wizards that create and edit the entries in a descriptor. If you like IDEs and you use one of the more popular application servers, you'll rarely have to write a descriptor from scratch. On the other hand, if you'd never allow a wizard-laden GUI tool anywhere near your machine, you'll appreciate the fact that the file isn't too complicated relative to what it allows you to do. In either case, the content of the file is more interesting than its format. You still must be aware of the format, though, because XML is easy to read, but it's not very forgiving . Whether you're creating deployment files from the ground up or tweaking ones that have been created for you, you need to know how the file is laid out. With that in mind, the attributes you can define in a descriptor are covered here based on where they must appear within the file.

Overall File Structure

For an XML file to be validated , it must specify the XML version to which it's written and name the DTD that governs it. The first two entries in a deployment descriptor (which are always the same) are a result of this requirement:

 <?xml version="1.0"?>  <!DOCTYPE ejb-jar PUBLIC    '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN'    'http://java.sun.com/dtd/ejb-jar_2_0.dtd'> 

These two lines aren't very interesting except that you can use the URL given for validating the file to download a copy of the DTD from Sun. Looking at the DTD is a quick way to verify that you have elements in the correct order and that you haven't left out a required entry. It also includes a short definition of each element that serves as a good reference. Other than the XML version and the DTD reference, the contents of the descriptor are defined within the ejb-jar tag:

 <ejb-jar>    <description>      This is an optional description of the ejb-jar file    </description>    <display-name>Optional short name used by tools</display-name>    <small-icon>    ...    </small-icon>    <large-icon>    ...    </large-icon>    <enterprise-beans>    ...    </enterprise-beans>    <relationships>    ...    </relationships>    <assembly-descriptor>    ...    </assembly-descriptor>    <ejb-client-jar>    ...    </ejb-client-jar>  </ejb-jar> 

Note

With the increasing proliferation of XML, it's assumed that you're comfortable working with XML files. The concepts needed to work with a deployment descriptor are quite simple. Each element in an XML file is defined by an opening and a closing tag (for example, <ejb-jar> and </ejb-jar> ). Unlike HTML, the name of each tag is case sensitive and closing tags are always required. This is sometimes referred to as "well- formed ." The DTD for the 2.0 version of the ejb-jar.xml file defines the valid tags and their allowed values. The required order of tags within the element that encloses them is also defined by the DTD.


The elements within ejb-jar allow you to both describe the contents of the file and provide detailed information about the beans you're deploying. First, you can include the optional description element with a string that describes the contents of the deployment unit. This can be a brief description of the beans that are referenced by the file for use by an application assembler or deployer. The display-name element that follows (also optional) is for a short name that an assembly or deployment tool can use to identify the file's contents. To support the GUI nature of such tools, it's assumed that they might also have the capability to associate an icon with a deployment file. If your beans are used with one that does, you can include a 16x16 and a 32x32 image file (either JPEG or GIF) in your deployment JAR and identify them using the optional small-icon and large-icon elements. If you supply these icons, the filenames for the images must end in either .gif or .jpg and the path names must be relative to the root directory in the JAR.

The substance of the deployment descriptor starts with the enterprise-beans tag. As a bean provider, you can focus mostly on defining the information found within this tag and, if you're using CMP, the relationships tag that follows it.

The enterprise-beans Element

Every EJB contained in an ejb-jar file must be identified within the enterprise-beans element of the deployment descriptor. This element can contain multiple bean descriptions, but it has to include at least one. The only elements allowed directly within enterprise- beans are entity , session , and message-driven . The file can include as many of these elements as you'd like (one per EJB) and you can include them in any order. Table 15.1 describes the fundamental elements found within these tags. The elements listed are given in order and are required unless otherwise noted.

Table 15.1. The Fundamental entity , session , and message-driven Elements

Element

Description

description

A description of the bean (optional).

display-name

A short name for display by an assembly or deployment tool (optional).

small-icon

The filename for a 16x16 GIF or JPEG image included in the JAR to represent the bean (optional).

large-icon

The filename for a 32x32 icon image (optional).

ejb-name

A logical name for the bean assigned by the bean provider that is independent of its JNDI name assigned at deployment. This name must be unique among the EJB names defined in a single JAR file.

home

The fully qualified name of the home interface (entity and session beans only). This is required only if the bean exposes a remote view of itself.

remote

The fully qualified name of the remote interface (entity and session beans only). This is required only if the bean exposes a remote view of itself.

local-home

The fully qualified name of the local home interface (entity and session beans only). This is required only if the bean exposes a local view of itself.

local

The fully qualified name of the local interface (entity and session beans only). This is required only if the bean exposes a local view of itself.

ejb-class

The fully qualified name of the bean implementation class.

persistence-type

The persistence management type for an entity bean that must be specified as either Bean or Container (entity beans only).

prim-key-class

The fully qualified name of the primary key class. This element is required but it can be specified as java.lang.Object to defer the selection to deployment time. See Chapter 5, "Entity Beans," for a discussion of primary key classes (entity beans only).

reentrant

Specified as True if an entity bean allows loopback calls or False otherwise ”see the discussion that follows (entity beans only).

cmp-version

Specified as 1.x or 2.x to indicate the version of container-managed persistence to use for an entity bean (entity beans only, optional, defaults to 2.x if not defined).

abstract-schema-name

The name for an entity bean using CMP version 2.x used by EJB QL queries that reference the bean (entity beans using CMP 2.x only).

cmp-field

A cmp-field entry is required for each persistent field of a CMP entity bean. Each entry can include an optional description and must include a field-name element that matches a public field of the bean class or one of its superclasses. For CMP 2.x, the field name must begin with a lowercase letter (entity beans only, one element required per persistent field).

primkey-field

The name of the cmp-field that represents the primary key of a CMP entity bean with a single-field key. The type of the field must match the prim-key-class . (Required only for CMP entity beans with single-field primary keys.)

session-type

Identifies a session bean as Stateful or Stateless (session beans only).

transaction-type

Specified as Bean or Container to indicate bean-managed or container-managed transaction demarcation , respectively (session and message-driven beans only).

message-selector

A selector string used to filter the messages a message-driven bean receives. Refer to Chapter 10, "Java Message Service," for a description of the format used for a selector (message-driven beans only, optional).

acknowledge -mode

Specified as Auto-acknowledge or Dups-ok-acknowledge to define the acknowledgement semantics for the onMessage method of a bean using bean-managed transaction demarcation (message-driven beans only, optional).

message-driven-destination

Indicates whether a message-driven bean should be associated with a queue or a topic (message-driven beans only, optional).

Note

For the message-driven-destination element in Table 15.1, it's up to the deployer to make the actual association, but this entry in the descriptor allows the bean provider to indicate which type should be used. If included, this element must contain a destination-type element specified as either javax.jms.Queue or javax.jms.Topic . If the destination is a topic, you also need to include the sub scription-durability element to identify the subscription as either Durable or NonDurable .


For more information on choosing a primary key class, see "Defining the Primary Key Class," p. 127 .

For more information on defining a message-selector , see "Message Selection and Filtering," p. 280 .

Most of the elements described in Table 15.1 are straightforward, but there is one notable exception. This is the issue of reentrant and non-reentrant entity beans. If you declare an entity bean to be reentrant, the container will allow a business method of a single bean instance to be called through its component interface while that instance is in the midst of executing another business method. The intent is to support an entity calling a method on another bean that in turn calls a method on the first bean (all within the same transaction context). This is referred to as a loopback.

By itself, a loopback isn't too complex a scenario. The confusion arises when, instead of this situation, the entity is called concurrently by multiple clients within the same transaction context. Because the transaction context is the same in both cases, the container can't distinguish a concurrent call from a loopback. The problem is that a concurrent call within the same transaction context is illegal. Think of the erroneous results that could occur if, within the same transaction context, two clients were allowed to execute business methods of the same bean instance at the same time. The safest way to prevent this from happening is to avoid the use of loopbacks and declare your entity beans as non-reentrant. When you do this, the container will throw a RemoteException (or EJBException if the bean has a local client) if a loopback or concurrent call within the same transaction context is attempted. If you must use loopbacks, you have to take extra precautions to avoid illegal concurrent calls from client code because the container can't protect you from them.

env-entry

The remaining elements of entity , session , and message-driven are more involved than those given in Table 15.1, so they're covered individually. First, any type of EJB can reference parameters in its environment as a way to make the bean configurable without changing its source code. It's the bean provider's responsibility to declare these parameters and use them in a bean's implementation, but not to specify their values. Environment parameters are declared using the env-entry tag in the deployment descriptor. An EJB can have any number of these entries, which contain an optional description , an env-entry-name , an env- entry-type , and an env-entry-value . The DTD defines the env-entry-value as optional so that the bean provider can defer its assignment to the application assembler or deployer.

The env-entry-name defines the string that the EJB will use to locate the value within the environment.

You can name an entry anything you want as long as it's unique among the entries for a bean. Your bean code must cast an environment entry to a specific type so you have to define that type in the descriptor using the env-entry-type tag. You must specify the type as Boolean , Byte , Character , Double , Float , Integer , Long , Short , or String using the type's fully qualified name (for example, java.lang.Boolean ). The following are examples of valid environment entry declarations by a bean provider:

 <env-entry>    <description>The maximum address line length that should be allowed    </description>    <env-entry-name>maxAddressLineLength</env-entry-name>    <env-entry-type>java.lang.Integer</env-entry-type>  </env-entry>  <env-entry>    <description>Should the system require a 9-digit zip code?</description>    <env-entry-name>require9DigitZip</env-entry-name>    <env-entry-type>java.lang.Boolean</env-entry-type>  </env-entry> 

The value assigned to maxAddressLineLength could be accessed within a bean method using

 InitialContext ctx = new InitialContext();  Integer maxLineLength =    (Integer)ctx.lookup("java:comp/env/maxAddressLineLength"); 

In general, environment entries apply to all instances of a particular bean class, so they're only appropriate for common information that you can use to drive business logic or adapt a bean's behavior to its deployed environment. One slight exception occurs when a bean is deployed multiple times into the same container. Here, the home associated with each deployment assigns values to the environment based on the descriptor entries for that deployment. In this situation, clients can access bean instances with behavior that depends on which JNDI name they use to locate the bean's home interface.

An environment entry is always associated with a single bean class. There's no way for another EJB class to directly access an entry you've declared in a bean's deployment information. Also important to note is that these entries are read-only as far as your bean classes are concerned . An EJB cannot write to its deployment descriptor ( neither can any other part of an application).

ejb-ref and ejb-local-ref

The next descriptor elements are the ejb-ref and ejb-local-ref tags, which may be used by all EJB types. An ejb-ref entry identifies another EJB that a bean depends on and defines a name that your bean code can use to look up a reference to that bean's home interface. The ejb-local-ref entry identifies another EJB that the referencing bean depends on in the same manner, but defines a name for the local home of that referenced bean.

These descriptor elements contain an optional description and mandatory ejb-ref-name and ejb-ref-type elements. The ejb-ref entry contains elements for the home and remote names, and an optional ejb-link . The ejb-local-ref entry contains elements for the local- home , local , and the optional ejb-link .

The ejb-ref-name defines the logical name used by your bean class to do a JNDI lookup of the reference. You can use any string here but you should prefix it with ejb/ to follow recommended conventions. You can reference both session and entity beans, so the ejb-ref- type must be specified as either Session or Entity to indicate which type you're using. The home and remote tags simply contain the fully qualified interface names of the bean being referenced, whereas the local-home and local tags in the ejb-local-ref entry contain the fully qualified interface names of the referenced bean's local interfaces. The ejb-link element is used by the application assembler or deployer to identify the referenced EJB. This entry is declared as optional by the DTD only because it's not up to the bean provider to define it. You'll see how to define this element later. The following shows an example EJB reference entry using an ejb-local-ref tag:

 <ejb-local-ref>    <description>This EJB reference is used to locate an auction's item    </description>    <ejb-ref-name>ejb/Item</ejb-ref-name>    <ejb-ref-type>Entity</ejb-ref-type>    <local-home>com.que.ejb20.item.model.ItemHome</local-home>    <local>com.que.ejb20.item.model.Item</local>  </ejb-local-ref> 

Just like environment entries, an EJB reference is only accessible to the bean whose deployment information defines it. Within that bean, you can obtain the home interface for a referenced EJB using code like the following:

 InitialContext ctx = new InitialContext();  Object homeObj = ctx.lookup("java:/comp/env/ejb/Item");  ItemHome home = (ItemHome)homeObj; 
security-role-ref

The security aspects of the EJB architecture allow you to declaratively restrict who can call the individual methods of a bean. You can also code your session and entity beans to restrict their methods or modify their behavior based on the authorization associated with the caller. You do this by calling the isCallerInRole method of EJBContext and passing a string that represents the name of a security role.

This name doesn't have to match anything in particular ”it just has to mean something within the context of the bean, such as employee or supervisor . The way you associate these names with actual security roles defined for an application's users is by defining security- role-ref entries in the deployment descriptor. This element contains an optional descrip tion , a role-name , and an role-link . The role-name has to match one of the string names used by the bean in a call to isCallerInRole for the entry to be valid. The role-link has to match one of the security-role role names defined later in the assembly-descriptor element. Following a pattern that should become familiar to you, the role-link is optional and should be supplied by the application assembler. The application assembler is also responsible for the security-identity elements that can follow the security-role-ref entries. These are discussed in the "Application Assembler Responsibilities" section. The following is an example security role reference declaration:

 <security-role-ref>    <description>The auction restricts some operations to valid bidders    </description>    <role-name>bidder</role-name>  </security-role-ref> 

This role could be referenced in a bean in the following manner (assume ctx is a field that holds a reference to the EJBContext ):

 if (ctx.isCallerInRole("bidder")) {   // do something only allowed for a bidder  } 
resource-ref

If a bean requires a connection to a resource manager, you obtain that connection through a connection factory, which is an object that implements an interface such as javax.sql.DataSource or javax.jms.QueueConnectionFactory . To access a connection factory from a bean, you must include a resource-ref entry in the bean's descriptor. A resource-ref is supported for any EJB type and contains an optional description , a res- ref-name , a res-type , a res-auth , and an optional res-sharing-scope .

The bean provider is responsible for all parts of a resource-ref entry. Connection factory references are located using JNDI lookups based on the res-ref-name . Similar to placing EJB references under the ejb subcontext, you should place JDBC, JMS, JavaMail, and URL connection factory references under the jdbc , jms , mail , and url subcontexts, respectively. The res-type identifies the interface associated with the resource. This will usually be one of javax.sql.DataSource , javax.jms.QueueConnectionFactory , javax.jms.TopicConnectionFactory , javax.mail.Session , or java.net.URL .

The res-auth must be specified as either Container or Application to define how logging in to the resource is handled. If you specify Container , the container performs the login using information supplied by the deployer (such as the database username and password included in a connection pool declaration). This is the more common approach, but you can also log in programmatically if you specify Application . For example, the following code segment shows what would be required in your code to do this to access a database:

 InitialContext ctx = new InitialContext();  DataSource source =  (DataSource)ctx.lookup("java:comp/env/jdbc/auctionSource");  // call getConnection without the login info to use Container authorization  Connection con = source.getConnection("MyUserName", "MyPassword"); 

The res-sharing-scope entry can be specified as either Shareable or NonShareable . This indicates whether a connection can be shared by multiple beans that access the same resource within the same transaction context. If this entry isn't included, the connections default to being shareable.

The following is an example connection factory reference:

 <resource-ref>    <description>Define a reference to a resource manager connection       factory for the auction database    </description>    <res-ref-name>jdbc/auctionSource</res-ref-name>    <res-type>javax.sql.DataSource</res-type>    <res-auth>Container</res-auth>  </resource-ref> 
resource-env-ref

Similar to EJB and connection factory references, a bean's use of administered objects associated with resources (such as JMS destinations) must also be indicated in the deployment descriptor. This is done using one or more resource-env-ref elements. This element type contains an optional description , a resource-env-ref-name , and a resource-env-ref-type . The resource-env-ref-name defines the name used by the bean in a JNDI lookup and should be prefixed with an appropriate subcontext name, such as jms/ . The resource-env- ref-type identifies the object type expected by the bean and must be a fully qualified class or interface name such as javax.jms.Queue . An example of a resource environment reference follows:

 <resource-env-ref>    <description>Currency conversion updates are obtained through a queue    </description>    <resource-env-ref-name>jms/exchangeUpdate</resource-env-ref-name>    <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>  </resource-env-ref> 

A reference to this queue could be obtained by an EJB using code like the following:

 Context ctx = new InitialContext();  Queue conversionQueue = (Queue)initCtx.lookup(   "java:comp/env/jms/exchangeUpdate"); 
query

The final element that applies to a bean type element is the query tag, which is only valid for entity beans that use EJB 2.x CMP. Each query entry defines a finder or select query and contains an optional description , a query-method , an optional result- type-mapping , and an ejb-ql element. The query-method identifies the finder or select method using a method- name and a method-params entry. The method-name must always correspond to the name of a finder method in the home interface or a select method in the bean implementation class. If you're defining a select method that returns one or more entity references, you can use result-type-mapping to identify the interface type as either Remote or Local . Local is the default if you omit this entry.

The ejb-ql entry defines the query for the method. Refer to Chapter 8, "EJB Query Language," to learn the syntax for defining a query. The ejb-ql element should be left blank if the query isn't implemented using EJB QL. The following is an example of a query entry:

 <query>    <description>A finder method for locating auctions beyond a specified      bid amount    </description>    <query-method>      <method-name>findHighBidAuctions</method-name>      <method-params>        <method-param>java.lang.Double</method-param>      </method-params>    </query-method>    <ejb-ql>SELECT OBJECT(auction) FROM EnglishAuctionBean AS auction,      IN (auction.bids) aBid WHERE aBid.amount &gt; ?1    </ejb-ql>  </query> 

The relationships Element

The relationships element defines associations among CMP 2.x entity beans. This element consists of an optional description , and one or more ejb-relation entries.

An ejb-relation element inside the relationships entry describes a relationship between two entity beans with container-managed persistence. The element contains an optional description , an optional ejb-relation-name , and exactly two ejb-relationship-role elements. Table 15.2 describes the elements of the ejb-relationship-role tag. You must specify one of these entries for each side of a relationship.

Table 15.2. The Content of an ejb-relationship-role Tag

Element

Description

description

A description of the relationship (optional).

ejb-relationship-role-name A name for a role within the relationship. This name must be

unique within the relationship but can be reused by other relationships (optional).

multiplicity

Specified as One or Many to define the multiplicity of this role in the relationship. Some implementations expect lowercase values and require one or many instead.

cascade-delete

Included for a role to indicate that it should be deleted if the entity bean on the other side of the relationship is deleted. You don't specify a value for this element ”you just include the tag if you want it to apply. A cascade delete is only valid if the other ejb-relationship-role is defined with a multiplicity of One (optional).

relationship-role-source

This element identifies the class associated with the role. It contains an optional description and a mandatory ejb-name entry that corresponds to the referenced entity.

cmr-field

Identifies the field used to reference the related object. This element contains an optional description , a cmr-field-name , and a cmr-field-type . The cmr-field-name must begin with a lowercase letter and match the corresponding get and set methods for the relationship.

Note

For the cmr-field in Table 15.2, you only include the cmr-field-type , which must be specified as either java.util.Collection or java.util.Set , if the role on the other side of the relationship has multiplicity Many . Don't include the cmr-field element if the object on this side of the relationship can't navigate to the other side.


The following example illustrates how a one-to-many relationship is defined in the deployment descriptor:

 <relationships>    <ejb-relation>      <ejb-relation-name>EnglishAuction-AuctionBid</ejb-relation-name>      <ejb-relationship-role>        <ejb-relationship-role-name>auction-has-bids        </ejb-relationship-role-name>        <multiplicity>one</multiplicity>        <relationship-role-source>          <ejb-name>EnglishAuction</ejb-name>        </relationship-role-source>        <cmr-field>          <cmr-field-name>bids</cmr-field-name>          <cmr-field-type>java.util.Collection</cmr-field-type>        </cmr-field>      </ejb-relationship-role>      <ejb-relationship-role>        <ejb-relationship-role-name>bid-belongs-to-auction        </ejb-relationship-role-name>        <multiplicity>many</multiplicity>        <cascade-delete/>        <relationship-role-source>          <ejb-name>AuctionBid</ejb-name>        </relationship-role-source>        <cmr-field>          <cmr-field-name>auction</cmr-field-name>        </cmr-field>      </ejb-relationship-role>    </ejb-relation>  </relationships> 

Note that the multiplicity entry relates to the role being defined and not to the object on the other side. Here this means that the entry for the auction role has multiplicity one and the entry for the bid role has multiplicity many .

The assembly-descriptor and ejb-client-jar Elements

The final high-level entries within the deployment descriptor are the assembly-descriptor and ejb-client-jar elements. The bean provider could supply some of the contents of the assembly-descriptor element, but, as its name implies, it's intended for the application assembler. The last element of ejb-jar is the ejb-client-jar tag. This is a simple (and optional) element that identifies a JAR file containing the classes needed by a client to access the beans defined in the deployment file. The EJB specification doesn't define a particular use for this, but a vendor could use it to simplify the deployment of any helper classes your EJBs rely on or a client application that uses your EJBs.



Special Edition Using Enterprise JavaBeans 2.0
Special Edition Using Enterprise JavaBeans 2.0
ISBN: 0789725673
EAN: 2147483647
Year: 2000
Pages: 223

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net