Configuring EJB Deployments

There are three types of EJBs that can be deployed: entity beans, session beans, and message-driven beans. In addition, one or more AC4J deployments, in which each one makes an EJB available to other AC4J objects, can be included.

In this section you'll look at the following:

  • The headers for each type of EJB

  • The common elements that can appear in any of the EJB deployments

  • Container-managed persistence elements for CMP entity beans

  • Java Expresso Machine (JEM) elements used to deploy EJBs as AC4J objects

Session Bean Deployment Header

For every session bean declared in ejb-jar.xml , you can specify a <session-deployment> element in orion-ejb-jar .xml with a JNDI location, environment entries, references to other EJBs, resource references, and other optional performance settings.

As an example, consider the following session bean definition in ejb-jar.xml :

 <session>     <description>Manages customers</description>  <ejb-name>CustomerManager</ejb-name>  <home>com.apress.ejb.CustomerManagerRemoteHome</home>     <remote>com.apress.ejb.CustomerManagerRemote</remote>     <local-home>com.apress.ejb.CustomerManagerHome</local-home>     <local>com.apress. ejb.CustomerManager</local>     <ejb-class>com.apress.ejb.CustomerManagerBean</ejb-class>     <session-type>Stateless</session-type>     <transaction-type>Container</transaction-type> </session> 

You can map CustomerManager to an actual JNDI location and tweak a few performance settings in orion-ejb-jar.xml like this:

 <session-deployment name="  CustomerManager  "  location=  "  store/ejb/CustomerManager  "     cache-timeout=120     min-instances=50     max-instances=200/> ... </session-deployment> 

Environment entries, resource references, EJB references, and other subelements of session-deployment are common across EJB types and are described later in this chapter.

The <session-deployment> element allows the following attributes listed in Table 11-2.

Table 11-2: session-deployment Elements

Parameter

Description

Default Value

session-deployment: pool-cache-timeout

The maximum number of seconds to cache bean instances. When this number is reached, all beans of this type will be flushed from the pool. Specifying "never" or a nonpositive integer will disable timeouts so that instances will never be removed from the pool.

60

session-deployment: call-timeout

The maximum number of milliseconds to wait for a resource (other than a database connection) before throwing a RemoteException . If set to 0, timeouts are disabled and it will wait forever.

session-deployment: copy- by-value

Specifies whether all parameters should be cloned and serialized before being passed in to this bean's methods . If false, objects will be passed by reference, which is faster but may cause problems if the parameter is an object and you modify its state.

true

session-deployment: location

The JNDI location in which to store this bean's Home .

 

session-deployment: max-instances

The maximum number of instances to keep cached in the pool.

100

session-deployment: min-instances

The minimum number of instances to keep cached in the pool.

session-deployment: max-tx-retries

The maximum number of times to retry transactions that are rolled back because of system failures. When a transaction involves multiple beans, the container will use the value specified for the first bean involved in the transaction.

3

session-deployment:name

The name of the bean as specified in ejb-jar.xml .

 

session-deployment: persistence-filename

Path to the file where session state is stored across server restarts. (Note: the survival of session state across server restarts is a nonportable feature.)

 

session-deployment: timeout

Maximum number of seconds of inactivity before removing a stateful session bean. If zero or negative, stateful session beans are never removed by the container and must be explicitly removed by the application.

1800

session-deployment: wrapper

Used by OC4J to store the name of the generated remote wrapper class. This value should not be edited.

 

session-deployment: local-wrapper

Used by OC4J to store the name of the generated local wrapper class. This value should not be edited.

 

Entity Bean Deployment Header

For every entity bean declared in the ejb-jar.xml , you can specify an <entity-deployment> element in orion-ejb-jar.xml . This is particularly relevant to entity beans that use CMP, since you'll need to map fields and finders to the corresponding database values, as shown in Table 11-3.

Table 11-3: entity-deployment Elements

Parameter

Description

Default Value

entity-deployment: call-timeout

The maximum number of milliseconds to wait for a resource (other than a database connection) before throwing a RemoteException , or to wait for a SQL query to finish before throwing an SQLException . If set to 0, timeouts are disabled and it will wait forever.

90000 ms

entity-deployment: clustering-schema

Not necessary in this release

 

entity-deployment: copy-by-value

Specifies whether all parameters should be cloned or serialized before being passed in to this bean's methods. If false, objects will be passed by reference, which is faster but may cause problems if the parameter is an object and you modify its state.

true

entity-deployment: exclusive-write-access

If true, the container assumes that it's the only process with write access to the database. This can provide performance boosts, but can ensure that data integrity should never be used when other processes might update the database.

false

entity-deployment: do-select- before-insert

If true, the container will execute a select before every insert to determine if a record already exists with the same key. If false, it will just attempt the insert, possibly causing a SQLException .

true

entity-deployment: instance-cache-timeout

The maximum number of seconds that instances are assigned to a particular identity (that is, one primary key) before being returned to the unassigned pool. Specifying a value of "never" means that instances will keep their identity until they are garbage collected.

60

entity-deployment: location

The JNDI location in which to store this bean's Home .

 

entity-deployment: isolation

Sets the database isolation level to serializable, srepeatable_read , committed, uncommitted , or none (only serializable and committed should be used for Oracle databases).

committed

entity-deployment: locking-mode

Sets the concurrency mode, which controls how to resolve resource contention between components . Possible values are as follows :

  • PESSIMISTIC . Only one user can use an entity bean at a single time. Others will block until it's available.

  • OPTIMISTIC . Multiple users can use the same entity bean, which means that data consistency is managed solely by database isolation modes.

  • READ-ONLY . The entity bean cannot be updated, so multiple users can use it without blocking.

OPTIMISTIC

entity-deployment: max-instances

The maximum number of instances to keep cached in the pool.

100

entity-deployment: min-instances

The minimum number of instances to keep cached in the pool.

entity-deployment: max-instances-per-pk

The maximum number of instances to keep cached for a single primary key.

 

entity-deployment: min-instances-per-pk

The minimum number of instances to keep cached for a single primary key.

 

entity-deployment: max-tx-retries

The maximum number of times to retry transactions that are rolled back because of system failures. When a transaction involves multiple beans, the container will use the value specified for the first bean involved in the transaction.

3

entity-deployment: disable-wrapper-cache

If true, bean instances aren't cached, but rather created on demand.

false

