4 Iterative Development of Enterprise JavaBeans

This chapter describes the general EJB 3.2 implementation process, and provides guidance for how to get an EJB up and running in WebLogic Server.

This chapter includes the following sections:

Overview of the EJB Development Process

This section is a brief overview of the EJB 3.2 development process. It describes the key implementation tasks and associated results.

The following section mostly discusses the EJB 3.2 programming model and points out the differences between the EJB 3.x and EJB 2.x programming model in only a few places. If you are an experienced EJB 2.x programmer and want the full list of differences between the two models, see New Features and Changes in EJB.

Table 4-1 EJB Development Tasks and Results

# Step Description Result

1

Create a Source Directory

Create the directory structure for your Java source files, and optional deployment descriptors.

A directory structure on your local drive.

2

Program the Annotated EJB Class

Create the Java file that implements the interface and includes the EJB 3.2 metadata annotations that describe how your EJB behaves.

.java file.

3

Program the EJB Interface

Create no-interface client views or business interfaces that describe your EJB.

.java file for each interface.

4

Optionally Program Interceptors

Optionally, create the interceptor classes that describe the interceptors that intercept a business method invocation or a life cycle callback event.

.java file for each interceptor class.

5

Optionally Program the EJB Timer Service

Optionally, create timers that schedule callbacks to occur when a timer object expires for timed event.

Either metadata (for automatic timers) and/or bean class changes (for programmatic timers).

6

Programming Access to EJB Clients

Obtain a reference to an EJB through either dependency injection or JNDI lookup.

Metadata (annotations and/or deployment descriptor settings) and/or code changes to the client.

7

Programming and Configuring Transactions

Program container-managed or bean-managed transactions.

Metadata and possibly logic to handle exceptions (retry logic or calls to setRollbackOnly).

8

Compile Java Source

Compile source code.

.class file for each class and interface.

9

Optionally Create and Edit Deployment Descriptors

Optionally create the EJB-specific deployment descriptors, although this step is no longer required when using the EJB 3.2 programming model.

  • ejb-jar.xml,

  • weblogic-ejb-jar.xml, which contains elements that control WebLogic Server-specific features.

10

Packaging EJBs

Package compiled classes and optional deployment descriptors for deployment.

If appropriate, you can leave your files unarchived in an exploded directory.

Archive file (either an EJB JAR or Enterprise Application EAR) or equivalent exploded directory.

11

Deploying EJBs

Target the archive or application directory to desired Managed Server, or a WebLogic Server cluster, in accordance with selected staging mode.

Deployed EJBs are ready to service invocations.

Create a Source Directory

Create a source directory where you will assemble the EJB 3.2 module.

Oracle recommends a split development directory structure, which segregates source and output files in parallel directory structures. For instructions on how to set up a split directory structure and package your EJB 3.2 as an enterprise application archive (EAR), see Overview of the Split Development Directory Environment in Developing Applications for Oracle WebLogic Server.

Directory Structure for Packaging a JAR

If you prefer to package and deploy your EJBs in a JAR file, create a directory for your class files. If you are also using the EJB deployment descriptor (which is optional but supported in the EJB 3.2 programming model), you can package it as META-INF/ejb-jar.xml.

For more information see, Packaging EJBs in a JAR.

Example 4-1 Directory Structure for Packaging a JAR

myEJBjar/
     META-INF/
          ejb-jar.xml
          weblogic-ejb-jar.xml
          weblogic-cmp-jar.xml
     foo.class
     fooBean.class

Directory Structure for Packaging a WAR

EJBs can also be packaged directly in a web application module (WAR) by putting the EJB classes in a subdirectory named WEB-INF/classes or in a JAR file within WEB-INF/lib directory. Optionally, if you are also using the EJB deployment descriptor, you can package it as WEB-INF/ejb-jar.xml.

Note:

EJB 2.1 Entity Beans and EJB 1.1 Entity Beans are not supported within WAR files. These component types must only be packaged in a stand-alone ejb-jar file or an ejb-jar file packaged within an EAR file.

For more information see, Packaging an EJB In a WAR.

Example 4-2 Directory Structure for Packaging a WAR

myEJBwar/
     WEB-INF/
          ejb-jar.xml
          weblogic.xml
          weblogic-ejb-jar.xml
          /classes
               foo.class
               fooServlet.class
               fooBean.class

Program the Annotated EJB Class

The EJB bean class is the main EJB programming artifact. It implements the EJB business interface and contains the EJB metadata annotations that specify semantics and requirements to the EJB container, request container services, and provide structural and configuration information to the application deployer or the container runtime.

In the 3.2 programming model, there is only one required annotation: either @javax.ejb.Stateful, @javax.ejb.Stateless, or @javax.ejb.MessageDriven to specify the type of EJB. Although there are many other annotations you can use to further configure your EJB, these annotations have typical default values so that you are not required to explicitly use the annotation in your bean class unless you want it to behave other than in the default manner. This programming model makes it very easy to program an EJB that exhibits typical behavior.

For additional details and examples of programming the bean class, see Programming the Annotated EJB Class.

Program the EJB Interface

Clients access enterprise beans either through a no-interface view or through a business interface.

Accessing EJBs Using the No-Interface Client View

The EJB 3.2 No-interface local client view type simplifies EJB development by providing local session bean access without requiring a separate local business interface, allowing components to have EJB bean class instances directly injected.

The no-interface view has the same behavior as the EJB 3.0 local view. For example, it supports features such as pass-by-reference calling semantics and transaction, and security propagation. However, a no-interface view does not require a separate interface. That is, all public methods of the bean class are automatically exposed to the caller. By default, any session bean that has an empty implements clause and does not define any other local or remote client views, exposes a no-interface client view.

You can follow these links to explore code examples of a no-interface client view:

