Enterprise JavaBeans™ (EJB)


Creative Commons License
This -Enterprise JavaBeans™- (EJB) tutorial is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License
Preamble
This tutorial on the Enterprise JavaBeans™ (EJB) component model is based on the Java Enterprise Edition (Java EE) 8 API (Application Programming Interface) and EJB version 3.2. Java EE 8 tutorial is here… Please take into account that very last EJB constructs will not work in old EJB versions.
Case studies are provided as Maven/NetBeans projects; they have also been tested by means of this Integrated Development Environment (IDE).
What is Java Enterprise Edition (Java EE)?

Java EE technologies

Java EE products (Java EE application servers)

Java EE challengers: Django, Drupal, .NET, Spring, Node.js

Java Application Model is here

Java EE 8 API (here)

EJB history
EJB overview

Principles

Characteristics

Benefits

EJB types
EJB metamodel

Implementation class

In the UML metamodel above, one shows that an EJB is embodied by one and only one Java implementation class (1..1 cardinality). By default, the EJB name is the name of that class. Otherwise:
@javax.ejb.Stateful(mappedName = "My_terminal", name = "Railcar_control_system_terminal")
public class TerminalBean implements Terminal {
    @javax.annotation.Resource
    private javax.ejb.SessionContext _ejb_context = null;
    Terminal _self = null;
    …
        _self = _ejb_context.getBusinessObject(Terminal.class);
    …
Stateless Session Beans

Key features

Creation and deletion

Transaction management

Design patterns

Example(s)

@javax.ejb.Remote
public interface Customer_managementRemote { // Business methods…

@javax.ejb.Stateless(mappedName = "Customer_management+", name = "Customer_management")
// @javax.ejb.Remote({Customer_managementRemote.class}) // Alternative to using '@javax.ejb.Remote' above
public class Customer_managementBean implements Customer_managementRemote { … 
Singleton Session Beans

Key features

Creation and deletion

Transaction management

Design patterns

Other features

Example(s)

Stateful Session Beans

Key features

Creation and deletion

Transaction management

Design patterns

Example(s)

Message-Driven Beans

Key features

Creation and deletion

Transaction management

Design patterns

Example(s)

Entity Beans

Key features

Creation and deletion

Additional information on Entity Beans requires a survey of the JPA technology (here)

Transaction management

Design patterns

Example(s)

See here
The lifecycles of Enterprise Beans

Lifecycle management

Passivation and activation

Because resources on Java EE application servers decrease performance, developers must take care of releasing these resources when unused. This may occur when beans are destroyed. This may also occur when beans, like Stateful Session Beans, are passivated. This example shows how to optimally handle a naming context:
private javax.naming.Context _jndi_context;
…
@javax.ejb.PrePassivate
public void passivate() {
    if (_jndi_context != null) _jndi_context.close(); // This code may raise an exception if the resource has been obtained through dependency injection
    _jndi_context = null; // Safer in case of dependency injection  
}
@javax.ejb.PostActivate
public void activate() {
    _jndi_context = new javax.naming.InitialContext(); 
}
Note: in general, resources acquired by dependency injection must not be managed by developers. In other words, the best solution when releasing such resources is to assign null to the variable embodying the resource.
The notion of EJB “container”
An EJB container is a kind of controller. Effectively, a container is an instance of a Java class generated by the application server at deployment time. This class mixes the Java code released by the EJB's developer with the configuration attribute values assigned by this developer to its EJB. For example, an EJB container opens and closes transactions (CMT mode) on the behalf on the EJB, which delegates this charge to its container. For various reasons, EJBs must sometimes access to their execution context materialized by their container in order to access resources/facilities. As an illustration, the BMT mode requires the access to the current transaction (example).

Interacting with a container (a.k.a. execution context)

In EJB ver. 2.x, one may, for instance, access to the execution context of a session bean instance as follows:
public class X_bean implements SessionBean {
    private SessionContext _ejb_context;
    public void setSessionContext(SessionContex ejb_context) {
        _ejb_context = ejb_context;
    }
    …
The access to the session bean itself (then avoiding this) is as follows:
X_remote x_remote = _ejb_context.getEJBObject(); // 'X_remote' is a Java interface that is declared in a XML file as the remote interface of 'X_bean' 
In EJB ver. 3.x, one accesses to the execution context of a session bean instance through dependency injection (example here).
EJB dependencies
Dependencies are links at runtime so that EJBs are able to interact. Dependencies are also concerned by links between software components and services on one side and, resources (databases, JMS queues/topics…) on another side.
From Java 5, resource injection (or dependency injection) is a key mechanism to setup dependencies between EJBs. From Java 6, the Context and Dependency Injection (CDI) mechanism is a more powerful mechanism. Historically, the EJB technology uses the Java Naming and Directory Interface (JNDI) technology to dynamically create references between EJBs. 

Dependency design patterns

Resource dependency management

Local, remote or no interface at all?

The case of home interfaces being local or remote

Local or remote home interfaces are a concept from older EJB versions, prior to 3.x especially. However, they remain useful in certain cases, namely when one want to initialize Session Beans with specific values at creation time. For that, the javax.ejb.Init annotation may be used.

@javax.ejb.Remote annotation

EJBs are located (packaged) in an EJB module. An EJB module is a unit of deployment. An instance of an EJB of type A in an EJB module can access to an instance of an EJB of type B in another EJB module only if and only if B is annotated with @javax.ejb.Remote. @javax.ejb.Remote has to be used sparingly. It is especially useful when one distributes EJB modules to different Java EE VMs (i.e., Java EE application server running instances).
Concurrency

From EJB 3.x, it exists two major mechanisms to deal with concurrency, more precisely, to control the concurrent access to a component. These are:

@javax.ejb.Remote({Obelix.class})
@javax.ejb.Stateless(mappedName = "ejb/Obelix")
public class Obelix_implementation implements Obelix {

