How to disable passivation for SFSB in WildFly

When a Stateful Bean is experiencing a period of inactivity, the EJB container may
decide to remove it from memory temporarily. This process is called passivation. Most of the
state of the EJB is saved automatically except for transient fields. When the EJB is restored,
the stateless EJB has its original content except for the transient fields.

Passivation is a resource consuming task therefore you can configure WildFly / JBoss EAP 7 to disable passivation.

There are two ways to disable passivations of Stateful Session Beans with WildFly / JBoss EAP 7:

Disabling Passivation programmatically

Including an EJB 3.2 attribute named “passivationCapable” in your SFSB definition as follows:

@Stateful(passivationCapable=false)
public class AccountEJB {  . . . }

Disabling passivation at configuration level

Change the stateful cache-ref from distributable to simple.

The CLI command to run is:

/subsystem=ejb3:write-attribute(name=default-sfsb-cache,value=simple)

That will reflect in the following change in configuration:

<stateful default-access-timeout="5000" cache-ref="simple" passivation-disabled-cache-ref="simple"/>

Please note that, by disabling passivation, all EJB instances are held on memory without passivation.

Therefore they will consume memory until they are expired by @javax.ejb.StatefulTimeout or removing an instance by calling remove API annotated @javax.ejb.Remove when finishing the SFSB execution.

EJB 3 tutorial : Session Beans

Enterprise JavaBeans (EJB) technology is an Enterprise technology for developing business components in a component-based, enterprise Java application.

EJB technology is generally viewed as powerful and sophisticated. The technology helps developers build business applications that meet the heavy-duty needs of an enterprise. In particular, applications built using EJB and other Enterprise technologies are secure, scale to support very large numbers of simultaneous users, and are transaction-enabled so that data maintains its integrity even though it’s processed concurrently by multiple users.

Despite its power and sophistication, some developers are hesitant to use EJB technology. The major obstacle for these developers is complexity. But there’s good news in store.

Java 5 introduced metadata annotations, which are property settings that mark a piece of code, such as a class or method, as having particular attributes. This is a declarative style of programming, where the developer specifies what should be done and the system adds the code to do it.

In EJB, metadata annotations dramatically simplify development and testing of applications, without having to depend on an external XML configuration file. It allows developers to declaratively add services to EJB components as and when they need.

Here we’ll assume you have already a basic knowledge of the three types of Enterprise Java so we’ll focus on the innovation introduced by the new release. So let’s start from Session Bean.

Stateless Session Bean lifecycle

To define a session bean, you first need to define the service interface containing all its business methods. The session bean interface is just plain old Java interface without any annotation. The client uses this interface to retrieve a stub object of the session bean from the EJB 3.0 container

package demo.ejb3;

public interface SessionDemoItf {

   public String doQuery (String param);

}

The @Stateless annotation indicates that this bean is a stateless session bean. Just add this notation and you’ll turn your POJO into an EJB !

We’ve also added the @PostConstruct and @PreDestroy notations, which are not compulsory but it’s helpful to understand the lifecycle of the EJB.

package demo.ejb3;

import javax.annotation.PostConstruct;
import javax.ejb.*;

@Stateless
public class SessionDemoBean implements SessionDemoItf {

    public String doQuery(String param) {
        return "Query with param " + param + " executed.";
    }

    @PostConstruct
    public void initialize () {
        // Initialize here objects which will be used
        // by the session bean
        System.out.println("SessionDemoBean initialized.");
    } 


    @PreDestory
    public void destroyBean() {
        // Free here resources acquired by the session bean
        System.out.println("SessionDemoBean initialized.");
    } 
}

Picture 1: Stateless Session Bean lifecycle

In order to compile a project which uses EJBs, it is sufficient to include the jakarta.jakartaee-api dependency in your pom.xml:

<dependencies>
        <dependency>
          <groupId>jakarta.platform</groupId>
          <artifactId>jakarta.jakartaee-api</artifactId>
          <version>${jakartaee.version}</version>
          <scope>provided</scope>
        </dependency>
</dependencies>

And specify the exact version of Jakarta EE. For example, for Jakarta EE 8:

<properties>
        <jakartaee.version>8.0.0</jakartaee.version>
</properties>

On the other hand, if you are developing for Jakarta EE 9:

<properties>
        <jakartaee.version>9.0.0</jakartaee.version>
</properties>

Stateful Session Bean lifecycle

The Stateful session bean is a session bean that maintains its internal states. If the client invokes method calls against the same bean stub, the calls are always tunneled to the same bean instance in the container. So, all field variables in the bean instance retain their values as long as the client application retains the bean stub (or reference for a local client).  

The stateful session bean is typically used to track states in an application: In a web application, the servlet (or JSP page) caches the bean stub as an attribute in the HttpSession object. The HTTP session’s state is therefore tracked and stored in the bean instance.