For more detailed information about the implementing the no-interface client view, see "Accessing Local Enterprise Beans Using the No-Interface View" in the "Enterprise Beans" chapter of the Java EE 7 Tutorial at http://docs.oracle.com/javaee/7/tutorial/index.html.

Accessing EJBs Using the Business Interface

The EJB 3.2 business interface is a plain Java interface that describes the full signature of all the business methods of the EJB. For example, assume an Account EJB represents a client's checking account; its business interface might include three methods (withdraw, deposit, and balance) that clients can use to manage their bank accounts.

The business interface can extend other interfaces. In the case of message-driven beans, the business interface is typically the message-listener interface that is determined by the messaging type used by the bean, such as javax.jms.MessageListener in the case of JMS. The interface for a session bean has not such defining type; it can be anything that suits your business needs.

Note:

The only requirement for an EJB 3.2 business interface is That it must not extend javax.ejb.EJBObject or javax.ejb.EJBLocalObject, as required in EJB 2.x.

See Example of a Simple Business Interface Stateless EJB and Example of a Simple Stateful EJB for examples of business interfaces implemented by stateless and stateful session beans.

For additional details and examples of specifying the business interface, see Specifying the Business and Other Interfaces.

Business Interface Application Exceptions

When you design the business methods of your EJB, you can define an application exception in the throws clause of a method of the EJB's business interface. An application exception is an exception that you program in your bean class to alert a client of abnormal application-level conditions. For example, a withdraw() method in an Account EJB that represents a bank checking account might throw an application exception if the client tries to withdraw more money than is available in their account.

Application exceptions are different from system exceptions, which are thrown by the EJB container to alert the client of a system-level exception, such as the unavailability of a database management system. You should not report system-level errors in your application exceptions.

Finally, your business methods should not throw the java.rmi.RemoteException, even if the interface is a remote business interface, the bean class is annotated with the @WebService JWS annotation, or the method is annotated with @WebMethod. The only exception is if the business interface extends java.rmi.Remote. If the EJB container encounters problems at the protocol level, the container throws an EJBException which wraps the underlying RemoteException.

Note:

The @WebService and @WebMethod annotations are in the javax.jws package; you use them to specify that your EJB implements a Web Service and that the EJB business will be exposed as public Web Service operations. For details about these annotations and programming Web Services in general, see Developing JAX-WS Web Services for Oracle WebLogic Server.

Using Generics in EJBs

The EJB 3.2 programming model supports the use of generics in the business interface at the class level.

Oracle recommends as a best practice that you first define a super-interface that uses the generics, and then have the actual business interface extend this super-interface with a specific data type.

The following example shows how to do this. First, program the super-interface that uses generics:

  public interface RootI<T> {
    public T getObject();
    public void updateObject(T object);
  }

Then program the actual business interface to extend RootI<T> for a particular data type:

  @Remote
  public interface StatelessI extends RootI<String> { }

Finally, program the actual stateless session bean to implement the business interface; use the specified data type, in this case String, in the implementation of the methods:

  @Stateless
  public class StatelessSample implements StatelessI {
    public String getObject() {
      return null;
    }
    public void updateObject(String object) {
    }
  }

If you define the type variables on the business interface or class, they will be erased. In this case, the EJB application can be deployed successfully only when the bean class parameterizes the business interface with upper bounds of the type parameter and no other generic information. For example, in the following example, the upper bound is Object:

public class StatelessSample implements StatelessI<Object> { 
   public Object getObject() { 
      return null;
   } 
   public void updateObject(Object object) { 
   } 
} 
Serializing and Deserializing Business Objects

Business object serialization and deserialization are supported by the following interfaces, which are implemented by all business objects:

  • weblogic.ejb.spi.BusinessObject

  • weblogic.ejb.spi.BusinessHandle

Use the BusinessObject._WL_getBusinessObjectHandle() method to get the business handle object and serialize the business handle object.

To deserialize a business object, deserialize the business handle object and use the BusinessHandle.getBusinessObject() method to get the business object.

Optionally Program Interceptors

An interceptor is a method that intercepts the invocation of a business method or a life cycle callback event.

You can define an interceptor method within the actual bean class, or you can program an interceptor class (distinct from the bean class itself) and associate it with the bean class using the @javax.ejb.Interceptor annotation.

See Specifying Interceptors for Business Methods or Life Cycle Callback Events for information on programming the bean class to use interceptors.

Optionally Program the EJB Timer Service

WebLogic Server supports the EJB timer service defined in the EJB 3.2 Specification. As per the EJB 3.2 "specification, the EJB Timer Service is a "container-managed service that allows callbacks to be scheduled for time-based events. The container provides a reliable and transactional notification service for timed events. Timer notifications may be scheduled to occur according to a calendar-based schedule, at a specific time, after a specific elapsed duration, or at specific recurring intervals."

The Timer Service is implemented by the EJB container. An enterprise bean accesses this service by means of dependency injection, through the EJBContext interface, or through lookup in the JNDI namespace.

The Timer Service is intended to be used as a coarse-grained timer service. Rather than having a large number of timer objects performing the same task on a unique set of data, Oracle recommends using a small number of timers that perform bulk tasks on the data. For example, assume you have an EJB that represents an employee's expense report. Each expense report must be approved by a manager before it can be processed. You could use one EJB timer to periodically inspect all pending expense reports and send an email to the corresponding manager to remind them to either approve or reject the reports that are waiting for their approval.

Overview of the Timer Service

The timer service provides methods for the programmatic creation and cancellation of timers, as well as for locating the timers that are associated with a bean. Timers can also be created automatically by the container at deployment time based on metadata in the bean class or in the deployment descriptor. Timer objects can be created for stateless session beans, singleton session beans, message-driven beans, and 2.1 entity beans. Timers cannot be created for stateful session beans.

Note:

The calendar-based timer, automatically-created timers, and non-persistent timer functionality is not supported for 2.1 Entity beans.

