7.7. Deploying an Enterprise JavaBeans Object
As shown in Figure 7-2, the EJB container generates a set of classes that deploy your EJB object. It's up to the EJB container to provide a tool or tools for generating these classes. Some may be command-line tools that accept some sort of properties file that tells the EJB container about your bean, while others may be GUI tools that let you control the deployment options of your bean using a visual interface. Regardless of the deployment/generation tool your EJB application server provides, it needs to be told the fully qualified names for the home and remote interfaces for your EJB object and for the bean implementation class. It also needs to be told how to deploy your bean, in terms of transaction support, client access to features of your bean, and management of the persistent data (if any) associated with your bean. The baseline information and options needed for deploying your enterprise bean are as follows:
Some EJB containers may expand on this baseline list to include properties they need for extended services they may provide or additional controls they provide to supplement the basic EJB deployment options.
All these deployment properties are represented as publicly accessible properties on the DeploymentDescriptor, SessionDescriptor, and EntityDescriptor classes in the javax.ejb.deployment package. If you want to create an EJB-JAR package for your bean, the EJB server tools typically allow you to bundle your deployment options into an instance of either the SessionDescriptor or EntityDescriptor class and serialize the object to a file to be included in the EJB-JAR file as the bean's deployment descriptor. See the later section "Packaging Enterprise Beans" for more details.
At the time of this writing, the released EJB specification doesn't include a standard format for deployment descriptor files. The EJB 1.1 public draft includes an XML-based deployment descriptor schema, but until the 1.1 specification is released and this standard deployment descriptor file format is widely supported, you need to deal with the vendor-specific formats currently provided by each EJB server. Currently, the only way to provide a portable deployment descriptor for your enterprise bean is to do the work of the server deployment tools yourself. To do this, you have to write some Java code that creates an instance of the appropriate DeploymentDescriptor subclass, fills in the properties on this object, and then serializes the descriptor object to a file. If you need to do this, refer to Chapter 20, "The javax.ejb.deployment Package" for details on DeploymentDescriptor and its subclasses. For the examples that follow, however, I'm going to show snippets of deployment descriptor files for a particular EJB server, BEA's WebLogic application server.
7.7.1. Container-Managed Data Mapping
If you are deploying an entity bean with container-managed persistence, you need to tell the EJB container which fields on your bean implementation are persistent and how to map them to persistent storage. For example, suppose we are deploying our entity ProfileBean, using container-managed persistence. Let's assume that we've made the modifications to our bean implementation we discussed in the section "Container-Managed Persistence." In other words, we've created a table called PROFILE_BYTES with a single LONG BINARY column named DATA to hold our serialized Properties object. Now we simply have to tell the container that the mEntriesBytes member on our modified ProfileBean is mapped to the DATA column on the PROFILE_BYTES table, with an entry in a textual deployment options file like this example shown for BEA WebLogic server:
(persistentStoreProperties persistentStoreType jdbc (jdbc tableName PROFILE_BYTES ... (attributeMap mName NAME mEntriesBytes DATA ) ) ) ... containerManagedFields [mName mEntriesBytes]
Based on these mappings, the EJB container generates all of the necessary JDBC calls in its generated classes.
7.7.2. Access-Control Deployment Attributes
There are precious few details in the EJB 1.0 specification about support for security in EJB containers, but there is a construct provided for you to specify certain access control levels at deployment time.
Essentially, the EJB server should provide some means for mapping a client-provided identity (in the form of a java.security.Identity object) to a named user or role on the EJB server itself. Then you, the bean provider, can specify which users and/or roles can access each method on your bean. The EJB server allows you to specify access control levels in some server-specific way (ideally, using the same deployment tools as the other deployment attributes). There should be a way to specify access for the entire bean, as well as for individual methods. Any method without an access-control entry assumes the access level of the bean as a default. So, for the various versions of our ProfileBean, we might want to allow anyone to get profile entries off of the bean, but only allow profile administrators (users or applications) to set profile entries. We might do this by specifying access-control entries such as:
(accessControlEntries DEFAULT [everyone] "setEntry(String, String)" [profileAdmin] )
As a step towards standardizing the specification of client identities to the EJB server, there is a proposal being considered by various EJB providers that involves the use of a reserved JNDI name entry to hold the client's identity. The client would provide an Identity object to the EJB server as the value of the Context.PROVIDER_IDENTITY property, passed in when the client creates its initial JNDI naming context from the server. This issue should be settled in an upcoming update to the EJB specification.
In addition to specifying client access rules for your bean, you need to specify to the EJB server what identity your bean should assume when it accesses controlled resources, such as other EJB objects and databases. This is done using two deployment properties: run-as-mode and run-as-identity. The run-as-mode property indicates whether the bean should assume the identity of the client that invoked it (CLIENT_IDENTITY), the identity of some system-defined account (SYSTEM_IDENTITY), or the identity of some other specific user account (SPECIFIED_IDENTITY). The SYSTEM_IDENTITY option causes the EJB server to use a platform-specific privileged account. A server may use the root account on Unix systems or the Administrator account on Windows NT systems, for example. Some EJB servers may use the account that runs the server when the SYSTEM_IDENTITY is specified. The run-as-identity property is used when run-as-mode is set to SPECIFIED_IDENTITY. The identity given in the run-as-identity property is the identity the bean assumes when accessing system resources and other beans.
The run-as-mode and run-as-identity attributes are settable at the bean level or at the individual method level, in the same way client access levels are applied. If you set these attributes for specific methods on your bean, that means you want those methods to be executed using the specified identity for access-control purposes. There are some restrictions imposed by the EJB specification, however. Within a single transaction, all methods invoked on your bean must be run with the same identity. If a client transaction attempts to execute methods you've deployed with different access-control identities, the server throws an RMI RemoteException to the client. If your bean is a stateful session bean, all methods executed during a session lifetime must be the same. If a client attempts, within the same session, to execute methods on your bean that have different access-control identities associated with them, the EJB server throws an RMI RemoteException.
7.7.3. Generating the Container Classes and Deployment Descriptor
Once you've specified all the deployment options for your bean, the container provides a utility for converting these deployment properties to a serialized deployment descriptor. This deployment descriptor is a serialized instance of either the EntityDescriptor or SessionDescriptor class from the javax.ejb.deployment package. The container tools store all the deployment options you specified into an instance of one of these classes, depending on what type of bean you're deploying, and serialize the object to a file you specify, one for each type of bean that you are deploying. You can then use these deployment descriptors to package your enterprise beans into EJB-JAR files, as described a bit later.
In addition to the deployment descriptor, you also need to use the EJB container's tools to generate the container-specific classes that deploy your bean, as shown in Figure 7-2. In order to generate these classes, the container tools need to take into account your deployment options. If you're deploying an entity bean, for example, the tool needs to know whether the bean uses container-managed persistence or not, so that the tool knows whether it needs to include JDBC code for the bean in its generated classes. The container tools typically allow you to specify where to generate the deployment classes.
Once you have your compiled interfaces and bean implementation class, the deployment descriptor, and the container-generated classes for your bean, you're ready to package your bean in an EJB-JAR file.
7.7.4. Packaging Enterprise JavaBeans
EJB-JAR files are the standard packaging format for Enterprise JavaBeans. They are normal Java archive (JAR) files, created using the standard jar utility, but they contain specific files that provide all the information needed for an EJB container to deploy the beans that are contained in the EJB-JAR file. An EJB-JAR file can contain one or many beans.
An EJB-JAR file contains three components:
The manifest file is a simple text file, with sections delimited by blank lines. Each section has name/value pairs. The name starts the line, followed by a colon, followed by the value. EJB-JAR files define two tags: "Name" and "Enterprise-Bean". The Name line specifies the serialized deployment descriptor for an enterprise bean, while Enterprise-Bean marks the section as relevant to the EJB server and always has a value of "True". Here's a typical manifest file that might be used for an EJB-JAR file that contains a few of our bean examples:
Name: jen/ejb/stateless/ProfileServerBeanDD.ser Enterprise-Bean: True Name: jen/ejb/entity/beanManaged/ProfileBeanDD.ser Enterprise-Bean: True
This manifest file describes two enterprise beans. The EJB-JAR file that contains this manifest must contain the two serialized deployment descriptors named in the manifest file, all class files specified in the deployment descriptors for the beans, and all container-generated classes for deploying the bean.
An EJB-JAR file contains everything an EJB container needs to deploy your bean. The container reads the manifest file and, for each bean specified, loads the serialized deployment descriptor and checks its parameters. The container looks in the JAR file for the class files needed for the bean and deploys the bean using the additional parameters specified in the deployment descriptors.
Some EJB container/server providers include a utility to facilitate the creation of EJB-JAR files from your bean classes. It's a simple matter, however, to create one using the standard jar utility provided with nearly every Java SDK implementation. Assuming that you have created a manifest file, such as the one shown earlier, in a file named ProfileManifest.txt, you can create an EJB-JAR file for the previous two beans with the following command:
% jar cmf ProfileManifest.txt ProfileBeans.jar\ jen/ejb/stateless jen/ejb/entity/beanManaged
This command creates an EJB-JAR file named ProfileBeans.jar in the current directory. The jar utility automatically places the manifest file in the proper location in the JAR file for you. Note that we're assuming that the subdirectories we've included in the JAR file contain both the class files we need and the serialized deployment decriptors mentioned in the manifest file.
Copyright © 2001 O'Reilly & Associates. All rights reserved.