In a rich client Java application (e.g., Swing application), the application determines what is a “session” and caches the Stateful Session bean stub accordingly.

 It is very easy to create a Stateful Bean with EJB 3.0. All bean types are homeless in EJB 3.0 so all you have to do to create a Stateful bean is to create a bean class and have it implement at least one interface. Take a look at this:

@Stateful

public class HelloWorldBean implements HelloWorldItf, Serializable {

    int counter;

    public void doSomething() {
        counter++;
        System.out.println("Value of counter is " + counter);

    }


    @PostConstruct
    public void initialize () {
        // As with stateless EJB, the container immediately calls the 
        // annotated method after a bean instance 
        // is instantiated. 
    }

    @PreDestroy
    public void exit () {
        // The annotated method is called before the container destroys 
        // an unused or expired bean instance from its object pool.
    }

    @PrePassivate
    public void beforePassivate () {
        // Called before SFSB is passivated 
    }


    @PostActivate
    public void afterActivation () {
        // Called before after SFSB is restored 
    }

    @Init
    public void initialize () {
        // Called to initialize SFSB 
    }

    @Remove
    public void stopSession () {
        // Call to this method signals the container
        // to remove this bean instance and terminates
        // the session. The method body can be empty.
    } 

}

The first thing to notice is that the class is tagged as @Stateful. This marks the class as a stateful bean and the deployer will deploy that class as a stateful bean EJB container.

 So a Stateful SB can be basically in three States: Does not Exist, Ready and Passivated. When the Bean is first instantiated it is moved to the Ready State. If the instance is idle for too long, the container might passivate it and store its state to a cache. The method is tagged by the annotation @PrePassivate.

Picture 2: Stateful Session Bean lifecycle

When the client uses the passivated stateful session bean again, a new instance is created and the bean state is restored. The method tagged by this annotation is @PostActivate and when it’s called the activated bean instance is ready.

Another useful annotation for a lifecycle method, especially for stateful session beans, is @Remove. This is not a callback method: when the application calls remove on the bean instance it will signal the container to remove this bean instance and terminates the session.

What is the JNDI Name of an EJB ?

The JNDI binding of an EJB is generated based on the EJB name and the module’s name containing the EJB. Here is the magic formula:

ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>

Now some explanations how to determine these values:

  • app-name: this is the enterprise application name ( without ear ) if your EJB has been packed in an EAR. It is empty if you packed the EJB in a JAR or WAR archive
  • module-name: this is the archive name where the EJB has been packaged (in our case ee-ejb-server-basic)
  • distinct-name: this is an optional parameter that can be set on a single deployment unit
  • bean-name: this is the implementation class that is used by the EJB
  • fully-qualified-classname-of-the-remote-interface: this is the fully qualified classname of the remote interface interface

In addition, Stateful EJBs must include an additional suffix named “?stateful“.

For example, this is the binding for a Stateless EJB named com.sample.Calculator packaged in a WAR archive:

ejb:/ee-ejb-server-basic/CalculatorEJB!com.sample.Calculator

And this is the binding for a Stateful EJB named com.sample.Account packaged in a WAR archive:

ejb:/ee-ejb-server-basic/AccountEJB!com.itbuzzpress.ejb.Account?stateful

How to control the timeout period of a Stateful Bean?

Stateful session beans have configurable timeout values which can control the amount of time a bean can remain idle prior to passivation or removal.

The timeout can be configured in different ways depending on the version of the application server used.

  • WildFly / JBoss EAP 7

We recommend checking the following tutorial: Configuring Timeout policies for your EJBs

  • JBoss 5

You can apply the the @org.jboss.annotation.ejb.cache.simple.CacheConfig annotation on your EJBs. For non clustered applications use:

@CacheConfig (maxSize=100000, idleTimeoutSeconds=300, removalTimeoutSeconds=0)

For clustered applications use:

@CacheConfig (name="jboss.cache:service=EJB3SFSBClusteredCache", maxSize=100000, idleTimeoutSeconds=300, removalTimeoutSeconds=0)

EJB 3 Client lookup

We cover in detail EJB 3 Client lookup in this tutorial: WildFly remote EJB client tutorial

Controlling EJB 3 initialization

To Control the initialization process of EJBs you can decorate your EJBs with the @Startup annotation.

We cover in detail this topic in the following tutorial: How to create an EJB Startup Service

Singleton EJB tutorial

If you need to make sure you are exposing an Enterprise Java  Bean as a Singleton, there is a simple approach which requires adding the @Singleton annotation on your EJB.
 
As the name implies a javax.ejb.Singleton is a session bean with a guarantee that there is at most one instance in the application. Until now if you wanted to expose a Service as Singleton you had to use either Service POJOS (See an article here JBoss MBeans POJO ) or tweak the EJB pool maximum size.

All of these approach worked, however they were not portable because they used JBoss annotations/configuration to do the trick.

