Before we delve into the configuration of the various EJB types, it is useful to understand under which circumstances the different EJB types should be used. After this, we provide an overview of how to package your EJBs, and how to use the deployment descriptors to configure the runtime behavior of your EJBs. We also describe how you can use WebLogic's tools to generate and compile the classes needed to deploy your EJBs. Finally, we look at how to set up references to other EJBs and resources.
10.1.1 EJB Types
WebLogic provides full support for the different component models: session beans that model business processes, entity beans that model domain entities, and message-driven beans (MDBs) that represent asynchronous message consumers. Here's a quick summary of important characteristics of these three EJB types:
Session beans
Consider using a session bean when only one client can have access to an EJB instance, and session state is relatively short-lived and need not be persisted. Consider using a stateful bean if the EJB holds session information for a client across multiple method invocations, or the EJB mediates between the client and other EJB components. Consider using a stateless bean if the EJB doesn't need to hold any client-specific session data, or you require a pool of objects that implement a generic set of business tasks. Stateless session beans are often used to create façades to entity beans.
Entity beans
You should use entity beans to model business concepts (entities) and not business procedures. For instance, a Student (university applicant) should be modeled as an entity bean, whereas Registration (registering for university courses) should be modeled as a session bean.
Consider using entity beans when the EJB state needs to persist beyond the lifetime of the EJB container. Consider using automatic EJB persistence if you want to avoid JDBC code and just let the EJB container synchronize the EJB's in-memory state with the underlying database. In fact, WebLogic's EJB container also supports a powerful way to handle relationships with other EJB instances.
Message-Driven Beans
Consider using MDBs when you need a pool of listeners that can respond asynchronously to JMS messages received on a particular JMS destination.
There is a price to be paid for using an EJB component rather than an ordinary Java object to implement your business logic. The EJB container provides inherent support for pooling, transactions, concurrency, security, remote access, persistence, and state management. If your application doesn't require support for these enterprise services, ordinary Java objects should suffice, perhaps supplemented with an alternative persistence mechanism such as plain Java Data Objects, or JDBC. However, if your business processes do need support for these features, the EJB framework provides an ideal platform for building enterprise applications.
A detailed discussion of how to develop EJB components is beyond the scope of this book. You should refer to Enterprise JavaBeans, Third Edition, by Richard Monson-Haefel (O'Reilly), for an in-depth explanation of the EJB programming model. Instead, we cover WebLogic-specific issues of which you should be aware when developing and deploying your EJB components. We also look at how WebLogic's EJB container manages the life cycle of enterprise beans, as this is crucial to understanding how WebLogic lets you manipulate and optimize the behavior of the EJB container.
10.1.2 Building EJBs
To implement an EJB, you need to create the bean implementation class, together with the home and remote interfaces. Entity EJBs often require more, such as primary key classes and value objects. These are all standard J2EE requirements, and you should familiarize yourself with the EJB specification, and in particular the life cycle of EJB components, before starting your implementation. WebLogic eases the implementation burden by providing convenience classes, the EJBGen tool, and WebLogic Workshop. The latter items will be covered in later sections.
The EJB specification requires any bean class to implement a number of methods that are invoked at various stages in the life cycle of the bean. To help you on your way, WebLogic provides convenience classes that provide sensible default implementations of these methods. These classes can be found in the weblogic.ejb package, and are all abstract classes. The most relevant are the GenericSessionBean, GenericEntityBean, and GenericMessageDrivenBean classes. Here is an example demonstrating how easy it is to create a session bean implementation class:
import javax.ejb.*; import weblogic.ejb.*; public class EasySessionBean extends GenericSessionBean { public List getUsers( ) { /* ... */ }; public List getGroups( ) { /* .. */ }; ... }
If you use EJBGen in addition to these convenience classes, you can construct complete EJBs, together with their metadata, using only a handful of lines.
10.1.3 EJBGen
EJBGen is a flexible code generator for EJBs. At one fell swoop it eliminates all the hassle associated with EJB development. The input to the tool is a bean implementation source file, annotated with JavaDoc tags. EJBGen parses this file, and generates the associated home and remote interfaces, as well as the accompanying XML descriptor files. The code generation is accomplished using templates, so you can modify these templates to enable the tool to generate code specific to your project.
EJBGen is supplied with WebLogic. Simply run the setEnv script to ensure that your classpath is set up appropriately before invoking the tool. The latest version of the tool, together with extensive documentation, is available at http://www.beust.com/ejbgen. There are many reasons why you should consider using EJBGen, instead of hand-coding all of the EJB source files and their subsidiary files:
The following sections provide an overview of how to use EJBGen, as well as a description of some of the additional features provided by the tool.
10.1.3.1 Using EJBGen
EJBGen is a command-line tool, implemented as a JavaDoc doclet. You can invoke it as follows:
javadoc -docletpath %WL_HOME%/server/lib/weblogic.jar -doclet weblogic.tools.ejbgen.EJBGen YourBean.java
Note that the -docletpath argument specified here must point to WebLogic Server's library, weblogic.jar. If you specify multiple Java files as arguments to the doclet, EJBGen will process each Java file. This will be necessary if you invoke the tool on entity EJBs that are involved in container-managed relationships. EJBGen also provides a standard Java class that you can invoke. In this case, you would invoke the tool as follows:
java weblogic.tools.ejbgen.EJBGen YourBean.java
Invoking this tool without any arguments lists all of the possible options.
Example 10-1 shows the source for a complete, annotated EJB that can be given to the tool as input. Notice how the EJB also makes use of the GenericSessionBean convenience class.
Example 10-1. An annotated session EJB file
package com.oreilly.wlguide.ejb; import javax.ejb.*; import weblogic.ejb.*; /** * @ejbgen:session * ejb-name = simpleSession * max-beans-in-free-pool = 42 * enable-call-by-reference = true * is-clusterable = true * methods-are-idempotent = true * trans-timeout-seconds = 20 * @ejbgen:jndi-name * remote = mySimpleSessionHome */ public class SimpleEJB extends GenericSessionBean { /** * Perform some business method. * @ejbgen:remote-method * is-idempotent = true */ public int calculate (int input) { return input*2; } }
This example has two sets of JavaDoc tags one annotating the entire class and which generally applies to the entire EJB, and the other specific for each EJB method. EJBGen provides a number of tags to take care of different deployment and configuration needs of the EJB. For example, you can use the @ejbgen:session tag to specify the general attributes of a session bean, the @ejbgen:jndi-name tag to specify its JNDI properties, and the @ejbgen:remote-method to indicate that the method must be exposed via the remote interface and to get additional information about its deploy-time and runtime behavior. Dozens of other tags can be used to specify everything from entity EJB finder methods and relationships to the details of a foreign JMS provider. Please refer to the tool documentation for a complete description of the supported JavaDoc tags.
Once you've properly annotated the EJB class file, you don't need to write anything else. Simply feed this source file to EJBGen, and it will produce the following items:
Simple.java
This file, representing the remote interface for the session bean, will look something like this:
public interface Simple extends EJBObject { public int calculate(int input) throws RemoteException; }
SimpleHome.java
The home interface for the session bean also will be created. It will look like this:
public interface SimpleHome extends EJBHome { public Simple create( ) throws CreateException, RemoteException; }
ejb-jar.xml
The standard EJB descriptor that is generated completely describes the EJB:
simpleSession com.oreilly.weblogic.ejb.SimpleHome com.oreilly.weblogic.ejb.Simple com.oreilly.weblogic.ejb.SimpleEJB Stateless Container
weblogic-ejb-jar.xml
The WebLogic-specific descriptor file, which contains many of the tedious descriptor settings needed to configure the bean, is also generated:
simpleSession 42 true true 20 true mySimpleSessionHome simpleSession calculate int
As you can see, there is nothing more to do. Simply JAR up the source and descriptor files, compile the EJB using weblogic.appc, and deploy!
10.1.3.2 Tag inheritance
EJBGen fits nicely into the OO mold, letting you inherit tag and attribute values. For example, say that all of your session EJBs inherit from the following base class:
/** * @ejbgen:session * trans-timeout-seconds = 20 * is-clusterable = true */ public class BaseSession extends GenericSessionBean { /* ... */ }
Classes that extend this BaseSession class will inherit the clusterable and timeout attributes automatically. Here is an example:
/** * @ejbgen:session * ejb-name = concreteSession */ public class ConcreteSession extends BaseSession { /* ... */ }
These classes can, of course, also override the attribute values by specifying their own copies.
10.1.3.3 Templates
The latest version of EJBGen generates the source files from a set of templates. By modifying the templates that EJBGen uses, you can customize the generated files. If you want to modify the templates, then you first need to extract them:
java weblogic.tools.ejbgen.EJBGen -extractTemplates tempDirectory
After modifying the templates appropriately, use the -templateDir argument to instruct EJBGen to use the modified templates. For example, you could then invoke the tool as follows:
java weblogic.tools.ejbgen.EJBGen -templateDir tempDirectory SimpleEJB.java
10.1.3.4 Reverse engineering
EJBGen is accompanied by a tool that can be used to reverse-engineer an EJB JAR and produce an EJBGen-annotated source file. The tag information embedded in the generated file is gleaned from introspecting the class files in the EJB, as well as from the accompanying XML descriptor files. If you have existing EJB source files and you want to start using EJBGen, you should use this tool. You can run it like this:
java com.bea.wls.revejbgen.Main -d outputdirectory EJBJar.jar
The Java class generated by this command is an abstract class. You can either create a concrete class that implements all of its methods, or perhaps more simply use the generated class as the basis for a new source file.
10.1.4 Packaging EJBs
The EJB classes and XML deployment descriptors are packaged in a single, deployable unit called an EJB JAR. A typical EJB JAR file includes the following:
Container classes are not strictly necessary, as WebLogic can create them at deployment time. For instance, the contents of an EJB JAR that packages a Registration session EJB could include the following files:
org/foo/bar/Registration.class org/foo/bar/RegistrationHome.class org/foo/bar/RegistrationBean.class meta-inf/Manifest.mf meta-inf/ejb-jar.xml meta-inf/weblogic-ejb-jar.xml
You also could package any dependent Java utility classes along with the EJB classes. Alternatively, you could set the Class-Path attribute in the JAR's manifest file, META-INF/MANIFEST.MF, to reference any dependent JAR files. However, this feature works only for EJB JARs that are deployed as part of an EAR file.
10.1.5 XML Deployment Descriptors
Every EJB JAR needs a standard ejb-jar.xml descriptor file. If your EJBs conform to the EJB 2.0 specification, this deployment descriptor must be a valid XML document that includes the following DTD reference:
The standard ejb-jar.xml descriptor is used to specify (among other things) the EJB type, the transaction behavior, references to external resources, the security configuration of the bean, and in the case of CMP beans, the abstract persistence schema, relationships, and EJB QL statements.
EJB components also may require a WebLogic-specific weblogic-ejb-jar.xml descriptor file. This XML descriptor allows you to customize the behavior of the EJB container and map EJB references and environment entries to actual WebLogic Server resources. In WebLogic 8.1, the weblogic-ejb-jar.xml descriptor must be a valid XML document that should include the following DTD reference:[1]
[1] In WebLogic 7.0, the weblogic-ejb-jar.xml descriptor file must use the following DTD reference:
As you will discover in this chapter, this deployment descriptor can be used to configure the pooling, caching, and concurrency behavior of beans, JNDI names of referenced resources, cluster behavior, security principal mappings, and method-level transaction isolation settings. An EJB JAR file also may include a weblogic-cmp-rdbms-jar.xml descriptor file that specifies how the EJB container handles both CMP and CMR fields with other entity beans. Chapter 11 covers WebLogic's brand of CMP in more detail. Refer to Chapter 12 for details on how to create and modify the deployment descriptors.
10.1.6 Compiling Your EJBs
Before you can introduce the EJB JAR to WebLogic, you need to generate the WebLogic-specific container classes for the EJB. In WebLogic 8.1, you can use the appc compiler to perform this task for you; in WebLogic 7.0, you can use the ejbc compiler. Once you've created the EJB JAR, you can deploy it to a server or cluster, either as a standalone EJB application or as an EJB module within an enterprise application.
You also can defer EJB compilation until deployment time. For instance, if you deploy a "raw" EJB JAR, WebLogic will automatically generate the container classes for the EJBs before deploying it. This approach is not recommended in a production environment because if something does go wrong, you will have to resolve compilation errors at deployment time. We recommend that you precompile your EJBs before you deploy the EJB JAR. This also will reduce the number of times that the EJB will be compiled. Deploying a raw EJB to several servers will result in the EJB being compiled on each server separately.
10.1.6.1 The ejbc tool
In WebLogic 7.0, you can use the ejbc compiler to generate and compile the container classes needed by your EJBs. Container classes provide the underlying implementation for the EJBs and remote access between the client stubs and server-side skeleton classes. Here's a summary of what the ejbc tool does:
Here's how you run the ejbc utility:
java weblogic.ejbc [options] <source directory or JAR file> <target directory or JAR file>
The ejbc command accepts the following two arguments:
source
Use this argument to specify the name of the directory or JAR file that contains the compiled EJB classes and XML deployment descriptors.
target
Use this argument to specify the name of the destination directory or JAR file. The original EJB classes and XML descriptors, and the newly generated container classes, will be written to this target.
The ejbc utility provides various options that let you alter the classpath, use a third-party Java compiler, and generate IDL for remote interfaces that are compliant with Orbix 2000 and Visibroker 4.5. The tool also is useful for identifying and correcting errors before you actually deploy the EJB JAR.
10.1.6.2 The appc tool
In WebLogic 8.1, the ejbc tool has been deprecated in favor of the appc tool. The appc compiler is a single tool for compiling and validating an EJB JAR, before it can be made ready for deployment. Not only does it ensure that the EJBs are packaged according to J2EE conventions, but it also validates the deployment descriptors of the EJB JAR and ensures that they conform to the specified DTDs. Use the following syntax to invoke the appc compiler:
java weblogic.appc [options] <source directory or JAR file>
The appc compiler accepts a single argument i.e., the name of the directory or JAR file that holds the compiled EJB classes and deployment descriptors for the EJB module. You also can instruct the compiler to place the original EJB classes and XML descriptors as well as the newly generated container classes in another directory or JAR file. For this, you must use the -output <file> option to specify the name of an alternative directory or JAR:
java weblogic.appc -output c:/myEjb.jar f:/ejb-staging-dir
Chapter 4 explains how to also use the appc tool to generate the IDL for the remote interfaces and to generate the necessary CORBA stubs for your EJBs. Refer to Chapter 12 for more information on how to use the appc compiler.
10.1.6.3 Generating an EJB client JAR
WebLogic can generate an EJB-specific client JAR, which packages all the necessary classes that a client needs to invoke the EJB. This includes the EJB's home and remote interfaces, the primary key class in the case of an entity bean with a composite primary key, and any other classes that may be referenced by these classes. In order to specify a client JAR, you must edit the ejb-jar.xml descriptor file and include the ejb-client-jar element:
StudentEJB ... ejb_studentclient.jar ...
Place the compiled classes and XML descriptors in a staging folder or JAR file, and compile your EJBs for WebLogic Server as described earlier. External clients can then invoke the deployed EJBs, after they include the generated client JAR in their classpath. The EJBs also would be accessible to a web application, once the client JAR has been placed under the WEB-INF/lib folder.
Note that the additional classes are included in the EJB client JAR only if they are not already included in the system CLASSPATH. Thus, to ensure that a client does indeed have access to all the necessary classes, make sure any classes that may be referenced by the EJB's home and remote interfaces and by the primary key class are not specified in the system CLASSPATH when you compile your EJBs.
10.1.7 Referencing J2EE Resources
Earlier in Chapter 5, we saw how an application-specific JDBC data source factory can be made available to all modules within an enterprise application. For instance, an EJB could reference a data source factory from within its local Environment Naming Context (ENC) using the logical name of the JDBC factory:
DataSource ds = (DataSource) ctx.lookup("java:comp/env/mydsfactory"); Connection con = ds.getConnection( );
An EJB can reference other EJBs and resource factories deployed to WebLogic in the same way. These references then are available to the EJB implementation code through its local ENC. The standard ejb-jar.xml descriptor file lets you declare references to other EJBs and resource factories. The weblogic-ejb-jar.xml descriptor file then maps these references to their configured JNDI names. The following portion from the ejb-jar.xml descriptor show how to set up a reference to another EJB:
RegistrationEJB ... ejb/studenthome Entity org.foo.bar.StudentHome org.foo.bar.Student ...
For each EJB reference, you need to declare an ejb-ref element in the ejb-jar.xml file. It specifies the EJB's name, whether it's a session bean or an entity bean, and the names for the home and remote interfaces. Then, in the weblogic-ejb-jar.xml descriptor file, you must specify the JNDI name to which the EJB's home object has been bound:
RegistrationEJB ... ... ejb/studenthome org/foo/bar/StudentHome ...
Similarly, if you need to provide a reference to a configured JDBC data source, you must declare a resource-ref element in the ejb-jar.xml descriptor file. The following portion from the ejb-jar.xml descriptor shows how to set up a reference to a data source:
RegistrationEJB ... jdbc/myds javax.sql.DataSource Container Shareable ...
The resource-ref element includes the resource name, the type of the resource, whether the application or the EJB container is responsible for authenticating access to the resource, and whether the resource is shareable. By default, the resource is considered shareable and the EJB container handles authentication on behalf of the application. After this, you must use the weblogic-ejb-jar.xml descriptor file to map the reference to the JNDI name of the configured JDBC data source:
RegistrationEJB ... jdbc/myds myds ...
Given these settings for the Registration session EJB, any implementation code for the Registration EJB then can look up the Student EJB (or the data source) from its local ENC. For instance, in the case of our session bean, you could perform the lookups from within the ejbCreate method:
public void ejbCreate( ) throws CreateException { try { InitialContext ctx = new InitialContext( ); ds = (DataSource) ctx.lookup("java:comp/env/jdbc/myds"); Object home = ctx.lookup("java:comp/env/ejb/studenthome"); ejbHome = (org.foo.bar.StudentHome) PortableRemoteObject.narrow(home, org.foo.bar.StudentHome.class); } catch (NamingException ene) { throw new CreateException("Failed to look up referenced resource" + ene); } }
10.1.7.1 Referencing application-scoped EJBs
Typically, you will deploy the EJB JARs as modules within an enterprise application. Whenever you deploy an EAR containing multiple EJB modules, WebLogic automatically makes the EJBs available to the local ENC through their EJB names. This means that instead of using the JNDI name, any code within the enterprise application can access the EJB's home object using its ejb-name:
Object home = ctx.lookup("java:comp/env/StudentEJB"); ejbHome = (org.foo.bar.StudentHome) PortableRemoteObject.narrow(home, org.foo.bar.StudentHome.class);
Alternatively, you can use the ejb-link subelement to directly reference another EJB bundled within the same EAR, without explicitly mapping it to the EJB's JNDI name. The following XML fragment shows how the Registration bean can reference the Student entity bean using the ejb-link subelement:
RegistrationEJB ... ejb/studenthome Entity org.foo.bar.StudentHome org.foo.bar.StudentHome ejb_student.jar#StudentEJB ...
Here, we have defined an EJB reference to the Student EJB packaged in the same EAR, using its ejb-name. Notice how we've qualified the ejb-link with the name of the EJB JAR that contains the StudentEJB. This ensures that the reference is unique, especially when multiple EJBs in the EAR file could use the same EJB name. Once you've linked the EJB reference directly to the target EJB, you don't need to specify the target EJB's JNDI name in the weblogic-ejb-jar.xml descriptor. Any implementation code for the Registration EJB can now use the ejb-ref-name to access the StudentEJB home object.
10.1.8 Deploying EJB Components
An EJB component can be deployed either as a standalone EJB application or as a "module" bundled within an enterprise application. Typically, an enterprise application will be packaged as an EAR file, which is a JAR file that packages multiple EJB components and web applications in a single, deployable unit. Each EJB module has an entry in the standard application.xml descriptor file that specifies the associated EJB JAR:
ejb_registration.jar ...
In development mode, you can automatically update an EJB application, simply by overwriting the existing EJB JAR file with a newer version. If the EJB JAR is deployed in exploded format, you can instead trigger its redeployment by "touching" a special empty file, which is named REDEPLOY and is located in the META-INF folder. If the EJB module contains uncompiled EJB classes and interfaces, WebLogic automatically picks up the changes, runs the configured Java compiler over the files, and then invokes the EJB compiler to generate the container classes.
Because the auto-deploy feature is disabled in production mode, you need to manually redeploy the EJB components. WebLogic allows you to refresh EJBs in two ways:
java weblogic.Deployer -adminurl http://adminserver:7001 -username system -password somepassword -name myapp.ear -activate -targets ejb_registration.jar@myserver -source /myapp.ear
Typically, you will invoke the tool from a shell script or an Ant script that automates the build/deployment process.
|
When you update an EJB component, WebLogic marks the classes associated with the EJB as unavailable. The EJB class loader and associated classes are abandoned, and a new EJB class loader is created that loads the modified EJB implementation classes. The next time a client obtains a reference to the EJB, the container uses the new EJB implementation classes. In Chapter 12, we look at how you can create a custom classloader hierarchy and thereby enable an EJB module to be redeployed independently of other components in an enterprise application.
Introduction
Web Applications
Managing the Web Server
Using JNDI and RMI
JDBC
Transactions
J2EE Connectors
JMS
JavaMail
Using EJBs
Using CMP and EJB QL
Packaging and Deployment
Managing Domains
Clustering
Performance, Monitoring, and Tuning
SSL
Security
XML
Web Services
JMX
Logging and Internationalization
SNMP