A timer is created to schedule timed callbacks. The bean class of an enterprise bean that uses the timer service must provide one or more timeout callback methods, as follows:

  • Programmatic Timers – For programmatically-created timers, this method may be a method that is annotated with the Timeout annotation, or the bean may implement the javax.ejb.TimedObject interface. The javax.ejb.TimedObject interface has a single method, the timer callback method ejbTimeout.

  • Automatic Timers – For automatically-created timers, the timeout method may be a method that is annotated with the Schedule annotation.

  • 2.1 Entity Bean Timers – A timer that is created for a 2.1 entity bean is associated with the entity bean's identity. The timeout callback method invocation for a timer that is created for a stateless session bean or a message-driven bean may be called on any bean instance in the pooled state.

Calendar-based EJB Timers

The EJB 31. Timer Service supports calendar-based EJB Timer expressions. The scheduling functionality takes the form of CRON-styled schedule definitions that can be placed on EJB methods, in order to have the methods be automatically invoked according to the defined schedule.

Note:

Calendar-based timers are not supported for EJB 2.x entity beans.

Calendar-based timers can be created programmatically using the two methods in the javax.ejb.TimerService that accept a javax.ejb.ScheduleExpression as an argument. The ScheduleExpression is constructed and populated prior to creating the Timer. For creating automatic calendar-base timers, the javax.ejb.Schedule annotation (and its corresponding ejb-jar.xml element) contains a number of attributes that allow for calendar-based timer expressions to be configured.

For detailed information about the seven attributes in a calendar-based time expression, see "Section 18.2.1, Calendar Based Timer Expressions" in the Enterprise JavaBeans 3.2 Specification (JSR-345) at http://jcp.org/en/jsr/summary?id=345.

Automatically-created EJB Timers

The EJB 3.2 Timer Service supports the automatic creation of a timer based on metadata in the bean class or deployment descriptor. This allows the bean developer to schedule a timer without relying on a bean invocation to programmatically invoke one of the Timer Service timer creation methods. Automatically created timers are created by the container as a result of application deployment.

The javax.ejb.Schedule annotation can be used to automatically create a timer with a particular timeout schedule. This annotation is applied to a method of a bean class (or super-class) that should receive the timer callbacks associated with that schedule. Multiple automatic timers can be applied to a single timeout callback method using the javax.ejb.Schedules annotation.

When the clustered EJB Timer implementation is used, each Schedule annotation corresponds to a single persistent timer, regardless of the number of servers across which the EJB is deployed.

Non-persistent Timers

By default, EJB timers are persistent. A non-persistent timer is a timer whose lifetime is tied to the JVM in which it is created. A non-persistent timer is considered canceled in the event of application shutdown, container crash, or a failure/shutdown of the JVM on which the timer was started.

Note:

Non-persistent timers are not supported for EJB 2.x Entity Beans.

Non-persistent timers can be created programmatically or automatically (using @Schedule or the deployment descriptor).

Automatic non-persistent timers can be specified by setting the persistent attribute of the @Schedule annotation to false. For automatic non-persistent timers, the container creates a new non-persistent timer during application initialization for each JVM across which the container is distributed.

Clustered Versus Local EJB Timer Services

You can configure two types of EJB timer services: clustered or local.

Clustered EJB Timer Services

Clustered EJB timer services provide the following advantages:

  • Better visibility.

    Timers are accessible from any node in a cluster. For example, the javax.ejb.TimerService.getTimers() method returns a complete list of all stateless session or message-driven bean timers in a cluster that were created for the EJB. If you pass the primary key of the entity bean to the getTimers() method, a list of timers for that entity bean are returned.

  • Automatic load balancing and failover.

    Clustered EJB timer services take advantage of the load balancing and failover capabilities of the Job Scheduler.

For information about the configuring a clustered EJB timer service, see Configuring Clustered EJB Timers.

Local EJB Timer Services

Local EJB timer services execute only on the server on which they are created and are visible only to the beans on that server. With a local EJB timer service, you do not have to configure a cluster, database, JDBC data source, or leasing service, as you do for clustered EJB timer services.

You cannot migrate a local EJB timer object from one server to another; timer objects can only be migrated as part of an entire server. If a server that contains EJB timers goes down for any reason, you must restart the server or migrate the entire server in order for the timers to execute.

Caution:

In a clustered environment, the local timer implementation has severe limitations; therefore Oracle recommends not using local timers in a clustered environment. Instead, use the clustered timer implementation in a clustered environment. A deployment-time warning will be thrown when a local timer implementation is configured to be used in a clustered environment.

Configuring Clustered EJB Timers

Note:

To review the advantages of using clustered EJB timers, see Clustered Versus Local EJB Timer Services.

To configure the clustering of EJB timers, perform the following steps:

  1. Ensure that you have configured the following:
    • A clustered domain. See Setting up WebLogic Clusters in Administering Clusters for Oracle WebLogic Server.

    • Features of the Job Scheduler, including:

      • HA database, such as Oracle, DB2, Informix, MySQL, Sybase, or MSSQL.

      • JDBC data source that is mapped to the HA database using the <data-source-for-job-scheduler> element in the config.xml file.

      • Leasing service. By default, database leasing will be used and the JDBC data source defined by the <data-source-for-job-scheduler> element in the config.xml file will be used.

    For more information about configuring the Job Scheduler, see The Timer and Work Manager API in Developing CommonJ Applications for Oracle WebLogic Server.

  2. To enable the clustered EJB timer service, set the timer-implementation element in the weblogic-ejb-jar.xml deployment descriptor to Clustered:
    <timer-implementation>Clustered</timer-implementation>
    

    For more information, see the timer-implementation element description in the weblogic-ejb-jar.xml Deployment Descriptor Reference in Developing Enterprise JavaBeans, Version 2.1, for Oracle WebLogic Server.