Making an EJB as Singleton is pretty easy: just add the @java.ejb.Singleton annotation and that’s all.

Here’s an example:

@Singleton
@Startup
public class UserRegistry {

        public ArrayList<String> listUsers;
        @PostConstruct
        public void init() {
                listUsers = new ArrayList<String>();
                listUsers.add("administrator");

        }

    	public void addUser(String username) {
    		listUsers.add(username);
    	}
    	public void removeUser(String username) {
    		listUsers.remove(username);
    	}

        public ArrayList<String> getListUsers() {
            return listUsers;
    }
}

In this example, the EJB exposes some methods to manage an in-memory cache based on an ArrayList.

Notice also the @Startup annotation which is not mandatory but can be used to signal to the container to invoke the @PostConstruct method just after the Bean has been created. So, if you need a proper Bean initialization, just add a @Startup annotation at Class level and a @PostConstruct at method level.

Testing the Singleton EJB is pretty simple, here’s a Servlet client:

@WebServlet("/servlet")
public class ServletClient extends HttpServlet {

    @EJB  UserRegistry ejb;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        PrintWriter out = resp.getWriter();
        ejb.addUser("frank");
        out.println("List of users:")
        ArrayList<String> list = ejb.getListUsers();       
        for (String s:list) {
            out.println(s);
        }    	

    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

Please note that you won’t be able to look up remotely a Singleton EJB. If you need to access the Singleton EJB remotely you should include a wrapper Stateless Bean with a remote interface.

Managing concurrency in EJB singleton

Singleton session beans are designed for concurrent access, situations in which many clients need to access a single instance of a session bean at the same time.

There are two ways to manage concurrent access to Singleton EJBs. Let’s see them both.

Singleton Container-Managed Concurrency

If a singleton uses container-managed concurrency, the EJB container will manage access to the business methods of the singleton. This is the default if you don’t use any @ConcurrencyManagement annotation.

You can use the javax.ejb.Lock and javax.ejb.LockType annotation to specify the access level of the singleton’s business methods.

  • Annotate a method with @Lock(LockType.READ) if the method can be concurrently accessed.
  • Annotate a method with @Lock(LockType.WRITE) if the singleton session bean should be locked to other clients while a client is calling that method.

Typically, the @Lock(LockType.WRITE) annotation is used when clients are modifying the state of the singleton

The following example shows how to use the @ConcurrencyManagement, @Lock(LockType.READ), and @Lock(LockType.WRITE) annotations for a singleton that uses container-managed concurrency:

@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
@Startup
public class UserRegistry {

        public ArrayList<String> listUsers;
        @PostConstruct
        public void init() {
                listUsers = new ArrayList<String>();
                listUsers.add("administrator");

        }

        @Lock(LockType.WRITE)
        @AccessTimeout(value=60, timeUnit=SECONDS)
    	public void addUser(String username) {
    		listUsers.add(username);
    	}
        @Lock(LockType.WRITE)
        @AccessTimeout(value=60, timeUnit=SECONDS)
    	public void removeUser(String username) {
    		listUsers.remove(username);
    	}
        @Lock(LockType.READ)
        public ArrayList<String> getListUsers() {
            return listUsers;
    }
}

You can specify how long the locks should be held by using the javax.ejb.AccessTimeout annotation.

The @AccessTimeout annotation can be applied to both @Lock(LockType.READ) and @Lock(LockType.WRITE) methods. .

The following excerpt shows how to apply a 1 minute timeout lock for some of your business methods:

@Lock(LockType.WRITE)
@AccessTimeout(value=60, timeUnit=SECONDS)
public void addUser(String username) {
    listUsers.add(username);
}
@Lock(LockType.WRITE)
@AccessTimeout(value=60, timeUnit=SECONDS)
public void removeUser(String username) {
    listUsers.remove(username);
}
Singleton Bean-Managed Concurrency

Singletons that use bean-managed concurrency allow full concurrent access to all the business and timeout methods in the singleton. The developer is now responsible for ensuring that the state of the singleton is synchronized across all clients. Typically, if you want to code EJB singletons with bean-managed concurrency, you should use synchronization primitives, such as synchronization and volatile, to prevent errors during concurrent access.

Add a @ConcurrencyManagement annotation with the type set to ConcurrencyManagementType.BEAN at the class level of the singleton to specify bean-managed concurrency:

@ConcurrencyManagement(BEAN)
@Singleton
public class UserRegistry { ... }

Handling failures in a Singleton Session Bean

If an EJB singleton encounters an error when initialized by the EJB container, that singleton instance will be destroyed and you won’t be able to access it.

However, once it is initialized, a singleton EJB, it is not destroyed if the singleton’s business or lifecycle methods cause System exceptions. This ensures that the same singleton instance is used throughout the application lifecycle.

Source code for this tutorial: https://github.com/fmarchioni/mastertheboss/tree/master/ejb/ejb-singleton

How to code EJB interceptors like a pro

EJB 3 interceptors provide the bean developer with fine grained control over the method invocation flow. In this tutorial we’ll see how to code server side EJB Interceptors and how to define Global EJB server side interceptors (WildFly 18 or newer).

An interceptor is a method that you can interpose in the invocation flow of an enterprise bean. You can define an interceptor to intercept an enterprise bean’s business methods:  the interceptor method will be executed before any of the bean’s business methods are invoked.


The great benefit of interceptors is that they give you a way to add functionality to your business methods without modifying the methods’ code.

There are two types of EJB Interceptors you can plug in your code:

  • aroundInvoke Interceptors: These Interceptors will be called before a target EJB is invoked
  • aroundTimeout Interceptors: These Interceptors are called upon timeout of EJB timer service

aroundInvoke EJB Interceptors

Let’s see a practical example:

import javax.ejb.Stateless;

import javax.interceptor.Interceptors;

import org.jboss.ejb3.annotation.RemoteBinding;

@Stateless(name="SampleEJB")
@RemoteBinding(jndiBinding="SampleEJB")
@Interceptors(value=com.sample.MyInterceptor.class)

public class SampleBean implements Sample {

    public void doSomething(String param) {
        callWebService(param);
    }
}

In this class we’ve declared a custom interceptor named com.sample.MyInterceptor :

How does it work ? when a method of your SampleEJB is invoked, the Interceptor is invoked. The interceptors has full access to the method name invoked and its parameter.

package com.sample;

import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

public class MyInterceptor {

    @AroundInvoke
    public Object log(InvocationContext ctx) throws Exception
    {
        System.out.println("*** TracingInterceptor intercepting " + ctx.getMethod().getName());
        long start = System.currentTimeMillis();
        String param = (String)ctx.getParameters()[0];

        if (param == null)
            ctx.setParameters(new String[]{"default"});

        try
        {
            return ctx.proceed();
        }
        catch(Exception e)
        {
            throw e;
        }
        finally
        {
            long time = System.currentTimeMillis() - start;
            String method = ctx.getClass().getName();
            System.out.println("*** TracingInterceptor invocation of " + method + " took " + time + "ms");
        }
    }
}

In this example the Interceptor validates the parameters and then invokes the method ctx.proceed() which in turns call the next Interceptor in the chain (if any) and finally the business method.

When the business method returns the Interceptor resumes its execution and calculates the time elapsed.

aroundTimeout EJB Interceptors

You can define interceptors for EJB timer service timeout methods by using the @AroundTimeout annotation on methods in the target class or in an interceptor class. Only one @AroundTimeout method per class is allowed.

The following code declares an @AroundTimeout interceptor method within a target class.

@Stateless
public class TimerBean {
...
    @Schedule(minute="*/1", hour="*")
    public void automaticTimerMethod() { ... }

    @AroundTimeout
    public void interceptorMethod(InvocationContext ctx) { ... }
...
}

Where can I apply EJB interceptors?

You can apply Interceptors at three different level:
1) Default interceptors:

These interceptors needs to be declared in your ejb-jar.xml and are valid across all your EJB deployed :

 <assembly-descriptor>
 <interceptor-binding>
 <ejb-name>*</ejb-name>
 <interceptor-class>sample.interceptor.MyDefaultInterceptor</interceptor-class>
 </interceptor-binding>
 ...
 </assembly-descriptor>

2) Class level interceptors:

This is the kind of interceptor we’ve seen in our example: it is valid across all methods of an EJB.

@Stateless
    @Interceptors(value=com.sample.SampleInterceptor.class)
    public class StatelessBean
    {
       ...
    }

3) Method level interceptors:

The method level interceptor only intercepts the single method call :

    @Interceptors(value=com.sample.MethodInterceptor.class)
    public void doSomething()
    {
       ...
    }

4) Interceptors in the Bean class:

Interceptors do not need to be written in a separate file: you can code interceptors in the EJB class as well:

@Stateless(name="SampleEJB")
@RemoteBinding(jndiBinding="SampleEJB")
@Interceptors(value=com.sample.MyInterceptor.class)

public class SampleBean implements Sample {

    public void doSomething(String param) {
        callWebService(param);
    }
    @AroundInvoke
    public Object log(InvocationContext ctx) throws Exception
    {

        try
        {
            return ctx.proceed();
        }
        catch(Exception e)
        {
            throw e;
        }
    }
}

The only thing that differs if you declare your interceptors in the Bean class is the order: if you have on the same Class both External Interceptors and Internal Interceptors the (Internal) Interceptor method defined in the bean class itself is invoked at the end. (after the Interceptors in external files).

Global EJB Interceptors

Since WildFly 18, it is possible to define one or more global EJB Interceptors which are invoked for all EJB running in the Container. The Interceptor is defined in a module therefore the application deployments are not changed.