entity-deployment:name

The name of the bean as specified in ejb-jar.xml .

 

entity-deployment:pool-cache-timeout

The maximum number of seconds to keep an unassigned entity instance before removing it from the pool. Specifying a value of "never" will disable the timeout.

60

entity-deployment:validity-timeout

For read-only beans, specifies how often to reload data. Useful for cases where data very rarely changes, but needs to be occasionally refreshed. Specifying a value of "never" will disable the timeout so that data may never be reloaded.

 

entity-deployment:force-update

If true, the container will call ejbStore() (and write to the database in the case of CMP) after every invocation, even if no data changes are detected . If false, it will track changes and only write when necessary.

false

entity-deployment:wrapper

Used by OC4J to store the name of the generated remote wrapper class. This value should not be edited.

 

entity-deployment: local-wrapper

Used by OC4J to store the name of the generated local wrapper class. This value should not be edited.

 

entity-deployment: delay-updates-until-commit

If true, updates aren't written to the database until the current transaction is committed. If false, every incremental update is passed through to the database.

true

CMP Entity Bean Configuration

All entity beans share the same header information. However, CMP entity beans use a number of additional attributes in the header, and a number of additional child elements as well. The additional header elements are list in Table 11-4.

Table 11-4: entity-deployment Elements

Parameter

Description

Default Value

entity-deployment: data-source

The JNDI name of a data source to use to access the database for this entity. The name specified here should match the ejb-location configured for the data source in the data-sources.xml file (see Chapter 5).

The value of orion-application:default-data-source in orion-application.xml for this application, or if that isn't specified, the same value in config/application.xml

entity-deployment: update-changed-fields-only

If true, when an EJB is saved, only the modified fields will be updated. If false, all the EJB fields will be updated no matter what was changed.

true

entity-deployment: table

The database table this entity should be saved to.

Generated by the server based on the EJB name, JAR name, and so on

Within the main entity-deployment element, you must specify child elements for the following:

  • Mapping CMP fields to database columns (note that Primary Key fields must be listed separately from the rest of the CMP fields)

  • Specifying queries for finders, for EJB 1.1, or when EJB-QL isn't sufficient to specify the query for EJB 2.0 finders

  • Resolving container-managed relationships to database tables and columns

Caution 

