2.3. Enterprise JavaBeans (EJB)

EJB (Enterprise JavaBeans) is a standard architecture of an environment for hosting server tiers of enterprise component applications. The EJB standard has evolved through several major revisions, which, besides introducing particular features, have also included changing the programming interface due to the introduction of language annotations. The text in this section deals mostly with the latest version.

An EJB application consists of components called enterprise beans that reside in a container. The beans implement the business logic of the application, the container provides the beans with standard services including lifecycle, dependency management, persistency, transactions, and makes the beans accessible to the clients.

Beans come in three distinct types, namely session objects, entity objects and message driven objects. The session objects are further split into stateless, stateful and singleton variants. Each type is tailored to fill a specific role in a component application.

The dependency management can use the CDI (Contexts and Dependency Injection) framework. The framework defines scopes that associate beans with particular execution context. An execution context is responsible for obtaining contextual instances of beans, this typically involves creating instances and looking up created instances.

EJB Architecture

Containers.  Environment providing services to enterprise application objects

  • Lifecycle management (creating and deleting instances)

  • Dependency management (resource and dependency injection)

  • Persistence and transactions

  • ...

Enterprise Beans.  Enterprise application objects managed by container

Stateful session bean

an object that lives within user session scope, state survives method invocation

Stateless session bean

an object that lives within user session scope, state only within method invocation

Singleton session bean

a singleton application object

Entity bean

an object representing persistent database state

Message driven bean

an object that handles messages, state only within message handling

Scopes and Contexts. 

public interface Context {
    public Class <? extends Annotation> getScope ();
    public <T> T get (Contextual <T> bean);
    public <T> T get (Contextual <T> bean, CreationalContext <T> creationalContext);
    ...
}
@Dependent

instance bound to single injection point

@RequestScoped

context associated with single method invocation or request handling

@SessionScoped

context associated with an HTTP session

@ApplicationScoped

context associated with application execution

@ConversationScoped

context associated with explicitly delimited UI interaction

2.3.1. Session Objects

Stateful Session Bean Example

@Stateful public class ASessionBean implements ABusinessInterface {

    // Injected reference to standard session context object
    @Resource public SessionContext sessionContext;

    // Method that is called after construction or activation
    @PostConstruct @PostActivate
    public void myInitMethod () { ... }

    // Method that is called before passivation or destruction
    @PreDestroy @PrePassivate
    public void myDoneMethod () { ... }

    // Some business methods ...
    public void myMethodOne (int iArgument) { ... }
    public int myMethodTwo (Object oArgument) { ... }

    // Business method with asynchronous interface
    @Asynchronous public Future<String> myAsynchronousMethod (String sArgument) { ... }

    // Business method that removes the bean instance
    @Remove public void myRemovalMethod () { ... }

    // Interceptor method that can also be in separate interceptor class
    @AroundInvoke
    public Object myInterceptor (InvocationContext inv)
    throws Exception {
        ...
        Object result = inv.proceed ();
        ...
        return (result);
    }
}
  • method invocations serialized by the container

  • asynchronous method invocations handled by the container

  • business interface can be accessed both locally and remotely

  • references obtained through dependency injection or JNDI lookup

Client life cycle view. 

  • accessible when reference first obtained

  • removed through explicit removal method

Container life cycle view. 

  • instance may be passivated and activated

Singleton Session Bean Example

@Startup @Singleton public class ASingletonBean {

    // Injected reference to JNDI resource
    @Resource (lookup = "java:comp/env/jdbc/SomeDataSource") DataSource dataSource;

    // Method that is called after construction
    @PostConstruct
    public void myInitMethod () { ... }

    // Method that is called before destruction
    @PreDestroy
    public void myDoneMethod () { ... }

    // Some business methods ...
    public synchronized void myMethodOne (int iArgument) { ... }
    public synchronized int myMethodTwo (Object oArgument) { ... }
}
  • concurrent method invocations possible

Container life cycle view. 

  • construction timing determined by container

  • eager construction can be requested through annotation

EJB Sessions and CDI Sessions

Unless explicitly disabled, each EJB session bean instance is bound to some CDI context. The default scope is @Dependent, which ties the EJB session bean instance lifecycle to the lifecycle of the injection point. An EJB session bean is therefore not necessarily associated with CDI session scope.

2.3.2. Message Driven Objects

Message Driven Bean Example