Each interceptor is configured in <interceptor> tag which contains the following fields:

  • module – the module in which the interceptor is defined
  • class – the class which implements the interceptor

In order to use server interceptors you have to create a module that implements them and place it into ${WILDFLY_HOME}/modules directory.

Global Interceptor implementations are also POJO classes which use javax.interceptor.AroundInvoke and javax.interceptor.AroundTimeout to mark interceptor methods.

Sample configuration in the ejb3 subsystem:

<server-interceptors>
    <interceptor module="com.sample:MyInterceptor:1.0" class="com.sample.MyInterceptor"/>
</server-interceptors>

An this is a sample implementation:

package com.sample;

import javax.annotation.PostConstruct;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;

public class MyInterceptor {

    @AroundInvoke
    public Object bar(final InvocationContext invocationContext) throws Exception {
        return invocationContext.proceed();
    }
}

Order of EJB Interception

The default interceptor is invoked at first. Then Bean level interceptors are invoked and, at last, method level interceptors. If you declare a list of interceptors in your xml/annotations the interceptors are invoked in the order in which they are declared in the annotation:

<interceptor-binding>
    <target-name>myapp.OrderBean</target-name>
    <interceptor-class>demo.FirstInterceptor.class</interceptor-class>
    <interceptor-class>demo.SecondInterceptor.class</interceptor-class>
    <interceptor-class>demo.ThirdInterceptor.class</interceptor-class>
    <method-name>updateInfo</method-name>
</interceptor-binding>

Excluding the default Interceptor

If you have defined a default interceptor for all your EJB in a jar file, you can use the following annotation to exclude it and instead execute the Interceptor in the class:

@Stateless(name="SampleEJB")
@ExcludeDefaultInterceptors        
public class TestEJB implements Test
{

    @AroundInvoke
    public Object customInterceptor(InvocationContext ctx) throws Exception
    {
        System.out.println("*** CustomInterceptor intercepting");
        return ctx.proceed();
    }
 }

Scenarios where you can use Interceptors:

Interceptors are particularly when:

  • It is required to validate parameters before they’re passed to a business method
  • You need to perform security checks at the time the business method is called.
  • You need to perform other useful for actions such as logging and profiling without changing the code of your EJB.

Using Bean Managed Transactions (BMT) in Java EE applications

In a Bean Managed Transaction (BMT), the code in the EJB or Message Driven Bean explicitly marks the boundaries of the transaction. Although beans with container-managed transactions (CMT) require less coding, they have one limitation: When a method is executing, it can be associated with either a single transaction or no transaction at all. If this limitation will make coding your bean difficult, you should consider using bean-managed transactions. How do you code an EJB 3 using Bean Managed Transactions (BMT)

Here is an example:

package com.mastertheboss.ejb;

import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.PersistenceContext;
import javax.transaction.Status;
import javax.transaction.UserTransaction;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;


@Stateless
@TransactionManagement(TransactionManagementType.BEAN)

public class ManagedComponent {
    /**
     * Ask the container to inject an Entity Manager (EM). As a consequence the EM will be automatically enlisted into any new
     * bean managed transaction
     *
     */
    @PersistenceContext
    private EntityManager entityManager;

    // Inject a UserTransaction for manual transaction demarcation.
    @Inject
    private UserTransaction userTransaction;

    public String executeTransaction() {

        try {
            userTransaction.begin();

            // Execute Bean Managed Transaction here

            userTransaction.commit();

            return result;
        } catch (Exception e) {
            return e.getMessage();
        } finally {
            /*
             * Clean up
             */
            try {
                if (userTransaction.getStatus() == Status.STATUS_ACTIVE)
                    userTransaction.rollback();
            } catch (Throwable e) {
                // ignore
            }
        }
    }
}

As you can see, we specify that an EJB uses Bean Managed Transaction (BMT) by using the @TransactionManagement annotation and setting its TransactionManagementType element to BEAN. Next, the transaction operations are enclosed in a code sequence starting with the UserTransaction ‘s begin method and ending with the commit method. Please note that the above example @Inject the UserTransaction therefore you need to include also CDI dependencies in your project.

On the other hand, if you are not using CDI in your project, you can use the legacy @Resource annotation to inject the UserTransaction in your project:

@Resource
private UserTransaction utx;

A Message Driven Bean with Bean Managed Transaction

Much the same way, we can code a Message Driven Bean using BMT. Here is an example:

import javax.annotation.Resource;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.ejb.MessageDrivenContext;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
import javax.transaction.UserTransaction;

import org.jboss.ejb3.annotation.ResourceAdapter;

