Concurrency

Having a good understanding of the Concurrency semantics of different sessions beans is extremly important in order to be able to leverage them effectively. This chapter covers concurrency related annotations and talks about how they affect performance characteristics

Specifies the time period after which a queued request (waiting for another thread to complete) times out. This feature does not make sense for Stateless beans since the container allocates a new bean instance for each request.

This annotation is valuable for Stateful beans as well as Singleton beans configured with container managed concurrency option (ConcurrencyManagementType.CONTAINER)

During peak loads, your session bean instances are bombarded with concurrent requests. The EJB container ensures sanity by serializing these calls i.e. blocking other threads until the current thread finishes execution. Think of this annotation as a concurrency policy. It ensures that the potential (waiting) threads are not kept blocked forever.

package ejbap.concurrency;

import javax.ejb.AccessTimeout;
import javax.ejb.Stateful;

@Stateful
public class StatefulBeanWithTimeout{

    @AccessTimeout(value=5000, unit=java.util.concurrent.TimeUnit.MILLISECONDS)
    public void find(String id){
        //... business logic
    }
}

You can use the value and unit elements of this annotation to refine its behaviour

Here are a few usage options

  • @AccessTimeout(0) – this means that your method does not support concurrent access at all and the client would end up getting a javax.ejb.ConcurrentAccessException

  • @AccessTimeout(-1) – your method will block indefinitely

  • @AccessTimeout(5000) – method will wait for 5000 ms (5 seconds) before the next thread in queue (if any) if given a chance

@ConcurrencyManagement

A Singleton bean is flexible in terms of Concurrency Management - by default (convention), the container handles concurrent access to a Singleton bean. By using the @ConcurrencyManagement annotation, you as a bean developer can take the bean concurrency management into your own control.

The possible values (enums) for this annotation are - ConcurrencyManagementType.CONTAINER and ConcurrencyManagementType.BEAN. The nomenclature of these enums clearly define their role.

package ejbap.concurrency;

import java.util.Date;
import javax.annotation.PostConstruct;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.ConcurrencyManagementType;
import javax.ejb.Singleton;

@Singleton
//applicable by default
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class ContainerManagedSingleton {

    private String property;

    //container takes care of synchronization. WRITE protected by default
    public void update(String property){
        this.property = this.property + " " + property;
    }

    @PostConstruct
    public void init() {
        property = new Date().toString();
    }


}

In case you opt for Bean managed concurrency, you as a bean developer are responsible for the thread safety of objects used within the Singleton bean e.g. using synchronized methods, thread safe collections etc

package ejbap.concurrency;

import java.util.Date;
import javax.annotation.PostConstruct;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.ConcurrencyManagementType;
import javax.ejb.Singleton;

@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class DeveloperManagedSingleton {

    private String property;

    /**
     * need to synchronize this manually since container 
     * has no control over how many threads can enter this method
     */

    public synchronized void update(String property){
        this.property = this.property + " "+ property;
    }


    @PostConstruct
    public void init() {
        property = new Date().toString();
    }
}

@Lock

When using Container managed concurrency (ConcurrencyManagementType.CONTAINER) with Singleton EJBs, the @Lock annotation can help define whether or not you want allow concurrent access to your bean methods. If this annotation is not used, the default value is LockType.WRITE (enum) which signifies that the method cannot be accessed by multiple threads at the same time. The other option LockType.READ, behaves in exactly the opposite manner i.e. it allows multiple threads to concurrently access this method given that there is no thread which is currently holding a write lock on the Singleton bean instance.

package ejbap.concurrency;

import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Singleton;

@Singleton
public class GoldiLocks {

    private String configuration;

    @PostConstruct
    public void init() {
        configuration = UUID.randomUUID().toString();
        System.out.println("Configuration bootstrapped -- " + configuration);
    }

    @PreDestroy
    public void destroy() {
        System.out.println("Destroying Configuration -- " + configuration);
        configuration = null;
    }

    /**
     * This is by default. We can afford to relax
     * since this is a READ operation
     */
    @Lock(LockType.READ) 
    public String getConfig() {
        return configuration;
    }

    /**
     * We don't want multiple threads updating the configuration 
     * (a WRITE operation) at the same time!
     */
    @Lock(LockType.WRITE) 
    public void update(String config) {
        this.configuration = configuration + " " + config;
    }
}

What's next ?

Let's explore the Aspect Oriented features provided by EJBs !

Last updated