@MessageDriven (activationConfig = {
    @ActivationConfigProperty (
        propertyName = "destinationType",
        propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty (
        propertyName = "destinationLookup",
        propertyValue = "jms/SomeQueue")
})
public class AMessageBean implements MessageListener {

    public AMessageBean () { ... }

    @Override public void onMessage (Message aMessage) { ... }

    ...
}
  • method invocations serialized by the container

  • multiple instances can be created by the container

  • message delivery order between instances is not defined

2.3.3. Entity Objects

Field Based Entity Bean Class Example

@Entity public class AnEntity {

    // With field based access fields are persistent by default
    private int someField;
    private String someOtherField;

    // Relationships among entities must be annotated
    @OneToMany private Collection <AnotherEntity> relatedEntities;

    // Every entity must have a primary key
    @Id private long aKeyField;

    // Field that is not persistent
    @Transient private String aTransientString;

    // Version field for optimistic concurrency
    @Version private long version = 0L;

    // Obligatory constructor with no arguments
    public AnEntity () { ... }

    // Additional business methods ...
    public void myMethodOne (int iArgument) { ... }
    public int myMethodTwo (Object oArgument) { ... }
}

Property Based Entity Bean Class Example

@Entity public class AnEntity {

    // With property based access fields are not persistent themselves
    private int someTransientField;
    private String someOtherTransientField;

    // Relationships among entities must be annotated
    private Collection <AnotherEntity> relatedEntities;
    @OneToMany public Collection <AnotherEntity> getRelatedEntities () {
        return (relatedEntities);
    }
    public void setRelatedEntities (Collection <AnotherEntity> entityCollection) {
        relatedEntities = entityCollection;
    }

    // Getter and setter methods for primary key
    private long aKeyField;
    @Id Long getAKeyField () { return (aKeyField); }
    public void setAKeyField (Long aKeyField) { this.aKeyField = aKeyField; }

    // Obligatory constructor with no arguments
    public AnEntity () { ... }

    // Additional business methods ...
    public void myMethodOne (int iArgument) { ... }
    public int myMethodTwo (Object oArgument) { ... }
}

Entity Manager Interface

public interface EntityManager {

    void persist (Object entity);
    void refresh (Object entity);
    void remove (Object entity);

    void detach (Object entity);
    <T> T merge (T entity);

    void lock (Object entity, LockModeType lockMode);

    // Find by primary key
    <T> T find (Class <T> entityClass, Object primaryKey);

    // Find by primary key and return lazy reference
    <T> T getReference (Class <T> entityClass, Object primaryKey);

    // Clear persistence context and detach all entities
    void clear ();

    // Check whether persistence context contains managed entity
    boolean contains (Object entity);

    // Synchronize persistence context with database
    // Flush mode governs automatic synchronization
    // upon query execution or upon commit
    void flush ();
    FlushModeType getFlushMode ();
    void setFlushMode (FlushModeType flushMode);

    Query createQuery (String ejbqlString);
    Query createNamedQuery (String name);
    Query createNativeQuery (String sqlString);
    ...
}

Query Interface

public interface Query {

    // Execute a query that returns a result list
    List getResultList ();
    // Execute a query that returns a single result
    Object getSingleResult();
    // Execute an update query
    int executeUpdate ();

    // Methods used to fetch results step by step
    Query setMaxResults (int maxResult);
    Query setFirstResult (int startPosition);

    // Bind a parameter in a query
    Query setParameter (String name, Object value);
    Query setParameter (String name, Date value, TemporalType temporalType);
    Query setParameter (String name, Calendar value, TemporalType temporalType);
    Query setParameter (int position, Object value);
    Query setParameter (int position, Date value, TemporalType temporalType);
    Query setParameter (int position, Calendar value, TemporalType temporalType);
}

2.3.4. Transactions

The flat transaction model is supported. Transactions are demarcated either by the beans or by the container. When bean managed transaction demarcation is used, the individual methods of a bean can explicitly begin and commit or rollback a transaction. When container managed transaction demarcation is used, the individual methods of a bean can use transaction attributes, specified either in the method annotations or in the deployment descriptor. The transaction attributes tell the container how to demarcate the transactions.

Transaction Annotations

@Stateful @TransactionManagement (BEAN) public class SomeBeanClass implements SomeBeanInterface {
    @Resource javax.Transaction.UserTransaction transaction;

    public void myMethodOne () {
        transaction.begin ();
        ...
    }

    public void myMethodTwo () {
        ...
        transaction.commit ();
    }
}

@Stateless public class SomeBeanClass implements SomeBeanInterface {
    @TransactionAttribute (REQUIRED) public void myMethod () {
        ...
    }
}
BEAN

bean demarcated transactions

NEVER

transaction must not be active or exception is thrown

MANDATORY

transaction must be active or exception is thrown

SUPPORTS

no specific demarcation performed by the container

NOT_SUPPORTED

active transaction suspended during call

REQUIRED

active transaction used or new transaction started during call

REQUIRES_NEW

active transaction suspended and new transaction started during call

The state of a session bean is not a transactional resource and therefore is not influenced by transaction commit or rollback. A session bean can implement the SessionSynchronization interface to receive the afterBegin, beforeCompletion, afterCompletion notifications. These can be used to commit or rollback the state of the bean explicitly.

2.3.5. References

  1. JSR 345: Enterprise JavaBeans 3.2. http://jcp.org/en/jsr/detail?id=345

  2. JSR 346: Contexts and Dependency Injection for Java EE 1.2. http://jcp.org/en/jsr/detail?id=346

  3. JSR 338: Java Persistence 2.2. http://jcp.org/en/jsr/detail?id=338