@MessageDriven(name = "MDB_BMTExample", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
                                                            @ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/testQueue"),
                                                            @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Dups-ok-acknowledge") })
@TransactionManagement(value = TransactionManagementType.BEAN)
@ResourceAdapter("hornetq-ra.rar")
public class MDB_BMTExample implements MessageListener
{
   @Resource
   MessageDrivenContext ctx;

   public void onMessage(final Message message)
   {
      try
      {
         
         TextMessage textMessage = (TextMessage)message;
         String text = textMessage.getText();
         System.out.println("message " + text + " received");

         // lets look at the user transaction to make sure there isn't one.
         UserTransaction tx = ctx.getUserTransaction();

         if (tx != null)
         {
            tx.begin();
            System.out.println("we're in the middle of a transaction: " + tx);
            tx.commit();
         }
         else
         {
            System.out.println("something is wrong, I was expecting a transaction");
         }
      }
      catch (Exception e)
      {
         e.printStackTrace();
      }
   }
}

Rolling back an EJB Bean Managed Transaction

In a BMT EJB, either the UserTransaction ‘s rollback() or setRollbackOnly() methods are used to explicitly rollback the transaction. In the above example, we have used the rollback() method of the UserTransaction class, however it is also possible to invoke setRollBackOnly as in this example:

try {
// Starts the transaction
userTransaction.begin;
...
// Commits the transaction
userTransaction.commit();
} catch (FirstException fe ) {
userTransaction.setRollbackOnly();
} catch (SecondException se ) {
userTransaction.setRollbackOnly();
}

So what is the difference between UserTransaction ‘s rollback() or setRollbackOnly() ? The use of the rollback() method results in the immediate rollback of the transaction. On the other hand, using the setRollbackOnly method only marks the transaction for rollback. It will not be rolled back until the transaction actually ends. Delaying the rollback can be advantageous since it permits other activities to be performed, such as logging the error conditions.

Transactions not completed in a BMT

According to the EJB specification a transaction must be finished from a BMT bean if it was opened there.

“If a stateless session bean instance starts a transaction in a business method, it must commit the transaction before the business method returns.
The Container must detect the case in which a transaction was started, but not completed, in the business method, and handle it as follows:

  • Log this as an application error to alert the system administrator.
  • Roll back the started transaction.
  • Discard the instance of the session bean.
  • Throw the java.rmi.RemoteException to the client”

Interview question

Q: And now a nice interview question: what happens if a Bean Managed Transaction EJB calls a CMT EJB in its transaction ? and viceversa ?

A: Actually, it is possible a BMT will start a transaction and then invoke a method of a CMT. As a result, the CMT will not be aware who started the transaction. In contrast, a BMT can only participate in a transaction that it started. It is not possible to propagate a transaction to another BMT EJB.

MDB Tutorial | Mastertheboss

A Message Driven Bean (MDB) is an asynchronous message consumer. The MDB is invoked by the container as a result of the arrival of a message at the destination that is serviced by the MDB. A Message Driven Bean can be used for a single messaging type, in accordance with the message listener interface it employs.
From the client view, a message-driven bean is a message consumer that implements some business logic running on the server. A client accesses the MDB by sending messages to the destination for which the message-driven bean class is the message listener.

Message Driven Bean Goals

  • MDBs are anonymous components. They have no client-visible identity.
  • MDBs have no conversational state. This means that all bean instances are equivalent when they are not involved in servicing a client message.
  • MDBs can be transaction aware
  • A MDB instance has no state for a specific client. However, the instance variables of the message-driven bean instance can contain state across the handling of client messages. Examples of such state, include an open database connection and a reference to an enterprise bean.
    A further goal of the message-driven bean model is to allow for the concurrent processing of a stream of messages by means of container-provided pooling of message-driven bean instances.

A sample Message Driven Bean

import java.util.logging.Logger;
import javax.ejb.*;
import javax.jms.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.sql.DataSource;

@MessageDriven(name = "MessageMDBSample", activationConfig = {
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "queue/MyQueue"),
        @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })

public class ExampleMDBean implements MessageListener {

    @Resource
    private MessageDrivenContext context;

    @Resource(lookup="java:jboss/datasources/PostGreDS")
    private DataSource ds;
    