Please note the following changes in the behavior of the clustered EJB timer service:

  • The weblogic.ejb.WLTimer* interfaces are not supported with clustered EJB timer services.

  • When creating a new clustered EJB timer using the createTimer() method, you may notice a delay in timeout execution during the initial setup of the timer.

  • The Job Scheduler provides an "at least once" execution guarantee. When a clustered EJB timer expires, the database is not updated until the timer listener callback method completes. If the server were to crash before the database is updated, the timer expiration would be executed twice.

  • Timer configuration options related to the actions to take in the event of failure are not valid for the clustered EJB timer service. These configuration options include: retry delay, maximum number of retry attempts, maximum number of time-outs, and time-out failure actions.

  • The Job Scheduler queries the database every 30 seconds to identify timers that are due to expire. Execution may be delayed for timers with an interval duration less than 30 seconds.

  • Only transactional timers will be retried in the event of failure.

  • Fixed rate scheduling of timer execution is not supported.

Note:

When you migrate a resource group that has not been shut down, the group is multitargeted. However, because clustered EJB timers do not support multitargeting, a clustered EJB timer may not run as expected. To avoid this problem, Oracle recommends that you shut down the resource group before you migrate the group. For more information about live, non-live, targeted, and multitargeted groups, see Using Oracle WebLogic Server Multitenant.

Using Java Programming Interfaces to Program Timer Objects

This section summarizes the Java programming interfaces defined in the EJB 3.2 Specification that you can use to program timers. For detailed information on these interfaces, refer to the EJB 3.2 Specification. This section also provides details about the WebLogic Server-specific timer-related interfaces.

EJB 3.2 Timer-related Programming Interfaces

EJB 3.2 interfaces you can use to program timers are described in the following table.

Table 4-2 EJB 3.2 Timer-related Programming Interfaces

Programming Interface Description

javax.ejb.ScheduleExpression

Create calendar-based EJB Timer expressions.

javax.ejb.Schedule

Automatically create a timer with a particular timeout schedule.

Multiple automatic timers can be applied to a single timeout callback method using the javax.ejb.Schedules annotation.

javax.ejb.TimedObject

Implement for the enterprise bean class of a bean that will be registered with the timer service for timer callbacks. This interface has a single method, ejbTimeout.

EJBContext

Access the timer service using the getTimerService method.

javax.ejb.TimerService

Create new EJB timers or access existing EJB timers for the EJB.

javax.ejb.Timer

Access information about a particular EJB timer.

javax.ejb.TimerHandle

Define a serializable timer handle that can be persisted. Since timers are local objects, a TimerHandle must not be passed through a bean's remote interface or Web service interface.

For more information on EJB 2.1 timer-related programming interfaces, see the EJB 2.1 Specification.

WebLogic Server-specific Timer-related Programming Interfaces

WebLogic Server-specific interfaces you can use to program timers include:

  • weblogic.management.runtime.EJBTimerRuntimeMBean—provides runtime information and administrative functionality for timers from a particular EJBHome. The weblogic.management.runtime.EJBTimerRuntimeMBean interface is shown in Example 4-3.

Example 4-3 weblogic.management.runtime.EJBTimerRuntimeMBean Interface

public interface weblogic.management.runtime.EJBTimerRuntimeMBean {
  public int getTimeoutCount(); // get the number of successful timeout notifications that have been made
  public int getActiveTimerCount(); // get the number of active timers for this EJBHome
  public int getCancelledTimerCount(); // get the number of timers that have been cancelled for this EJBHome
  public int getDisabledTimerCount(); // get the number of timers temporarily disabled for this EJBHome
  public void activateDisabledTimers(); // activate any temporarily disabled timers
}
  • weblogic.ejb.WLTimerService interface—extends the javax.ejb.TimerService interface to allow users to specify WebLogic Server-specific configuration information for a timer. The weblogic.ejb.WLTimerService interface is shown in Example 4-4; for information on the javax.ejb.TimerService, see the EJB 2.1 Specification.

    Note:

    The weblogic.ejb.WLTimerService interface is not supported by the clustered EJB timer service, as described in Configuring Clustered EJB Timers.

Example 4-4 weblogic.ejb.WLTimerService Interface

public interface WLTimerService extends TimerService {
  public Timer createTimer(Date initial, long duration, Serializable info,
    WLTimerInfo wlTimerInfo)
    throws IllegalArgumentException, IllegalStateException, EJBException;
  public Timer createTimer(Date expiration, Serializable info,
    WLTimerInfo wlTimerInfo)
    throws IllegalArgumentException, IllegalStateException, EJBException;
  public Timer createTimer(long initial, long duration, Serializable info
    WLTimerInfo wlTimerInfo)
    throws IllegalArgumentException, IllegalStateException, EJBException;
  public Timer createTimer(long duration, Serializable info,
    WLTimerInfo wlTimerInfo)
    throws IllegalArgumentException, IllegalStateException, EJBException;
}
  • weblogic.ejb.WLTimerInfo interface—used in the weblogic.ejb.WLTimerService interface to pass WebLogic Server-specific configuration information for a timer. The weblogic.ejb.WLTimerInfo method is shown in Example 4-5.

    Note:

    The weblogic.ejb.WLTimerService interface is not supported by the clustered EJB timer service, as described in Configuring Clustered EJB Timers.

Example 4-5 weblogic.ejb.WLTimerInfo Interface