    @javax.ejb.Asynchronous // The result is returned to the enterprise bean container, not directly to the client component...
    @Override
    public java.util.concurrent.Future<String> complain() {
        return new javax.ejb.AsyncResult<>("Arrrrrgggglllll");
    }

    @Override
    public String strength() {
        return "I'm really the strongest... ";
    }
}
@javax.ejb.EJB(mappedName = "ejb/Obelix", lookup = "ejb/Obelix")
Obelix o = null;

@Override
public void strength() {
    java.util.concurrent.Future<String> result = o.complain();
    try {
        System.out.println(o.strength() + (result.isDone() ? result.get() : "not yet available, operation canceled: " + result.cancel(false)));
    } catch (InterruptedException | java.util.concurrent.ExecutionException ex) {
        java.util.logging.Logger.getLogger(Asterix.class.getSimpleName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
}
Reentrance
EJBs are by default not reentrant. This means that an EJB involved in a business method cannot receive at the same time a request from elsewhere demanding the execution of the same, or another offered, business method. Reentrance is firstly linked to transactions. If the executing business method is configured such that it is included within a transaction, calling at the same time the EJB is incompatible with the ongoing transaction, which handles the EJB as an exclusive resource. Secondly, reentrance is also not possible even if the transaction mode is set to BMT (@javax.ejb.TransactionManagement(javax.ejb.TransactionManagementType.BEAN)) or is not supported (@javax.ejb.TransactionAttribute(javax.ejb.TransactionAttributeType.NOT_SUPPORTED)). In this case, no transaction is in progress but the EJB is nevertheless active for the execution duration of a given business method.
Reentrance is mainly concerned with Stateful Session Beans because references to other EJBs do not require to be kept. Reentrance issues have been better addressed in EJB ver 3.x with the arrival of Singleton Session Beans.
Transaction management

Key features

Container-Managed Transaction (CMT)

@javax.ejb.Stateful
public class TerminalBean implements Terminal {
    @javax.ejb.TransactionAttribute(javax.ejb.TransactionAttributeType.NOT_SUPPORTED)
    public String get_name() {
        …
    …
Containers roll back transactions in case of "system" failures, namely when a javax.ejb.EJBException is raised. However, there are some tricky cases when such an exception is not raised. At the same time, one wants to roll back the transaction because of a local business dysfunction, which is not captured by the container. In this specific case, one rolls back the current transaction while the CMT mode is active:
@javax.annotation.Resource
private javax.ejb.SessionContext _ejb_context = null;
…
assert(_ejb_context != null);
javax.transaction.UserTransaction ut = _ejb_context.getUserTransaction();
…
if(/* some test */) ut.setRollbackOnly();

Bean-Managed Transaction (BMT)

In this case, the developer must setup the bean so that it may benefit from the BMT status:
@javax.ejb.Stateful
@javax.ejb.TransactionManagement(javax.ejb.TransactionManagementType.BEAN)
public class RailcarBean implements Railcar { …
Next, she/he must catch the ongoing transaction, start it, stop it through the COMMIT or ROLLBACK functions:
@javax.annotation.Resource
private javax.ejb.SessionContext _ejb_context = null;
…
assert(_ejb_context != null);
javax.transaction.UserTransaction ut = _ejb_context.getUserTransaction();
ut.begin();
…
if(/* some test */) ut.commit();
else ut.rollback();

Transactions in Message-Driven Beans

Message consumption is associated with an acknowledgement mechanism. Message acknowledgement is automatic unless specific settings. By default, acknowledgment leads to COMMIT while other situations lead to ROLLBACK (e.g., failure within onMessage).

Fine-grain transaction control

There is a support for managing transactions with higher accuracy (CMT Stateful Session Beans only), namely when transactions are to be started, are to be completed and have just completed. The javax.ejb.SessionSynchronization interface is devoted to this job.
Configuration
The deep nature of EJBs is the possibility of configuring deployment values. These values are that of parameters, which are interpretable by a Java EE application server. The latter transforms the developer's values into code in order to match to the execution environments characteristics, constraints, etc. Application server administration allows the introduction of homemade parameters but, it is outside the scope of this tutorial. Configuration preferably occurs through XML files (EJB 2.x and older versions) or annotations (EJB 3.x). The last approach does not exclude the utilization of XML files in tricky cases. The core configuration file is the ejb-jar.xml file. So, for example, in aged EJB versions (2.x), transaction attributes may be setup in ejb-jar.xml  as follows (one declares that all (*) business methods of My_bean have the RequiresNew transaction attribute):
<ejb-jar …> <!--EJB ver. 2.x--> 
    …
    <assembly-descriptor>
        …
        <container-transaction>
            <method>
                <ejb-name>My_bean</ejb-name>
                <method-name>*</method-name>
            </method>
            <trans-attribute>RequiresNew</trans-attribute>
        </container-transaction>
    </assembly-descriptor>
</ejb-jar>
There are some other important configurations files like persistence.xml (JPA) or glassfish-resources.xml. The latter is a proprietary file of the Glassfish Java EE application server. Any configured value within this file is not portable across application servers. For example, one may force Glassfish to create no more than 1 instance of a given Message-Driven Bean with <max-pool-size>1</max-pool-size>.

EJB dependencies in ejb-jar.xml file

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         version="3.2"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_3_2.xsd"> <!--EJB ver. 3.x-->
    <enterprise-beans>
        <session>
            <ejb-name>My_Asterix</ejb-name>
            <business-remote>Asterix.Asterix</business-remote>
            <ejb-class>Asterix.Asterix_implementation</ejb-class>
            <session-type>Stateless</session-type>
            <transaction-type>Container</transaction-type>
            <ejb-ref>
                <ejb-ref-name>ejb/Obelix</ejb-ref-name>
                <ejb-ref-type>Session</ejb-ref-type>
                <remote>Obelix.Obelix</remote>
            </ejb-ref>
        </session>
    </enterprise-beans>
</ejb-jar>
Packaging
EJB applications are packaged in EJB modules or in EJB applications (.ear or .jar files). Files including source files and configuration data must be located in precise directories with a special tree structure. For example:
Security
Security features can be setup at design to be experienced at runtime.
Advanced Features

Service computing in EJB

The big picture: the Java EE platform itself provides "technical" services as provided by any middleware. The major Java EE services are transaction management, security, performance (load balancing), persistence, naming, messaging… Most of them often come from the Java EE sublayer. As an illustration, practically, the Glassfish Java EE application server may be built on the top of CORBA that itself supports technical services: COS naming, CORBA Object Transaction Service (OTS)… OSGi is another candidate for Java EE application server implementation. In EJB, there are also business services that are the primary way of modularizing applications through the sharing of these software components among several enterprise applications. Endowing these business services with Internet interoperability leads to giving the status of Web services to Stateless Sessions Beans.

Support for Web services

Stateless Session Beans (including singletons) annotated with @javax.ejb.WebService can be accessed as a Web service (example here).

Timer service

For reliability reasons, the Java SE API for timers (i.e., java.util.Timer and java.util.TimerTask…) has to be avoided in EJB applications because of distribution especially across Java VMs. Moreover, since Stateful Session Beans can be passivated, timer services are not allowed for this kind of EJBs. This book (§ 8.5.6) briefly explains how to implement timer services in Stateful Session Beans. Otherwise, a concise example of using timer services in EJBs may be found here

CDI

The beans.xml file is dedicated to CDI. It can be empty.