    public void onMessage(Message message) {

         try (Connection con = ds.getConnection();
             PreparedStatement ps = createPreparedStatement(con);
             ResultSet rs = ps.executeQuery()) {

            while(rs.next()) {
                System.out.write("Time from Database: " +rs.getString(1));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
    private PreparedStatement createPreparedStatement(Connection con) throws SQLException {
        String sql = "SELECT NOW();";
        PreparedStatement ps = con.prepareStatement(sql);
        return ps;
    }
}

This example shows a MDB which will be triggered when a message is sento the the JMS Queue bound in the JNDI tree under the “queue/MyQueue” name.

An MDB client:

We add here a simple Servlet client which sends a batch of messages to the destination where the MDB is actively listening:

@WebServlet("/HelloWorldMDBServletClient") 

public class HelloWorldMDBServletClient extends HttpServlet {
  private static final int MSG_COUNT = 50;
  
  @Inject 
  private JMSContext context;
  @Resource(lookup = "java:/queue/MyQueue") 
  private Queue queue;
  @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    resp.setContentType("text/html");
    PrintWriter out = resp.getWriter();
    try {
      out.write("Sending messages to " + destination);
      out.write("The following messages will be sent to the destination:");
      for (int i = 0; i & lt; MSG_COUNT; i++) {
        String text = "This is message " + (i + 1);
        context.createProducer().send(queue, text);
        out.write("Message (" + i + "): " + text + "");
      }
      out.write("Go to your JBoss EAP server console or server log to see the result of messages processing.");
    } finally {
      if (out != null) {
        out.close();
      }
    }
  }
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    doGet(req, resp);
  }
}

Within this tutorial, we have covered some of the options available to configure an MDB. You can read more about MDB annotations here: 10 Annotations you can use on your MDBs

How to add a Selector with MDB 3.0 ?

Message selectors allow an MDB to be more selective about the messages it receives from a particular topic or queue. Message selectors use Message properties as criteria in conditional expressions. These conditional expressions use Boolean logic to declare which messages should be delivered to a client.

With MDB 3.0 it’s easier to configure a selector : simply add an @ActivationConfigProperty at the top of your MDB:

@MessageDriven(activationConfig = {
  
  @ActivationConfigProperty(propertyName = "messageSelector",propertyValue = "color= 'red'")}
)


public class Mdbsample implements MessageListener {
 ... 
}

Using an MDB Selector in XML descriptors

If you don’t want to include in your code the Selector info, you can also specify it in the ejb-jar.xml configuration file. See this example:

<ejb-jar>
    <display-name>DemoMDB</display-name> 
    <enterprise-beans>
        <message-driven>
            <display-name>testMdb</display-name>
            <ejb-name>DemoMDB</ejb-name>
            <ejb-class>DemoMDB</ejb-class>
            <transaction-type>Container</transaction-type>
            <message-selector>RECIPIENT='MDB'</message-selector>
            <message-driven-destination>
                <destination-type>javax.jms.Queue</destination-type>
            </message-driven-destination> 
                <resource-ref>
                <description>description</description>
                <res-ref-name>jms/myQueueConnectionFactory</res-ref-name>
                <res-type>javax.jms.QueueConnectionFactory</res-type>
                <res-auth>Application</res-auth>
                <res-sharing-scope>Shareable</res-sharing-scope>
            </resource-ref> 
            <resource-env-ref>
               <resource-env-ref-name>jms/persistentQueue</resource-env-ref-name>
             <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>
            </resource-env-ref> 
        </message-driven>
    </enterprise-beans>

    <assembly-descriptor>
        <container-transaction>
            <method>
                <ejb-name>DemoMDB</ejb-name>
                <method-name>onMessage</method-name>
                <method-params>
                    <method-param>javax.jms.Message</method-param>
                </method-params>
            </method>
            <trans-attribute>Required</trans-attribute>
        </container-transaction>
    </assembly-descriptor> 
</ejb-jar>

Setting a Message Selector programmatically

You can also set a Selector on your Producer by setting a String property as follows:

Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(true, 0);
Message message = session.createMessage();
message.setStringProperty("color", "yellow");
JMSProducer producer = context.createProducer();

producer.send(queue, message);

How to define a Selector at Queue level

Finally, it is worth mentioning that the messaging-activemq subsystem (available in WildFly / JBoss EAP 7) also allows to define a selector for your destination. To do that, set the filter attribute of your destination as shown here:

<subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
...
<queue
  name="myQueue"
  filter="color='red'" />
...
</subsystem>

You can set the filter when you are creating your Queue as in this example:

jms-queue add --queue-address=QUEUE_ADDRESS --selector=FILTER_EXPRESSION

How can I retrieve the id of a Transaction started by JBoss ?

Sometimes it an be useful for debugging purpose to retrieve the id of a transaction; one typical scenario could be a transaction started by an EJB deployed as CMT.

The javax.transaction.TransactionManager interface provides two ways to fetch the transaction id:

  • The simplest strategy is to call the toString method to print complete information about the running transaction. That will print also the transaction id.
  • Other than that, you can cast the javax.transaction.Transaction instance to a com.arjuna.ats.jta.transaction.Transaction . Then, call either the get_uid method, which returns the Transaction Uid representation. Example:

com.arjuna.ats.jta.transaction.Transaction tx = (com.arjuna.ats.jta.transaction.Transaction)tx.getTransaction();
System.out.println("Transaction UID" +tx.get_uid());
  • Please note that you need to call the getTxId method to fetch the Xid for the global identifier.