public final interface WLTimerInfo {
  public static int REMOVE_TIMER_ACTION  = 1;
  public static int DISABLE_TIMER_ACTION = 2;
  public static int SKIP_TIMEOUT_ACTION  = 3;
  /**
   * Sets the maximum number of retry attempts that will be
   * performed for this timer.  If all retry attempts
   * are unsuccesful, the timeout failure action will
   * be executed.
   */
  public void setMaxRetryAttempts(int retries);
  public int getMaxRetryAttempts();
  /**
   * Sets the number of milliseconds that should elapse
   * before any retry attempts are made.
   */
  public void setRetryDelay(long millis);
  public long getRetryDelay();
  /**
   * Sets the maximum number of timeouts that can occur
   * for this timer.  After the specified number of
   * timeouts have occurred successfully, the timer
   * will be removed.
   */
  public void setMaxTimeouts(int max);
  public int getMaxTimeouts();
/**
   * Sets the action the container will take when ejbTimeout
   * and all retry attempts fail.  The REMOVE_TIMER_ACTION,
   * DISABLE_TIMER_ACTION, and SKIP_TIMEOUT_ACTION fields
   * of this interface define the possible values.
   */
  public void setTimeoutFailureAction(int action);
  public int getTimeoutFailureAction();
}
  • weblogic.ejb.WLTimer interface—extends the javax.ejb.Timer interface to provide additional information about the current state of the timer. The weblogic.ejb.WLTimer interface is shown in Example 4-6.

    Note:

    The weblogic.ejb.WLTimerService interface is not supported by the clustered EJB timer service, as described in Configuring Clustered EJB Timers.

Example 4-6 weblogic.ejb.WLTimer Interface

public interface WLTimer extends Timer {
  public int getRetryAttemptCount();
  public int getMaximumRetryAttempts();
  public int getCompletedTimeoutCount();
}

Programming Access to EJB Clients

This section provides some guidelines in determining the client view to provide for accessing an enterprise bean.

Remote Clients

As stated in the EJB 3.2 specification, a remote client accesses a session bean through the bean's remote business interface. For a session bean client and component written to the EJB 2.1 and earlier APIs, the remote client accesses the session bean through the session bean's remote home and remote component interfaces.

Note:

The EJB 2.1 and earlier API required that a remote client access the stateful or stateless session bean by means of the session bean's remote home and remote component interfaces. These interfaces remain available for use with EJB 3.x, and are described in Create EJB Classes and Interfaces in Developing Enterprise JavaBeans, Version 2.1, for Oracle WebLogic Server.

The remote client view of an enterprise bean is location independent. A client running in the same JVM as a bean instance uses the same API to access the bean as a client running in a different JVM on the same or different machine.

Local Clients

As stated in the EJB 3.2 specification, a local client accesses a session bean through the bean's local business interface or through a no-interface client view representing all the public methods of the bean class. For a session bean or entity bean client and component written to the EJB 2.1 and earlier APIs, the local client accesses the enterprise bean through the bean's local home and local component interfaces. The container object that implements a local business interface or the no-interface local view is a local Java object.

A local client is a client that is collocated in the same application with the session bean that provides the local client view and which may be tightly coupled to the bean. A local client of a session bean may be another enterprise bean or a Web component. Access to an enterprise bean through the local client view requires the collocation in the same application of both the local client and the enterprise bean that provides the local client view. The local client view therefore does not provide the location transparency provided by the remote client view.

Looking Up EJBs From Clients

The client of an enterprise bean obtains a reference to an instance of an enterprise bean through either dependency injection, using Java programming language annotations, or JNDI lookup, using the Java Naming and Directory Interface syntax to find the enterprise bean instance.

Note:

For instructions on how clients can look up 2.x or earlier enterprise beans using EJB Links, see Using EJB Links in Developing Enterprise JavaBeans, Version 2.1, for Oracle WebLogic Server.

Using Dependency Injection

Dependency injection is when the EJB container automatically supplies (or injects) a bean's variable or setter method with a reference to a resource or another environment entry in the bean's context. Dependency injection is simply an easier-to-program alternative to using the javax.ejb.EJBContext interface or JNDI APIs to look up resources.

You specify dependency injection by annotating a variable or setter method with one of the following annotations, depending on the type of resource you want to inject:

  • @javax.ejb.EJB—Specifies a dependency on another EJB.

  • @javax.annotation.Resource—Specifies a dependency on an external resource, such as a JDBC datasource or a JMS destination or connection factory.

For detailed information, see Injecting Resource Dependency into a Variable or Setter Method.

Using the JNDI Portable Syntax

The Portable Global JNDI naming option in EJB 3.2 provides a number of common, well-known namespaces in which EJB components can be registered and looked up from using the patterns listed in this section. This standardizes how and where EJB components are registered in JNDI, and how they can be looked up and used by applications.

Three JNDI namespaces are used for portable JNDI lookups: java:global, java:module, and java:app.

  • The java:global JNDI namespace is the portable way of finding remote enterprise beans using JNDI lookups. JNDI addresses are of the following form:

    java:global[/application name]/module name/enterprise bean name[/interface name]

    Application name and module name default to the name of the application and module minus the file extension. Application names are required only if the application is packaged within an EAR. The interface name is required only if the enterprise bean implements more than one business interface.

  • The java:module namespace is used to look up local enterprise beans within the same module. JNDI addresses using the java:module namespace are of the following form:

    java:module/enterprise bean name/[interface name]

    The interface name is required only if the enterprise bean implements more than one business interface.

  • The java:app namespace is used to look up local enterprise beans packaged within the same application. That is, the enterprise bean is packaged within an EAR file containing multiple Java EE modules. JNDI addresses using the java:app namespace are of the following form:

    java:app[/module name]/enterprise bean name[/interface name]

    The module name is optional. The interface name is required only if the enterprise bean implements more than one business interface.

For example, if an enterprise bean, MyBean, is packaged within the Web application archive myApp.war, the default module name is myApp. (In this example, the module name could be explicitly configured in the web.xml file.) The portable JNDI name is java:module/MyBean. An equivalent JNDI name using the java:global namespace is java:global/myApp/MyBean.

Customizing JNDI Names

Though global JNDI bindings are registered by default, you can also customize the JNDI names of your EJB client view bindings by using the weblogic.javaee.JNDIName and weblogic.javaee.JNDINames annotations. For more information, see weblogic.javaee.JNDIName and weblogic.javaee.JNDINames.

