Singleton Session EJB

From NovaOrdis Knowledge Base
Jump to navigation Jump to search

Internal

Concepts

Overview

A singleton session bean is a component that is instantiated once per application. For distributed applications that span multiple VMs, each application will have on singleton session bean instance per JVM. The instances are intended to be shared, and must support concurrent access. The Singleton bean instances maintain state between invocations, but the state is not required to survive container shutdown or crash.

Lifecycle

Instantiation

The singletons are lazy instantiated by default. The container instantiates them when the first invocation arrives. However, a Singleton bean can declare that it needs eager initialization, when the application starts, by declaring the @Startup annotation. If eagerly initialized, it is the container's responsibility to initialize the bean before any external client requests are delivered to the instance.

To create the instance, the container invokes newInstance() method on the Singleton bean class. Then the container performs any dependency injection. Then the container calls @PostConstruct methods.

If a failure occurs during the Singleton initialization, it is considered fatal and the instance is discarded.

@PostConstruct methods for Singletons with container-managed transaction are transactional. See EJB 3.1 Specification Section 4.8.3.

Dependencies

A Singleton bean may declare an initialization dependency on another Singleton bean instance, by declaring the @DependsOn annotations. More details on dependencies available in @DependsOn.

Active Life

Once instantiated according to the previous sequence, the Singleton bean instance lives for the duration of the application. Unlike instances of other component types, system exceptions thrown from business methods or callbacks of a Singleton do not result in the destruction of the instance.

Destruction

When the application is shutting down, the container invokes @PreDestroy methods, and this ends the life of the instance.

Note that during destruction, the container ensures that all Singleton beans on which this instance @DependsOn are still available during the instance's @PreDestroy methods.

@PreDestroy methods for Singletons with container-managed transaction are transactional. See EJB 3.1 Specification Section 4.8.3.

Concurrency



Next time I have to deal with this, write a playground example and verify all assertions


Singleton beans are intended to support concurrent access. The developer may choose between bean-managed concurrency, where the container allows unencumbered full concurrent access, and state access synchronization becomes the responsibility of the developer, and container-managed concurrency, where the container manages concurrent access, according to method-level locking metadata. A Singleton bean can be designed to use either method, but not both. The default behavior when nothing is explicitly specified, is container-managed concurrency. Regardless of the concurrency management method, the container will insure that there is no concurrent access until after @PostConstruct methods successfully complete.

It is legal to store JEE objects that do not support concurrent access within Singleton bean instances, but it the responsibility of the developer to ensure such objects are not accessed by more than one thread at a time.

Singleton beans support reentrant calls (EJB 3.1 Spec Section 4.8.5.1.1).

If the developer chooses to use container-managed concurrency, the container controls concurrent access based on method-level locking metadata. Each business method may be associated with either a shared READ lock, or an exclusive WRITE lock. The association can be declared using the @Lock(LockType.READ|Lock(LockType.WRITE) annotation.

The annotation can be applied to method level and class level. Specifying the Lock annotation on the bean class means that it applies to all applicable business methods of the class. If the concurrency locking attribute is not specified, for both class or method, it is assumed to be @Lock(WRITE). @Lock is equivalent with @Lock(WRITE), LockType.WRITE is the default concurrency attribute.

If the container invokes a method associated with a READ lock, any number of other concurrent invocations on READ methods are allowed to access the bean instance simultaneously. There is just one READ lock per Singleton instance.

If the container invokes a method associated with a WRITE lock, no other concurrent invocations will be allowed to proceed until the initial WRITE method’s processing completes. There is just one WRITE lock per Singleton instance.

More details on concurrency metadata, including the rules that apply in case of inheritance are described in EJB 3.1 specifications, sections 4.8.5.4, and 4.8.5.5.

If the lock is not acquired within a certain amount of time, timeouts can be specified via metadata, with the @AccessTimeout annotation (EJB 3.1 Spec Section 4.8.5.5.1). If an invocation fails due to lock timeout, the container will throw ConcurrentAccessTimeoutException.

Also see

EJB Concepts - Concurrency

Interceptors

The interceptor classes associated with a Singleton bean have the same lifecycle and concurrency behavior as that Singleton. Each interceptor class will be instantiated once per Singleton bean instance.

Restrictions

Singleton beans must not implement javax.ejb.SessionSychronization interface or use the session synchronization annotations.