 Viewing Transactions from the JBoss CLI

If you want to fetch the transactions from the CLI, the following command will show all prepared transactions:

ls /profile=default/subsystem=transactions/log-store=log-store/transactions

Then, to view attributes of a Transaction:

/profile=default/subsystem=transactions/log-store=log-store/transactions=0\:gtrw7f000001\:-b11tfg2\:3t4j1r6a\:9:read-resource

Versioning Entity with Hibernate Envers

The Envers project aims to enable easy auditing/versioning of persistent classes. This can simplify storing and retrieving historical sets of data from the DB.
Similarly to Subversion, Envers has a concept of revisions. Basically, one transaction is one revision (unless the transaction didn’t modify any audited entities).
 
As the revisions are global, having a revision number, you can query for various entities at that revision, retrieving a view of the database at that revision.The Project Envers is available as standalone project, however, since the release 3.5 of Hibernate it is included as Hibernate module too.
Let’s see a practical example:
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.envers.Audited;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.io.Serializable;


@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Audited
@Builder
public class Customer implements Serializable {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    private String firstName;
    private String lastName;
}

As you can see, that is an Entity Bean which uses Lombok project to reduce boilerplate coding but also contains the @org.hibernate.envers.Audited annotation, which tells Envers to automatically track changes to this entity.

To get it working, you have to add the hibernate-envers dependency to your pom.xml file:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-envers</artifactId>
    <version>${hibernate.version}</version>
</dependency>
Please note that instead of annotating the whole class, you can annotate only some persistent properties with @Audited. This will cause only these properties to be audited.

With the @Audited annotation in place, Hibernate will then create a new revision for each transaction and create a new record in the audit table for each create, update or delete operation performed on an audited Entity.

You can then retrieve and query historical data without much effort. Basically, one transaction is one revision. As the revisions are global, having a revision number, you can query for various entities at that revision, retrieving a (partial) view of the database at that revision. You can find a revision number having a date, and the other way round, you can get the date at which a revision was commited.

For above entity will be auto-generated audit table:

create table Customer_AUD (
    id bigint not null,
    REV integer not null,
    REVTYPE tinyint,
    firstName varchar(255),
    lastName varchar(255),
    primary key (id, REV)
)

The REVTYPE column value is taken from the RevisionType Enum:

| Database column value | RevisionType
| ----------------------|-------------
| 0                     | ADD
| 1                     | MOD
| 2                     | DEL
  • ADD – indicates that the entity was added (persisted) at that revision.
  • DEL – indicates that the entity was deleted (removed) at that revision.
  • MOD – indicates that the entity was modified (one or more of its fields) at that revision.

Accessing Entity History

You can access the audit (history) of an entity using the AuditReader interface, which you can obtain from an open EntityManager:

AuditReader reader = AuditReaderFactory.get(entityManager);
Customer oldCustomer = auditReader.find(Customer.class, customerId, rev)

That returns the Customer entity with the given primary key, with the data it contained at the given revision. If the entity didn’t exist at this revision, null is returned.

You can also get a list of revisions at which an entity was modified:

List<Number> revisions = auditReader.getRevisions(Customer.class, customerId);

And you can  retrieve the date (when the revision was created) using the getRevisionDate method:

Map<Number, Date> revisionDatesMap = revisions.stream().collect(Collectors.toMap(Function.identity(), auditReader::getRevisionDate));

For additional information about Envers, visit the Enver Project documentation at: https://envers.jboss.org/

 

How to create a MDB 3.0 singleton ?

You can specify the maximum number of JMS Sessions that are available to concurrently deliver messages to an MDB using the maxSession property. Here is an example:

@MessageDriven(activationConfig = {
        @ActivationConfigProperty(propertyName = "maxSessions", propertyValue = "1"),
        @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
        @ActivationConfigProperty(propertyName = "destination", propertyValue = "TASK.QUEUE")
})
public class BuildTasksMessageListener implements MessageListener {

    @Override
    public void onMessage(Message message) {
        try {

            doSomethingUseful();

        } catch (JMSException e) {
            // Why can't I throw a JMS Exception
            throw new RuntimeException(e);
        }
    }

    // This is the only "useful" code in the class
    private void doSomethingUseful() {

    }
}

You can also set the max-session attribute in the XML descriptor:

<activation-config>
    <activation-config-property>
        <activation-config-property-name>maxSession</activation-config-property-name>
        <activation-config-property-value>1</activation-config-property-value>
    </activation-config-property>
</activation-config>

By setting max-session to 1 will essentially give you a singleton MDB.

Warning:  a Message Driven Bean configured to run as Singleton can soon become a bottleneck for your application. If you want a higher scalability / availability of your MDB you should consider increasing the number of MDB session instead.

Older JBoss versions

If you are running JBoss 4/5/6 you can configure this at EJB container level by changing the server/$/deploy/ejb3-interceptors-aop.xml file:

<annotation expr="!class(@org.jboss.annotation.ejb.DefaultActivationSpecs)">
  @org.jboss.annotation.ejb.DefaultActivationSpecs (value={@~ActivationConfigProperty(propertyName = "maxSession", propertyValue = "1")})
</annotation>

This will set the default for all message driven beans.