For EJBs using deployment descriptors, you can specify the custom JNDI bindings in the weblogic-ejb-jar.xml deployment descriptor by using the jndi-binding element. See EJB Deployment Descriptors in Developing Enterprise JavaBeans, Version 2.1, for Oracle WebLogic Server.

Configuring EJBs to Send Requests to a URL

To enable an EJB to open an HttpURLConnection to an external HTTP server using the java.net.URL resource manager connection factory type, specify the URL, or specify an object bound in the JNDI tree that maps to a URL, using either the @Resource annotation in the bean class, or if using deployment descriptors, by using the resource-ref element in ejb-jar.xml and the res-ref-name element in weblogic-ejb-jar.xml.

Specifying an HTTP Resource by URL

When using annotations to specify the URL to which an EJB sends requests:

  1. Annotate a URL field in your bean class with @Resource.

  2. Specify the URL value using the look-up element of @Resource.

When using deployment descriptors to specify the URL to which an EJB sends requests:

  1. In ejb-jar.xml, specify the URL in the <jndi-name> element of the resource-ref element.
  2. In weblogic-ejb-jar.xml, specify the URL in the <jndi-name> element of the resource-description element:
    <resource-description>
        <res-ref-name>url/MyURL</res-ref-name>
        <jndi-name>http://www.rediff.com/</jndi-name>
    </resource-description>
    

    WebLogic Server creates a URL object with the jndi-name provided and binds the object to the java:comp/env.

Specifying an HTTP Resource by Its JNDI Name

When using annotations to specify an object that is bound in JNDI and maps to a URL, instead of specifying a URL:

  1. Annotate a URL field in your bean class with @Resource.

  2. Specify the name by which the URL is bound in JNDI using the look-up element of @Resource.

When using deployment descriptors to specify an object that is bound in JNDI and maps to a URL, instead of specifying a URL:

  1. In ejb-jar.xml, specify the name by which the URL is bound in JNDI in the <jndi-name> element of the resource-ref element.
  2. In weblogic-ejb-jar.xml, specify the name by which the URL is bound in JNDI in the <jndi-name> element of the resource-description element:
    <resource-description>
        <res-ref-name>url/MyURL1</res-ref-name>
        <jndi-name>firstName</jndi-name>
    </resource-description>
    

    where firstName is the object bound to the JNDI tree that maps to the URL. This binding could be done in a startup class. When jndi-name is not a valid URL, WebLogic Server treats it as an object that maps to a URL and is already bound in the JNDI tree, and binds a LinkRef with that jndi-name.

Accessing HTTP Resources from Bean Code

Regardless of how you specified an HTTP resource—by its URL or a JNDI name that maps to the URL—you can access it from EJB code in this way:

URL url = (URL) context.lookup("java:comp/env/url/MyURL");
connection = (HttpURLConnection)url.openConnection();

Configuring Network Communications for an EJB

You can control the attributes of the network connection an EJB uses for communications by configuring a custom network channel and assigning it to the EJB. For information about WebLogic Server network channels and associated configuration instructions see Configure Network Resources in Administering Server Environments for Oracle WebLogic Server. After you configure a custom channel, assign it to an EJB using the network-access-point element in weblogic-ejb-jar.xml.

Programming and Configuring Transactions

The following sections contain guidelines for programming transactions.

Programming Container-Managed Transactions

Container-managed transactions are simpler to program than bean-managed transactions, because they leave the job of demarcation—starting and stopping the transaction—to the EJB container. You configure the desired transaction behaviors using EJB annotations javax.ejb.TransactionAttribute or by using EJB deployment descriptors ejb-jar.xml and weblogic-ejb-jar.xml.

Key programming guidelines for container-managed transactions include:

  • Preserve transaction boundaries—Do not invoke methods that interfere with the transaction boundaries set by the container. Do not use:

    • The commit, setAutoCommit, and rollback methods of java.sql.Connection

    • The getUserTransaction method of javax.ejb.EJBContext

    • Any method of javax.transaction.UserTransaction

  • Roll back transactions explicitly—To cause the container to roll back a container-managed transaction explicitly, invoke the setRollbackOnly method of the EJBContext interface. (If the bean throws a non-application exception, typically an EJBException, the rollback is automatic.)

  • Avoid serialization problems—Many data stores provide limited support for detecting serialization problems, even for a single user connection. In such cases, even with transaction-isolation in weblogic-ejb-jar.xml set to TransactionSerializable, exceptions or rollbacks in the EJB client might occur if contention occurs between clients for the same rows. To avoid such exceptions, you can:

    • Include code in your client application to catch SQL exceptions, and resolve them appropriately; for example, by restarting the transaction.

    • For Oracle databases, use the transaction isolation settings described in isolation-level in the weblogic-ejb-jar.xml Deployment Descriptor Reference appendix in Developing Enterprise JavaBeans, Version 2.1, for Oracle WebLogic Server.

Configuring Automatic Retry of Container-Managed Transactions

In Oracle WebLogic Server, you can specify that, if a business method that has started a transaction fails because of a transaction rollback that is not related to a system exception, the EJB container will start a new transaction and retry the failed method up to a specified number of times. If the method fails for the specified number of retry attempts, the EJB container throws an exception.

Note:

The EJB container does not retry any transactions that fail because of system exception-based errors.