Many of the elements and attributes described in this section can be used for different things (for example, depending on whether they're mapping a CMP field or a CMR field).

Mapping Primary Key Fields

The primary key fields must be listed separately from the rest of the CMP fields, but the format is essentially the same. There's one primkey-mapping element that holds a single cmp-field-mapping element, which can hold one or more field mappings, using any of the syntaxes described in the following sections.

For example, for an Order EJB with a single primary key field called OrderId in the EJB mapping to a column named OrderId in the database, the mapping would look like this:

 <primkey-mapping>     <cmp-field-mapping name="orderId" persistence-name="OrderId" /> </primkey-mapping> 

For an OrderLine EJB with a multicolumn primary key, you cannot list all the columns directly under the primkey-mapping element, since it only takes a single child. Instead, you'll use one of the following options to embed multiple CMP field definitions. For example, if the OrderLine primary key consists of OrderId and LineNumber properties in the EJB and OrderId and LineNumber columns in the database, the mapping would look like this:

 <primkey-mapping>     <cmp-field-mapping>         <properties>             <cmp-field-mapping name="orderId" persistence-name="OrderId" />              <cmp-field-mapping name="lineNumber" persistence-name="LineNumber" />         </properties>     </cmp-field-mapping> </primkey-mapping> 

We recommend that you don't use composite primary keys. A primary key should have no relation to any identifiers used in real world. Using a national insurance number, for example, as a primary key isn't the best idea because it mayunder the most obscure circumstanceschange. The same principle can be applied to orders and order lines. You may have to change the line number for some reason and doing so will impact your primary key. Instead, use a synthetic primary key, such as OrderLineId , which doesn't relate in any way to order and line number.

Mapping Simple CMP Fields

All CMP fields are mapped using the cmp-field-mapping element. Simple fields just specify a CMP field name (in the name attribute) and a database column name (in the persistence-name attribute) directly in the cmp-field-mapping element. For most cases, no child elements are required. The following attributes listed in Table 11-5 are available on the cmp-field-mapping element.

Table 11-5: cmp-field-mapping Elements

Parameter

Description

Default Value

cmp-field-mapping

Holds mapping information for one or more CMP or CMR fields. Simple CMP fields just use attributes, while CMR and more complex arrangements use child elements.

 

cmp-field-mapping: ejb-reference-home

Generally not used. When mapping to other EJBs, you can use the entity-ref:home attribute described in the following CMR sections.

 

cmp-field-mapping: name

Identifies the CMP field or CMR field in question. For CMP fields, this must match the value in the field-name element of the ejb-jar.xml file. For CMR fields, this must match the value in the cmr-field-name element of the ejb-jar.xml file.

 

cmp-field-mapping: persistence-name

The name of the database column this CMP field should map to.

Same as the CMP field name

cmp-field-mapping: persistence-type

The database-specific data type of the column this field maps to. This is only necessary if the application is configured to create tables for CMP entity beans (see orion-application:autocreate-tables ).

Configured in the XML file for the current DBMS in config/database-schemas/

For example, if the User EJB needs to map the FirstName and LastName CMP fields to FirstName and LastName database columns, you could use two simple mappings like this:

 <cmp-field-mapping name="firstName" persistence-name="FirstName" /> <cmp-field-mapping name="lastName" persistence-name="LastName" /> 

However, there are two cases in which the cmp-field-mapping element must contain children. One case is for multicolumn primary keysas discussed previously, the primkey-mapping element only allows one cmp-field-mapping child, so to map to multiple primary key fields that cmp-field-mapping child must have a fields child or a properties child that can enumerate the primary key fields.

The other case in which the cmp-field-mapping element must contain children is when the CMP or CMR field itself is a complex type: an EJB, an array or collection, and so forth. The mappings for these situations are described in the following sections.

Explicitly Mapping EJB 1.1-style CMP Fields

In cases in which you want to explicitly indicate that a group of CMP fields should be represented by EJB 1.1-style public fields on the bean implementation class, you can use the fields child of the cmp-field-mapping element.

For example, if the User EJB needs to map the FirstName and LastName CMP fields to FirstName and LastName database columns, and you wanted to indicate that those CMP fields are represented by Java fields (not EJB 2.0-style properties), you could a fields element like this:

 <cmp-field-mapping>     <fields>         <cmp-field-mapping name="firstName" persistence-name="FirstName" />          <cmp-field-mapping name="lastName" persistence-name="LastName" />     </fields> </cmp-field-mapping> 
Explicitly Mapping EJB 2.0-style CMP Properties

In cases in which you want to explicitly indicate that a group of CMP fields should be represented by EJB 2.0-style abstract properties on the bean implementation class, you can use the properties child of the cmp-field-mapping element.

For example, if the User EJB needs to map the FirstName and LastName CMP fields to FirstName and LastName database columns, and you wanted to indicate that those CMP fields are represented by Java properties (not EJB 1.1style fields), you could define the properties element like this:

 <cmp-field-mapping>     <properties>         <cmp-field-mapping name="firstName" persistence-name="FirstName" />         <cmp-field-mapping name="lastName" persistence-name="LastName" />     </properties> </cmp-field-mapping> 
Mapping Complex Objects as CMP Fields

In OC4J, CMP fields aren't restricted to simple data types. For example, the User EJB might include a CMP field whose type is FullName , whereas the FullName object has fields for the first name and the last name as well as a helper method to access the full name as one String . This one CMP field would still map to two separate columns in the databaseone for the first name, and one for the last name. You can use the fields or properties elements described earlier to provide mappings for either fields or properties of the complex object. The elements are listed in Table 11-6.

Table 11-6: cmp-field-mapping Elements

Parameter

Description

properties

Holds one or more cmp-field-mapping entries that represent Java properties on the complex data type.

fields

Holds one or more cmp-field-mapping entries that represent Java fields on the complex data type.

For example, if the FullName looked like this:

 public class FullName implements Serializable {     public String firstName;     public String lastName;     } 

then you could declare a CMP field (in this example, named fullName ) of type FullName , and use a mapping like this:

 <cmp-field-mapping name="fullName">     <fields>         <cmp-field-mapping name="firstName" persistence-name="FirstName" />         <cmp-field-mapping name="lastName" persistence-name="LastName" />     </fields> </cmp-field-mapping> 

If the FullName used properties instead, like this:

 public class FullName implements Serializable {     public String getFirstName() { }     public String getLastName() { }     public void setLastName(String) { }     public void setFirstName(String) { } 

then you could use a very similar mapping with the properties element , as follows:

 <cmp-field-mapping name="fullName">     <properties>         <cmp-field-mapping name="firstName" persistence-name="FirstName" />         <cmp-field-mapping name="lastName" persistence-name="LastName" />     </properties> </cmp-field-mapping> 
Mapping CMP Fields to Custom Persistence Managers

Though it's not commonly used, you can actually map individual CMP fields to a third-party persistence manager, using the field-persistence-manager element. The elements are shown in Table 11-7.

Table 11-7: Persistence Manager Elements in field-persistence-manager

Parameter

Description

field-persistence-manager

Specifies an alternate persistence manager to use for the specified field.

field-persistence-manager:class

The class name of the persistence manager.

property

A property used to configure the persistence manager.

property:name

The name of the property.

property:value

The value for the properties.

Note 

For a description of the pluggable persistence architecture, see http://otn.oracle.com/tech/java/oc4j/1003/how_to/how-to-ejb-switchPM.html .

Specifying Queries for Finders and Selectors

In EJB 1.1, you must specify the query for each finder in the orion-ejb-jar.xml deployment descriptor. In EJB 2.0, you only need to specify a query for a finder or selector here if you can't construct the correct query in EJB-QL, or you want to override the EJB-QL definition. However, the format is the same in either case.

The query syntax uses $fieldName to refer to CMP fields, and $1 to refer to argument one, $2 to refer to the second argument, and so on. Beyond that, the query uses simple SQL syntax, starting with the WHERE clause if the partial attribute is true (the default), or including the entire query if the partial attribute is false and the query is complex (for example, including a join).

The elements used to specify a query for a finder are listed in Table 11-8.

Table 11-8: finder-method Elements

Parameter

Description

Default Value

finder-method

The parent element for providing finder queries.

 

finder-method:partial

If true, the query begins with the WHERE clause (the word WHERE should not be included). If false, the entire query must be provided, making sure to include all necessary fields in the SELECT clause.

true

finder-method:query

The query to use for this finder.

 

method

Indicates which finder method the query is for.

 

ejb-name

The name of the EJB that the method is in. The body of this element holds its value.

 

method-intf

The interface for the finder method. The body of this element must be Home for finders, and Remote for selectors.

 

method-name

The body of this element is the name of the method in question.

 

method-params

A list of parameters to distinguish between overloaded methods. A method with no parameters should include a method-params element with no children. Otherwise, this element has one method-param child for each parameter of the method (in order).

 

method-param

The body of this element is the fully qualified Java name of a single method parameter type.

 

If the User EJB has an Integer for a primary key, but still needs to look users up by their username, it might include a finder definition like this:

 <finder-method partial="true" query="$username = ">     <method>         <ejb-name>User</ejb-name>         <ejb-intf>Home</ejb-intf>         <method-name>findByUsername</method-name>         <method-params>             <method-param>java.lang.String</method-param>         </method-params>     </method> </finder-method> 

If you also wanted a finder to find people whose boss has a specified first name, you might use a more complex query, as follows:

 <finder-method partial="false"   query="select u.* from users u, users boss where boss.id=u.boss_id and boss.firstName=">     <method>         <ejb-name>User</ejb-name>         <ejb-intf>Home</ejb-intf>         <method-name>findByBossFirstName</method-name>         <method-params>             <method-param>java.lang.String</method-param>         </method-params>     </method> </finder-method> 
Mapping One-to-One Container-Managed Relationships

In a one-to-one relationship, each bean maps to a single bean of the other type. This is usually represented by a foreign key on one table, but you need to take special care with the database design with OC4J.

For example, if a User has an Address , you might naturally include the UserId as a column on the Addresses table. This is good enough for OC4J to create a one-way relationship, but unfortunately in this case, it's probably the wrong wayan Address can find its User , but a User can't find its Address . In order to map the relationship the other way, the foreign key needs to go on the User table, and if you wanted it to be a bidirectional relationship (in which both beans can see the other), you need to include foreign keys on both tables!

Further, in OC4J, CMR fields can't be set before a bean is created, which means that the initial rows will be inserted before the foreign keys are populated , and thus the foreign key columns must be nullable. However, you can get around this requirement if you declare the foreign key column as INITIALLY DEFERRED DEFERRABLE and set the CMR field in the same transaction where you create the bean. Deferred foreign key modifiers instruct the database not to perform data integrity checks to see whether the referenced row exists during the current transaction, but only upon commit. This will allow you to use "proper" foreign keys with NOT NULL constraints.

Finally, the foreign key fields should not be part of the primary key of either bean. So, for example, you couldn't make the UserId act as the primary key for the Address table, even though users are unique and there's exactly one address per user.

So here's a recap of the database requirements:

  • Each bean that has a CMR field that accesses the referenced bean must declare a foreign key in its table.

  • It's best if each foreign key has only one column.

  • The foreign key columns must be declared nullable, or INITIALLY DEFERRED DEFERRABLE .

  • The foreign key columns should not overlap with the primary key columns of the same bean.

The XML tags used to map a one-to-one relationship are listed in Table 11-9.

Table 11-9: cmp-field Elements

Parameter

Description

cmp-field-mapping

This element encloses the CMR field definition.

cmp-field-mapping:name

The name of the CMR field, which must match the cmr-field-name tag in the ejb-jar.xml file.

Entity-ref

Indicates that this CMR field maps to a single entity.

Entity-ref:home

Holds the JNDI name where the server can find the entity that this CMR field maps to.

cmp-field-mapping

This element appears again to map the CMR field to a specific foreign key column.

cmp-field-mapping:name

The CMR field name, again.

cmp-field-mapping:persistence-name

The name of the foreign key column in the table for this entity bean.

For example, you'll use the User EJB and the Address EJB. You'll assume a bidirectional one-to-one relationship; the Users table has an Address column, and the Addresses table has a User column. Their relationship might look like this in ejb-jar.xml :

 <ejb-relation>     <ejb-relation-name>UserAddress</ejb-relation-name>     <ejb-relationship-role>         <ejb-relationship-role-name>User</ejb-relationship-role-name>         <multiplicity>One</multiplicity>         <cascade-delete/>         <relationship-role-source>             <ejb-name>User</ejb-name>         </relationship-role-source>         <cmr-field>             <cmr-field-name>address</cmr-field-name>         </cmr-field>     </ejb-relationship-role>     <ejb-relationship-role>         <ejb-relationship-role-name>Address</ejb-relationship-role-name>         <multiplicity>One</multiplicity>         <relationship-role-source>             <ejb-name>Address</ejb-name>         </relationship-role-source>         <cmr-field>             <cmr-field-name>user</cmr-field-name>         </cmr-field>     </ejb-relationship-role> </ejb-relation> 

Notice that each bean has a CMR field to access the other. To map this relationship to database columns, you must add entries to orion-ejb-jar.xml for each of the two entity beans, as shown here:

 <entity-deployment name="  User  ">      <cmp-field-mapping name="address">          <entity-ref home="Address">             <cmp-field-mapping name="  address  " persistence-name="  Address  " />         </entity-ref>     </cmp-field-mapping> </entity-deployment> <entity-deployment name="  Address  ">     <cmp-field-mapping name="user">         <entity-ref home="User">             <cmp-field-mapping name="  user  " persistence-name="  User  " />         </entity-ref>     </cmp-field-mapping> </entity-deployment> 

Note that the User bean maps the "address" CMR field to the Address foreign-key column, and the Address bean maps the user CMR field to the User foreign-key column.

We've used many different foreign key naming schemas, but the one we're most comfortable using is this parent table: Parents with primary key ParentId and a child table Children with primary key ChildId . We named the foreign key in the Children table that references a row in Parents table Parent . This describes the entity the foreign key is referencing and makes all updates much easier because you cannot use aliases in UPDATE statements.

Mapping One-to-Many Container-Managed Relationships

In a one-to-many relationship, the parent bean maps to a group of child beans, while each child bean maps to only one parent bean. For example, the User bean maps to many PhoneNumbers , but each PhoneNumber is only used by one User . Again, this is typically modelled with a single foreign key in the child table. In this example, the PhoneNumber table would typically have a User field that references Users(UserId) .

Additionally, the same foreign-key considerations apply to one-to-many relationships, as follows:

  • It's best if each foreign key has only one column.

  • The foreign key columns must be declared nullable, or INITIALLY DEFERRED DEFERRABLE .

  • The foreign key columns should not overlap with the primary key columns of the same bean.

To map a one-to-many relationship to database tables, you need to use different syntax for each bean in the relationship. The child bean uses the same syntax as for one-to-many relationships. The elements are listed in Table 11-10.

Table 11-10: cmp-field-mapping Elements and One-to-Many Relationship

Parameter

Description

cmp-field-mapping

This element encloses the CMR field definition.

cmp-field-mapping:name

The name of the CMR field, which must match the cmr-field-name tag in the ejb-jar.xml file.

entity-ref

Indicates that this CMR field maps to a single entity.

entity-ref:home

Holds the JNDI name where the server can find the entity that this CMR field maps to.

cmp-field-mapping

This element appears again to map the CMR field to a specific foreign key column.

cmp-field-mapping:name

The CMR field name, again.

cmp-field-mapping:persistence-name

The name of the foreign key column in the table for this entity bean.

However, the parent bean definition uses new syntax, as shown in Table 11-11.

Table 11-11: cmp-field-mapping Elements for the Parent Bean

Parameter

Description

Default Value

cmp-field-mapping

This element encloses the CMR field definition.

 

cmp-field-mapping:name

The name of the CMR field, which must match the cmr-field-name tag in the ejb-jar.xml file.

 

collection-mapping

Used to hold the persistence settings for the many side of a relationship when the cmr-field-type declared in ejb-jar.xml is java.util.Collection . Otherwise the same as the set-mapping element.

 

collection-mapping:table

The name of the mapping table (if a mapping table is used) or the table for the many bean (with the foreign key) if no mapping table is used.

 

set-mapping

Used to hold the persistence settings for the many side of a relationship when the cmr-field-type declared in ejb-jar.xml is java.util.Set . Otherwise the same as the collection-mapping element.

set-mapping:table

The name of the mapping table (if a mapping table is used) or the table for the many bean (with the foreign key) if no mapping table is used.

 

primkey-mapping

Defines the foreign key column in the "many" table.

 

cmp-field-mapping

Appears within the primkey-mapping element.

 

cmp-field-mapping:name

Holds the name of the foreign key column in the "many" table.

 

cmp-field-mapping: persistence-name

Also holds the name of the foreign key column in the "many" table.

 

value-mapping

Indicates the expected data type of the values in the Collection as well as how to map them to records in the database.

 

value-mapping:immutable

Whether the value can change once added to the collection (mutable) or will always stay the same (immutable). Immutable values are more efficient for the server.

true for Sets , false for Collections

value-mapping:type

The fully qualified Java class name of the objects stored as values in the collection, which amounts to the Local interface of the "many" bean.

 

cmp-field-mapping

Appears within the value-mapping element.

 

entity-ref

Indicates that the values are mapped to EJBs.

 

entity-ref:home

Holds the JNDI name where the server can find the entity whose interface is listed in value-mapping:type .

 

cmp-field-mapping

Appears within the entity-ref element to provide the primary key of the "many" table.

 

cmp-field-mapping:name

Holds the name of the primary key column in the "many" table.

 

cmp-field-mapping: persistence-name

Also holds the name of the primary key column in the "many" table.

 

For example, you'll use the User EJB and the PhoneNumber EJB. You'll assume a bidirectional one-to-many relationship; the PhoneNumber table has PhoneNumberId as its primary key, and a foreign key User that references Users(UserId) . Their relationship might look like this in ejb-jar.xml :

 <ejb-relation>     <ejb-relation-name>UserPhoneNumbers</ejb-relation-name>     <ejb-relationship-role>         <ejb-relationship-role-name>User</ejb-relationship-role-name>         <multiplicity>One</multiplicity>         <relationship-role-source>             <ejb-name>User</ejb-name>         </relationship-role-source>         <cmr-field>             <cmr-field-name>phoneNumbers</cmr-field-name>             <cmr-field-type>java.util.Collection</cmr-field-type>         </cmr-field>     </ejb-relationship-role>     <ejb-relationship-role>         <ejb-relationship-role-name>PhoneNumber</ejb-relationship-role-name>         <multiplicity>Many</multiplicity>         <relationship-role-source>             <ejb-name>PhoneNumber</ejb-name>         </relationship-role-source>         <cmr-field>             <cmr-field-name>user</cmr-field-name>         </cmr-field>     </ejb-relationship-role> </ejb-relation> 

Notice that each bean has a CMR field to access the other, and the User bean uses a Collection to access the group of PhoneNumbers for a user. To map this relationship to database columns, you must add entries to orion-ejb-jar.xml for each of the two entity beans. The PhoneNumber bean is the easier "many" bean, while the User bean is the more complex "one" side, as shown here:

 <entity-deployment name="  PhoneNumber  ">     <cmp-field-mapping name="user">         <entity-ref home="User">             <cmp-field-mapping name="  user  " persistence-name="  UserId  " />         </entity-ref>     </cmp-field-mapping> </entity-deployment> 

The PhoneNumber bean maps the user CMR field to the User foreign key field.

 <entity-deployment name="  User  ">     <cmp-field-mapping name="phoneNumbers">         <collection-mapping table="PhoneNumbers">             <primkey-mapping>                 <cmp-field-mapping name="  User  " persistence-name="  User  "/>             </primkey-mapping>             <value-mapping type="com.apress.oc4j903.ejb.PhoneNumber">                 <cmp-field-mapping>                     <entity-ref home="PhoneNumber">                         <cmp-field-mapping name="  PhoneNumberId  "                          persistence-name="  PhoneNumberId  " />                     </entity-ref>                 </cmp-field-mapping>             </value-mapping>         </collection-mapping>     </cmp-field-mapping> </entity-deployment> 

The User bean indicates that the primary key in the PhoneNumbers table is the PhoneNumberId column, and the foreign key in the PhoneNumbers table is the User column.

Mapping Many-to-Many Container-Managed Relationships

In a many-to-many relationship, each bean maps to a group of beans of the other type. For example, the User may have many Roles , and each Role may include many Users . This relationship is always modelled with a third join table (such as UserRoles ) in which each row in the join table is nothing but a pair of foreign keys, one to each of the bean tables.

The foreign key considerations in the other CMR cases don't apply here because neither bean table needs to include a foreign key. However, it's important to note that the join table cannot have any columns other than the foreign keys.

To map a many-to-many relationship to database tables, you'll use the following syntax for each bean in the relationship, as shown in Table 11-12.

Table 11-12: cmp-field-mapping for Many-to-Many Mappings

Parameter

Description

Default Value

cmp-field-mapping

This element encloses the CMR field definition.

 

cmp-field-mapping:name

The name of the CMR field, which must match the cmr-field-name tag in the ejb-jar.xml file.

 

collection-mapping

Used to hold the persistence settings when the cmr-field-type declared in ejb-jar.xml is java.util.Collection . Otherwise the same as the set-mapping element.

 

collection-mapping:table

The name of the mapping table.

 

set-mapping

Used to hold the persistence settings when the cmr-field-type declared in ejb-jar.xml is java.util.Set . Otherwise the same as the collection-mapping element.

 

set-mapping:table

The name of the mapping table.

 

primkey-mapping

Maps the foreign key in the join table to the primary key in this table.

 

cmp-field-mapping

Appears within the primkey-mapping element.

 

cmp-field-mapping:name

Holds the name of the foreign key column for this bean in the join table.

 

cmp-field-mapping: persistence-name

Holds the name of the primary key column that foreign key maps to in the bean table.

 

value-mapping

Indicates the expected data type of the values in the Collection as well as how to map them to records in the database.

 

value-mapping:immutable

Whether the value can change once added to the Collection (mutable) or will always stay the same (immutable). Immutable values are more efficient for the server.

true for Sets , false for Collections

value-mapping:type

The fully qualified Java class name of the objects stored as values in the Collection , which amounts to the Local interface of the opposite bean.

 

cmp-field-mapping

Appears within the value-mapping element.

 

entity-ref

Indicates that the values are mapped to EJBs.

 

entity-ref:home

Holds the JNDI name where the server can find the entity whose interface is listed in value-mapping:type .

 

cmp-field-mapping

Appears within the entity-ref element to provide the mappings for the other table.

 

cmp-field-mapping:name

Holds the name of the primary key column in the table for the other bean.

 

cmp-field-mapping: persistence-name

Holds the name of the foreign key column in the join table for the foreign key that maps to the other bean.

 

As an example, you'll use the User EJB and the Role EJB. You'll assume a bidirectional many-to-many relationship; the UserRoles table has a User foreign key that references Users(UserId) , and a Role foreign key referencing Roles(RoleId) . The primary key in the Users table is named UserId and RoleId for the Roles table. Their relationship might look like this in ejb-jar.xml :

 <ejb-relation>     <ejb-relation-name>UserRole</ejb-relation-name>     <ejb-relationship-role>         <ejb-relationship-role-name>User</ejb-relationship-role-name>         <multiplicity>Many</multiplicity>         <relationship-role-source>             <ejb-name>User</ejb-name>         </relationship-role-source>         <cmr-field>             <cmr-field-name>roles</cmr-field-name>             <cmr-field-type>java.util.Collection</cmr-field-type>         </cmr-field>     </ejb-relationship-role>     <ejb-relationship-role>         <ejb-relationship-role-name>Role</ejb-relationship-role-name>         <multiplicity>Many</multiplicity>         <relationship-role-source>             <ejb-name>Role</ejb-name>         </relationship-role-source>         <cmr-field>             <cmr-field-name>users</cmr-field-name>             <cmr-field-type>java.util.Collection</cmr-field-type>         </cmr-field>     </ejb-relationship-role> </ejb-relation> 

Notice that each bean has a CMR field to access the other, and both use a Collection . To map this relationship to database columns, you must add entries to orion-ejb-jar.xml for each of the two entity beans, as follows:

 <entity-deployment name="  User  ">     <cmp-field-mapping name="roles">         <collection-mapping table="  UserRoles  ">             <primkey-mapping>                 <cmp-field-mapping name="  User  " persistence-name="  UserId  " />             </primkey-mapping>             <value-mapping type="com.apress.oc4j903.ejb.Role">                 <cmp-field-mapping>                     <entity-ref home="Role">                         <cmp-field-mapping name="  RoleId  "                         persistence-name="  RoleId  " />                     </entity-ref>                 </cmp-field-mapping>             </value-mapping>         </collection-mapping>     </cmp-field-mapping> </entity-deployment> 

When you compare the preceding User mapping to the following Role mapping, you see that each side effectively includes all the information required for the relationship, and the positions in which the different field names appear are opposite.

 <entity-deployment name="  Role  ">     <cmp-field-mapping name="users">         <collection-mapping table="  UserRoles  ">             <primkey-mapping>                 <cmp-field-mapping name="  Role  " persistence-name="  RoleId  " />             </primkey-mapping>             <value-mapping type="com.apress.oc4j903.ejb.User">                 <cmp-field-mapping>                     <entity-ref home="User">                         <cmp-field-mapping name="  UserId  "                          persistence-name="  UserId  " />                     </entity-ref>                 </cmp-field-mapping>             </value-mapping>         </collection-mapping>     </cmp-field-mapping> </entity-deployment> 
Mapping Relationships in EJB 1.1

Though EJB 1.1 doesn't include standard features for relationships between entity beans, OC4J provides proprietary methods for mapping relationships to the database. We won't cover those features in detail, since the standard EJB 2.0 CMR features are available, but in short, relationships are mapped more or less the same way as CMR. In addition to individual Entities, Sets , and Collections , these mappings can include Lists, Vectors , and Arrays (using the list-mapping element), and Maps, Hashtables , and java.util.Properties (using the map-mapping element).

The new elements used listed in Table 11-13.

Table 11-13: list-mapping Elements

Parameter

Description

list-mapping

Indicates how to persist a List, Vector , or array, with a primkey-mapping child and a value-mapping child.

map-mapping

Indicates how to persist a Map, Hashtable , or Properties , with a primkey-mapping child, a map-key-mapping child, and a value-mapping child.

map-key-mapping

Specifies the persistence of the keys of the map.

map-key-mapping:type

The fully qualified Java class name of the key type.

Message-Driven Bean Deployment Header

For every message-driven bean (MDB) declared in ejb-jar.xml , you need to specify a <message-driven-deployment> element in orion-ejb-jar.xml with the locations of JMS connection factories and destinations. Within this element, you can also declare environment entries, reference other EJBs, reference resources, and configure a few optional performance settings.

For example, if the ejb-jar.xml declares the following message-driven bean:

 <message-driven>      <description>Order Confirmation Mailer</description>      <display-name>OrderConfirmationService</display-name>      <ejb-name>OrderConfirmationService</ejb-name>      <ejb-class>com.apress.ejb.OrderConfirmationService</ejb-class>      <transaction-type>Container</transaction-type>      <message-driven-destination>        <destination-type>javax.jms.Topic</destination-type>        <subscription-durability>Durable</subscription-durability>      </message-driven-destination> </message-driven> 

Then you need to add something like this to the orion-ejb-jar.xml :

 <message-driven-deployment   name="OrderConfirmationService"   connection-factory-location=       "java:comp/resource/storeCF/TopicConnectionFactories/storeCF"   destination-location="java:comp/resource/storeCF/Topics/orders"   subscription-name="orderSub"   listener-threads="25" transaction-timeout="43200"> ... </message-driven-deployment> 

Table 11-14 lists the message-driven-deployment elements.

Table 11-14: message-driven-deployment Elements

Parameter

Description

Default Value

message-driven-deployment

Contains container-specific settings for an individual message-driven bean. In particular, it links the MDB to an actual JMS topic or queue.

 

message-driven-deployment: cache-timeout

Should not be used for MDBs. (For stateless session beans, this specifies the number of seconds to keep instances in the pool.)

 

message-driven-deployment: connection-factory-location

The JNDI location of the JMS connection factory to use. Should be specified in the form: "java:comp/resource" plus the resource-provider name plus the "TopicConnectionFactories" or " QueueConnectionFactories" plus the user-defined name, where the resource-provider name matches the resource provider defined in application.xml .

 

message-driven-deployment: destination-location

The JNDI location of the queue or topic to use. Should be specified in the form "java:comp/resource/" plus the resource-provider name plus the "/Topics/" or "/Queues/" plus the name of the topic or queue.

 

message-driven-deployment: max-instance

Should not be used for MDBsuse listener threads instead. (For other types of beans, this specifies the max number of instances to keep in the pool.)

 

message-driven-deployment: min-instances

Should not be used for MDBsuse listener threads instead. (For other types of beans, this specifies the minimum number of instances to keep in the pool.)

 

message-driven-deployment: name

The name of the message-driven bean, as defined in ejb-jar.xml .

 

message-driven-deployment: subscription-name

For topics, the name of the subscription.

 

message-driven-deployment: listener-threads

The number of threads created to consume messages concurrently.

1

message-driven-deployment: transaction-timeout

The number of seconds before a container-managed MDB transaction is rolled back automatically.

86400 (1 day)

Resolving EJB References

Within ejb-jar.xml , EJBs can declare references to other EJBs using the <ejb-ref> element. This allows you to look up the referenced EJBs within the component environment ( java:comp/env ) using a logical name.

These logical names need to be mapped to the actual JNDI locations of the EJBs with the <ejb-ref-mapping> element in orion-ejb-jar.xml .

For example, if the EJB needed to reference an Invoice bean, you might declare the following in its ejb-jar.xml :

 <ejb-ref>     <ejb-ref-name>ejb/accounting/Invoice</ejb-ref-name>     <ejb-ref-type>Entity</ejb-ref-type>     <home>com.apress.ejb.accounting.InvoiceHome</home>     <remote> com.apress.ejb.accounting.InvoiceHome</remote> </ejb-ref> 

Then, within its orion-ejb-jar.xml , you would map that name to the JNDI location of an actual deployed EJB, as follows:

 <ejb-ref-mapping name="ejb/accounting/Invoice"              location="Invoice"/> 
Note 

If the logical ejb-ref-name matches the actual JNDI location, you don't need to provide a mapping. Even if it doesn't match, you can avoid this mapping by specifying the actual JNDI location in the <ejb-link> element inside <ejb-ref> in the ejb-jar.xml .

The <ejb-ref-mapping> element can be used inside session, entity, and message-driven deployments, and allows for the specification of the following attributes listed in Table 11-15.

Table 11-15: ejb-ref-mapping Elements

Parameter

Description

ejb-ref-mapping:location

The actual JNDI location where the referenced EJB can be found (as specified in that bean's orion-ejb-jar.xml ).

ejb-ref-mapping:name

The logical name given to the referenced bean in the <ejb-ref-name> element.

Resolving Resource References

Within ejb-jar.xml , EJBs can declare references to JDBC data sources, JavaMail sessions, URLs, and other resources using the <resource-ref> element. This element allows the EJB to look up the resource within its component environment ( java:comp/env ) using a logical name.

Unless these logical names match the real JNDI locations exactly, they need to be mapped to actual resource locations using the resource-ref-mapping element in orion-ejb-jar.xml .

For example, if you assign the logical name jdbc/CustomerDS to a DataSource in ejb-jar.xml like this:

 <resource-ref>     <res-ref-name>  jdbc/CustomerDS  </res-ref-name>     <res-type>javax.sql.DataSource</res-type>     <res-auth>Application</res-auth> </resource-ref> 

Now you define the following data source in the data-sources.xml configuration file, as follows:

 <data-source    class="com.evermind.sql.DriverManagerDataSource"    name="OracleDS"    location="jdbc/direct/OracleCustomerDatabase"    xa-location="jdbc/xa/OracleCustomerDatabase "    ejb-location="jdbc/OracleCustomerDatabase "    connection-driver="oracle.jdbc.driver.OracleDriver"    username="scott"    password="tiger"    url="jdbc:oracle:thin:@localhost:1521:oracle"    inactivity-timeout="30" /> 

You need to map the resource reference to the actual data source in orion-ejb-jar.xml like this:

 <resource-ref-mapping name="jdbc/CustomerDS"             location="jdbc/OracleCustomerDatabase"/> 

If you need to look up a resource in a location outside the server, then you can link to an external JNDI context like this:

 <resource-ref-mapping name="logicalName">     <lookup-context location="some/external/jndi/location">         <context-attribute name="java.naming.factory.initial"                 value="someInitialContextFactoryClass"/>     </lookup-context> </resource-ref-mapping> 

The <resource-ref-mapping> element can be used inside session, entity, and message-driven deployments, and contains the following elements listed in Table 11-16.

Table 11-16: resource-ref-mapping Elements

Parameter

Description

resource-ref-mapping:name

Matches the logical resource-ref name used in ejb-jar.xml .

resource-ref-mapping:location

The actual JNDI location of the resource to map to.

lookup-context

Allows the optional specification of a particular context to be used to look up a resource (useful when the resource is outside the server).

lookup-context:location

Name where the resource can be found in the specified context.

context-attribute

Specifies JNDI properties to be used for the specified lookup-context . Only the initial context factory property is required.

context-attribute:name

Name of the JNDI property (for example, java.naming.factory.initial ).

context-attribute:value

Value of the JNDI property (for example, the class name of the initial context factory).

Resolving Resource env References

The ejb-jar.xml descriptor can also define <resource-env-ref> elements for administered objects associated with other resources (for example, JMS destinations). These references are mapped very similarly to the resource references described earlier.

For example, if the ejb-jar.xml references a JMS topic like this:

 <resource-env-ref>     <description>Registration Events</description>     <res-env-ref-name>jms/regEventsTopic</res-ref-name>     <res-env-ref-type>javax.jms.Topic</res-type> </resource-env-ref> 

and you've declared the corresponding topic in the jms.xml like this:

 <topic name="Registration Events" location="jms/RegistrationTopic">     <description>Broadcasts user registration events</description> </topic> 

then the orion-ejb-jar.xml should contain something like this:

 <resource-env-ref-mapping name="jms/regEventsTopic"                           location="jms/RegistrationTopic"/> 

The <resource-env-ref-mapping> element can be used inside session, entity, and message-driven deployments, and contains the following elements in Table 11-17.

Table 11-17: resource-env-ref-mapping Elements

Parameter

Description

resource-env-ref-mapping:name

Matches the logical resource-env-ref name used in ejb-jar.xml .

resource-env-ref-mapping:location

The actual JNDI location of the resource to map to.

Overriding Environment Entries

In some cases, you may want to override an environment entry specified in an ejb-jar.xml (perhaps to avoid altering the standard descriptor of a third-party component). OC4J allows you to do this in orion-ejb-jar.xml with the env-entry-mapping element.

For example, if the ejb-jar.xml contains the following environment entry:

 <env-entry>     <env-entry-name>pastDueDays</env-entry-name>     <env-entry-type>java.lang.Integer</env-entry-type>     <env-entry-value>15</env-entry-value> </env-entry> 

then you can override it to a different value in orion-ejb-jar.xml like this:

 <env-entry-mapping name="pastDueDays">30</env-entry-mapping> 

The elements are listed in Table 11-18.

Table 11-18: env-entry-mapping Elements

Parameter

Description

env-entry-mapping

In session-deployment, message-driven deployment, and entity-driven deployment. Body is the new value.

env-entry-mapping:name

Matches the env entry name in ejb-jar.xml .

Asynchronous Invocation with AC4J

In addition to the standard J2EE message-driven beans described earlier, OC4J allows asynchronous calls to EJBs using the proprietary AC4J architecture. If you want the beans to be accessible through AC4J, you need to configure the names, Databus, and security that will be used to invoke them.

In the following example (within orion-ejb-jar.xml ) you make the CustomerManager EJB accessible through AC4J as jem/CustMgr , and configure it to use the caller's identity and require that the caller possess the manager role. You also need to specify the data source that contains the AC4J Databus, using the <jem-server-extension> element, as follows:

 <jem-server-extension data-source-location="  jdbc/DataBusDS  "         scheduling-threads="1">     <description>AC4J configuration</description> </jem-server-extension> <jem-deployment jem-name="  jem/CustMgr  "         ejb-name="  CustomerManager  ">     <description>  CustomerManager  bean</description>     <called-by>         <caller caller-identity="manager"/>     </called-by>     <security-identity>         <description>pass through caller identity</description>         <use-caller-identity>true</use-caller-identity>     </security-identity> </jem-deployment> 

Without changing the CustomerManager implementation in any way, you've now allowed clients to invoke its methods asynchronously through AC4J. For example, to issue a credit check, a client might do something like this:

 Context context = new InitialContext(); String dsName = "java:comp/env/jdbc/DataBusDS"; DataSource ds = (DataSource) context.lookup(dsName); Connection dsCon = ds.getConnection("user", "password"); JEMConnection jemCon = new JemConnection(dsCon); JEMSession jemSession = new JEMSession(jemCon); JEMHandle custMgr = (JEMHandle) context.lookup("jem/CustMgr"); Object[] params = new Object[] { accountNumber, expiration }; JEMEmitToken call = jemSession.call(custMgr, "processCreditCheck",     null, params, null, 0, 0); dsCon.commit(); 

At this point, the Data Bus takes control and invokes CustomerManager.processCreditCheck() at the next opportunity without forcing the client to wait for CustomerManager to be available.

For more information about using AC4J, check the OC4J Enterprise JavaBeans Developer Guide and the AC4J JavaDocs, both available at http://otn.oracle.com .

The following elements listed in Table 11-19 may be used inside the <enterprise-beans> element to configure AC4J deployments.

Table 11-19: jem-server-extension Elements

Parameter

Description

Default Value

jem-server-extension

Contains AC4J configuration information for JEM deployments.

 

jem-server-extension: data-source-location

JNDI location of the DataSource (defined in data-sources.xml ) that contains the Data Bus.

 

jem-server-extension: scheduling-threads

Number of OC4J threads that can act in parallel.

1

jem-deployment

Contains information about how to locate the EJB and invoke its methods securely.

 

jem-deployment:ejb-name

Specifies the name of the EJB as defined in ejb-jar.xml .

 

jem-deployment:jem-name

Specifies the name AC4J clients will use to find this EJB.

 

called-by

Specifies which callers are allowed to invoke this EJB through AC4J.

 

caller

Represents a single caller allowed to invoke this EJB through AC4J.

 

caller:caller-identity

The specific security role the caller must possess.

 

security-identity

Specifies whether to propagate security identities through AC4J or always use a specified identity.

 

use-caller-identity

If true, caller's identity will be used.

 

run-as-specified-identity

If specified, the identity AC4J will use to invoke this EJB's methods.

 

role-name

The specific security role to use

 

RMI/IIOP Security Interoperability

Most CORBA configuration takes place at the server level. For each individual CORBA-accessible EJB, however, you need to configure security settings in ejb-jar.xml .

In particular, you need to specify which transport security features are supported or required, whether or not callers must be authenticated, and how caller identities will be propagated.

In the following example, you'll require one transport security element and support all the others. Callers to this EJB will need to authenticate with a username and password against the default realm. Finally, if provided by other servers, delegated identities will be used.

 <ior-security-config>   <transport-config>     <integrity>required</integrity>     <confidentiality>supported</confidentiality>     <establish-trust-in-target>supported</establish-trust-in-target>     <establish-trust-in-client>supported</establish-trust-in-client>   </transport-config>   <as-context>     <auth-method>username_password</auth-method>     <realm>default</realm>     <required>true</required>   </as-context>   <sas-context>     <caller-propagation>supported</caller-propagation>   </sas-context> </ior-security-config> 

The <ior-security-config> element may be used within session and entity deployments, and includes the following elements listed in Table 11-20.

Table 11-20: transport-config Elements

Parameter

Description

transport-config

Contains settings for CSIv2 security properties.

integrity

Specifies whether CSIv2 integrity is required, supported , or not supported ( none ).

confidentiality

Specifies whether CSIv2 confidentiality is required, supported , or not supported ( none ).

establish-trust-in-target

Specifies whether CSIv2 establish-trust-in-target is required, supported , or not supported ( none ).

establish-trust-in-client

Specifies whether CSIv2 establish-trust-in-client is required, supported , or not supported ( none ).

as-context

Contains settings for caller authentication

auth-method

Specifies how the caller should authenticate. May be set to username_password or none .

realm

The realm to use for authentication. Must be set to default in current releases.

required

Whether authentication is required to use this EJB.

sas-context

Contains settings for caller identity propagation.

caller-propagation

Specifies whether this EJB accepts propagated identities. If set to required , then servers must pass in an identity. If supported , then it will allow identities to be propagated. If set to none , then identity propagation isn't supported.



Oracle Application Server 10g. J2EE Deployment and Administration
Oracle Application Server 10g: J2EE Deployment and Administration
ISBN: 1590592352
EAN: 2147483647
Year: 2004
Pages: 150

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