To configure automatic retry of container-managed transactions:

  1. Make sure your bean is a container-managed session or entity bean.

    You can configure automatic retry of container-managed transactions for container-managed session and entity beans only. You cannot configure automatic retry of container-managed transactions for message-driven beans because MDBs do not acknowledge receipt of a message they are processing when the transaction that brackets the receipt of the message is rolled back; messages are automatically retried until they are acknowledged. You also cannot configure automatic retry of container-managed transactions for timer beans because, when a timer bean's ejbTimeout method starts and is rolled back, the timeout is always retried.

  2. Make sure the business methods for which you want to configure automatic retry of transactions are defined in the bean's remote or local interface or as home methods (local home business logic that is not specific to a particular bean instance) in the home interface; the methods must have one of the following container-managed transaction attributes:
    • RequiresNew. If a method's transaction attribute (trans-attribute element in ejb-jar.xml) is RequiresNew, a new transaction is always started prior to the invocation of the method and, if configured, automatic retry of transactions occurs if the transaction fails.

    • Required. If a method's transaction attribute (trans-attribute element in ejb-jar.xml) is Required, the method is retried with a new transaction only if the failed transaction was begun on behalf of the method.

    For more information on:

  3. Make sure the methods for which you want to enable automatic retry of transactions are safe to be re-invoked. A retry of a failed method must yield results that are identical to the results the previous attempt, had it been successful, would have yielded. In particular:
    • If invoking a method initiates a call chain, it must be safe to re-invoke the entire call chain when the method is retried.

    • All of the method's parameters must be safe for reuse; when a method is retried, it is retried with the same parameters that were used to invoke the failed attempt. In general, parameters that are primitives, immutable objects, or are references to read-only objects are safe for reuse. If a parameter is a reference to an object that is to be modified by the method, re-invoking the method must not negatively affect the result of the method call.

    • If the bean that contains the method that is being retried is a stateful session bean, the bean's conversational state must be safe to re-invoke. Since a stateful session bean's state is not transactional and is not restored during a transaction rollback, in order to use the automatic retry of transactions feature, you must first be sure the bean's state is still valid after a rollback.

  4. Specify the methods for which you want the EJB container to automatically retry transactions and the number of retry attempts you want the EJB container to make in the retry-methods-on-rollback element in weblogic-ejb-jar.xml.

    The retry-count sub-element to retry-methods-on-rollback can also be modified via the WebLogic Server Administration Console.

Programming Bean-Managed Transactions

This section contains programming considerations for bean-managed transactions.

  • Demarcate transaction boundaries—To define transaction boundaries in EJB or client code, you must obtain a UserTransaction object and begin a transaction before you obtain a Java Transaction Service (JTS) or JDBC database connection. To obtain the UserTransaction object, use this command:

    ctx.lookup("javax.transaction.UserTransaction");
    

    After obtaining the UserTransaction object, specify transaction boundaries with tx.begin(), tx.commit(), tx.rollback().

    If you start a transaction after obtaining a database connection, the connection has no relationship to the new transaction, and there are no semantics to "enlist" the connection in a subsequent transaction context. If a JTS connection is not associated with a transaction context, it operates similarly to a standard JDBC connection that has autocommit equal to true, and updates are automatically committed to the data store.

    Once you create a database connection within a transaction context, that connection is reserved until the transaction commits or rolls back. To optimize performance and throughput, ensure that transactions complete quickly, so that the database connection can be released and made available to other client requests.

    Note:

    You can associate only a single database connection with an active transaction context.

  • Setting transaction isolation level—For bean-managed transactions, you define isolation level in the bean code. Allowable isolation levels are defined on the java.sql.Connection interface. For information on isolation level behaviors, see isolation-level in the weblogic-ejb-jar.xml Deployment Descriptor Reference appendix in Developing Enterprise JavaBeans, Version 2.1, for Oracle WebLogic Server.

    See Example 4-7 for a code sample.

Example 4-7 Setting Transaction Isolation Level in BMT

import javax.transaction.Transaction;
import java.sql.Connection
import weblogic.transaction.TxHelper:
import weblogic.transaction.Transaction;
import weblogic.transaction.TxConstants;
User Transaction tx = (UserTransaction)
ctx.lookup("javax.transaction.UserTransaction");
//Begin user transaction
    tx.begin();
//Set transaction isolation level to TransactionReadCommitted
Transaction tx = TxHelper.getTransaction();
    tx.setProperty (TxConstants.ISOLATION_LEVEL, new Integer
    (Connection.TransactionReadCommitted));
//perform transaction work 
    tx.commit();
  • Avoid restricted methods—Do not invoke the getRollbackOnly and setRollbackOnly methods of the EJBContext interface in bean-managed transactions. These methods should be used only in container-managed transactions. For bean-managed transactions, invoke the getStatus and rollback methods of the UserTransaction interface.

  • Use one connection per active transaction context—You can associate only a single database connection with an active transaction context.

Programming Transactions That Are Distributed Across EJBs

This section describes two approaches for distributing a transaction across multiple beans, which may reside on multiple server instances.

Calling multiple EJBs from a client's transaction context

The code fragment below is from a client application that obtains a UserTransaction object and uses it to begin and commit a transaction. The client invokes two EJBs within the context of the transaction.

import javax.transaction.*;
...
u = (UserTransaction) jndiContext.lookup("javax.transaction.UserTransaction");
u.begin();
account1.withdraw(100);
account2.deposit(100);
u.commit();
...

The updates performed by the account1 and account2 beans occur within the context of a single UserTransaction. The EJBs commit or roll back together, as a logical unit, whether the beans reside on the same server instance, different server instances, or a WebLogic Server cluster.

All EJBs called from a single transaction context must support the client transaction—each beans' trans-attribute element in ejb-jar.xml must be set to Required, Supports, or Mandatory.

Using an EJB "Wrapper” to Encapsulate a Cross-EJB Transaction

You can use a wrapper EJB that encapsulates a transaction. The client calls the wrapper EJB to perform an action such as a bank transfer, and the wrapper starts a new transaction and invokes one or more EJBs to do the work of the transaction.

The wrapper EJB can explicitly obtain a transaction context before invoking other EJBs, or WebLogic Server can automatically create a new transaction context, if the wrapper's trans-attribute element in ejb-jar.xml is set to Required or RequiresNew.

All EJBs invoked by the wrapper EJB must support the wrapper EJB's transaction context— their trans-attribute elements must be set to Required, Supports, or Mandatory.

Compile Java Source

Once you have written the Java source code for your EJB bean class and optional interceptor class, you must compile it into class files, typically using the standard Java compiler. The resulting class files can then be packaged into a target module for deployment. Typical tools to compile include:

  • javac —The javac compiler provided with the Java SE SDK provides Java compilation capabilities. See http://www.oracle.com/technetwork/java/javase/documentation/index.html.

  • weblogic.appc—To reduce deployment time, use the weblogic.appc Java class (or its equivalent Ant task wlappc) to pre-compile a deployable archive file, (WAR, JAR, or EAR). Precompiling with weblogic.appc generates certain helper classes and performs validation checks to ensure your application is compliant with the current Java EE specifications. See Building Modules and Applications Using wlappc in Developing Applications for Oracle WebLogic Server.

  • wlcompile Ant task—Invokes the javac compiler to compile your application's Java components in a split development directory structure. See Compiling Applications Using wlcompile in Developing Applications for Oracle WebLogic Server.

Optionally Create and Edit Deployment Descriptors

An important aspect of the EJB 3.x programming model was the introduction of metadata annotations. Annotations simplify the EJB development process by allowing a developer to specify within the Java class itself how the bean behaves in the container, requests for dependency injection, and so on. Annotations are an alternative to deployment descriptors that were required by older versions (2.x and earlier) of EJB.

However, EJB 3.2 fully supports the use of deployment descriptors, even though the standard Java EE 6 ones are not required. For example, you may prefer to use the old 2.x programming model, or might want to allow further customizing of the EJB at a later development or deployment stage; in these cases you can create the standard deployment descriptors in addition to, or instead of, the metadata annotations.

Deployment descriptor elements always override their annotation counterparts. For example, if you specify the @javax.ejb.TransactionManagement(BEAN) annotation in your bean class, but then create an ejb-jar.xml deployment descriptor for the EJB and set the <transaction-type> element to container, then the deployment descriptor value takes precedence and the EJB uses container-managed transaction demarcation.

Note:

This version of EJB 3.2 also supports all 2.x WebLogic-specific EJB features. However, the features that are configured in the weblogic-ejb-jar.xml or weblogic-cmp-rdbms-jar.xml deployment descriptor files must continue to be configured that way for this release of EJB 3.2 because currently they do not have any annotation equivalent.

The 2.x version of Developing Enterprise JavaBeans, Version 2.1, for Oracle WebLogic Server provides detailed information about creating and editing EJB deployment descriptors, both the Java EE standard and WebLogic-specific ones. In particular, see the following sections:

Packaging EJBs

Oracle recommends that you package EJBs as part of an enterprise application. See Deploying and Packaging from a Split Development Directory in Developing Applications for Oracle WebLogic Server.

However, EJB 3.2 simplifies packaging by providing the ability to place EJB components directly inside of Web application archive (WAR) files, removing the need to produce separate archives to store the Web and EJB components and combine them together in an enterprise application archive (EAR) file.

Packaging EJBs in a JAR

WebLogic Server supports the use of ejb-client.jar files for packaging the EJB classes that a programmatic client in a different application requires to access the EJB.

Specify the name of the client JAR in the ejb-client-jar element of the bean's ejb-jar.xml file. When you run the appc compiler, a JAR file with the classes required to access the EJB is generated.

Make the client JAR available to the remote client. For Web applications, put the ejb-client.jar in the /lib directory. For non-Web clients, include ejb-client.jar in the client's classpath.

Note:

WebLogic Server classloading behavior varies, depending on whether the client is stand-alone. Stand-alone clients with access to the ejb-client.jar can load the necessary classes over the network. However, for security reasons, programmatic clients running in a server instance cannot load classes over the network.

Packaging an EJB In a WAR

EJB 3.2 has removed the restriction that enterprise bean classes must be packaged in an ejb-jar file. Therefore, EJB classes can be packaged directly inside a Web application archive (WAR) using the same packaging guidelines that apply to Web application classes. Simply put your EJB classes in the WEB-INF/classes directory or in a JAR file within WEB-INF/lib directory. Optionally, if you are also using the EJB deployment descriptor, you can package it as WEB-INF/ejb-jar.xml. When you run the appc compiler, a WAR file with the classes required to access the EJB components is generated.

In a WAR file there is a single component naming environment shared between all the components (web, enterprise bean, etc.) defined by the module. Each enterprise bean defined by the WAR file shares this single component environment namespace with all other enterprise beans defined by the WAR file and with all other web components defined by the WAR file.

Enterprise beans (and any related classes) packaged in a WAR file have the same class loading requirements as other non-enterprise bean classes packaged in a WAR file. This means, for example, that a servlet packaged within a WAR file is guaranteed to have visibility to an enterprise bean component packaged within the same WAR file, and vice versa.

Caution:

EJB 2.1 Entity Beans and EJB 1.1 Entity Beans are not supported within WAR files. These component types must only be packaged in a stand-alone ejb-jar file or an ejb-jar file packaged within an EAR file. Applications that violate this restriction will fail to deploy.

There is an example of using the simplified WAR packaging method bundled in the WebLogic Server distribution kit. See EJB 3.1: Example of Simplified No-interface Programming and Packaging in a WAR File.

Deploying EJBs

Deploying an EJB enables WebLogic Server to serve the components of an EJB to clients. You can deploy an EJB using one of several procedures, depending on your environment and whether or not your EJB is in production.

For general instructions on deploying WebLogic Server applications and modules, including EJBs, see Deploying Applications to Oracle WebLogic Server. For EJB-specific deployment issues and procedures, see Deploying Standalone EJBs as Part of an Enterprise Application. and Deploying EJBs as Part of an Web Application.

For more information about deploying an EJB created with the 2.x programming model, see Deployment Guidelines For Enterprise JavaBeans in the Developing Enterprise JavaBeans, Version 2.1, for Oracle WebLogic Server guide, which concentrates on the 2.x programming model.