| Title: Singleton Beans |
| <a name="SingletonBeans-SingletonOverview"></a> |
| # Singleton Overview |
| For the first time in years EJB has a new bean type, the *@Singleton*. In |
| my opinion, the javax.ejb.Singleton will replace a lot of what people are |
| using @Stateless for today. |
| |
| The Singleton is essentially what you get if you take a Stateless bean and |
| adjust the pool size to be exactly 1 resulting in there being exactly one |
| instance of the Singleton bean in the application which can be invoked |
| concurrently by multiple threads, like a servlet. It can do everything a |
| Stateless can do such as support local and remote business interfaces, web |
| services, security, transactions, and more. Additionally, the Singleton |
| can have its @PostConstruct method called with the application starts up |
| and its @PreDestroy method called when the application shuts down. This |
| allows it to serve as an application lifecycle listener which is something |
| only Servlets could do before. It has an *@Startup* annotation which is |
| similar in concept to the servlet <load-on-startup>, but unlike servlets it |
| doesn't take a number as an argument. Instead, you can use an *@DependsOn* |
| annotation to say which other Singletons you need and the container will |
| ensure they start before you. |
| |
| See the [Singleton Example](singleton-example.html) |
| for sample bean code and client. |
| |
| <a name="SingletonBeans-Concurrency"></a> |
| ## Concurrency |
| |
| Singletons support two modes of concurrent access, Container-Managed |
| Concurrency (the default) and Bean-Managed Concurrency. |
| |
| <a name="SingletonBeans-Bean-ManagedConcurrency"></a> |
| ### Bean-Managed Concurrency |
| |
| With Bean-Managed Concurrency, annotated as *@ConcurrencyManagement(BEAN)*, |
| the container sends all invocations into the bean and lets the Singleton |
| bean instance decide how and when to synchronize access, if at all. Here |
| the 'synchronization' keyword is allowed as well as the full |
| javax.util.concurrent set of libraries. |
| |
| <a name="SingletonBeans-Container-ManagedConcurrency"></a> |
| ### Container-Managed Concurrency |
| |
| With Container-Managed Concurrency, annotated as |
| *@ConcurrencyManagement(CONTAINER)*, the container will enforce concurrency |
| for you via locking method access to the bean. Two modes, called locks |
| exist and can be assigned to both the bean class and methods of the bean |
| class. |
| |
| <a name="SingletonBeans-Locktype"></a> |
| #### Lock type |
| |
| The first and the default is a "write" lock, annotated as *@Lock(WRITE)*. |
| Essentially, with a write lock the caller holds an exclusive lock on the |
| bean for the duration of the method call and all other threads for that or |
| any other method must wait. |
| |
| The second option is a "read" lock, annotated as *@Lock(READ)*. The read |
| lock allows full concurrent access to the methods (assuming no write locks |
| are held). The default mode of "write" essentially makes your bean a |
| single-threaded bean, which is very slow. The more conservative |
| @Lock(WRITE) was chosen as the default as this is how all the other bean |
| types work (only a single thread may access a bean instance at any given |
| time). Those that are aware of how to handle concurrent access can easily |
| put @Lock(READ) on their bean class, thus changing the default, and then |
| @Lock(WRITE) on specific methods if needed. |
| |
| The locking modes of Container-Managed Concurrency map directly to the *[java.util.concurrent.ReadWriteLock](http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/ReadWriteLock.html) |
| * API which looks like this: |
| |
| public interface ReadWriteLock { |
| /** |
| * Returns the lock used for reading. |
| * |
| * @return the lock used for reading. |
| */ |
| Lock readLock(); |
| |
| /** |
| * Returns the lock used for writing. |
| * |
| * @return the lock used for writing. |
| */ |
| Lock writeLock(); |
| } |
| |
| |
| Literally 100% of the Singleton locking we're talking about is taken from |
| this interface and its javadoc is a great source of information. It's safe |
| to imagine that under the covers the Singleton Container has an instance of |
| ReadWriteLock which it uses to enforce the locking for all the Singleton |
| bean's methods. Essentially: |
| |
| - @Lock(READ) == theSingletonReadWriteLock.readLock().lock() |
| - @Lock(WRITE) == theSingletonReadWriteLock.writeLock().lock() |
| |
| The EJB container may use something other than ReadWriteLock but the |
| semantics of a ReadWriteLock must be followed. Internally, we use an |
| instance of [java.util.concurrent.ReentrantReadWriteLock](http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html) |
| which supports correct memory synchronization, some reentrancy, lock |
| downgrading, and [more|http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html] |
| . |
| |
| <a name="SingletonBeans-AcquiringtheLock"></a> |
| #### Acquiring the Lock |
| |
| The *@AccessTimetout* annotation can configure how long a thread will wait |
| to acquire the read or write lock. This annotation can be used on the bean |
| class or individual methods. The annotation maps directly to the [java.util.concurrent.locks.Lock](http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/locks/Lock.html) |
| interface. |
| |
| public interface Lock { |
| |
| /** |
| * Blocks (potentially) forever |
| * |
| * @AccessTimout with a value of -1 |
| */ |
| void lock(); |
| |
| /** |
| * Non-blocking |
| * |
| * @AccessTimout with a value of 0 |
| */ |
| boolean tryLock(); |
| |
| /** |
| * Blocks (potentially) up to a limit |
| * |
| * @AccessTimout(30, TimeUnit.SECONDS) |
| */ |
| boolean tryLock(long time, TimeUnit unit) throws InterruptedException; |
| |
| } |
| |
| |
| In the event it is not possible to acquire the lock a |
| *javax.ejb.ConcurrentAccessException* or |
| *javax.ejb.ConcurrentAccessTimeoutException* will be thrown. |
| |
| <a name="SingletonBeans-DefaultTimeout"></a> |
| #### Default Timeout |
| |
| The default value of *@AccessTimeout* annotation is vendor specific. In |
| OpenEJB it defaults to the value of the *AccessTimeout* property which can |
| be configured in many different scopes. Here is the order of preference: |
| |
| 1. bean-level in |
| openejb-jar.xml/<openejb-jar>/<ejb-deployment>/<properties> |
| 1. jar-level in openejb-jar.xml/<openejb-jar>/<properties> |
| 1. container-level in openejb.xml/<openejb>/<Container> |
| 1. boot-level via InitialContext(Properties) or |
| EJBContainer.createEjbContainer(Map<Object,Object>) |
| 1. system-level in System.getProperties() |
| |
| The value of the property can be phrased in plain english such as "1 hour |
| and 23 minutes and 17 seconds" see [Configuring Durations](configuring-durations.html) |
| for details. |
| |
| <a name="SingletonBeans-StartupandStartupOrdering"></a> |
| ## Startup and Startup Ordering |
| |
| Singletons have an *@Startup* annotation which can be applied to the bean |
| class. When used, the Container will instantiate the Singleton instance |
| _eagerly_ when the application starts up, otherwise the Container will |
| instantiate the Singleton instance _lazily_ when the bean is first |
| accessed. |
| |
| If one Singleton refers to another Singleton in the @PostConstruct or |
| @PreDestroy method, there must be some measure taken to ensure the other |
| Singleton exists and is started. This sort of ordering is achieved with |
| the *@DependsOn* annotation which can be used to list the names of |
| Singleton beans that must be started before the Singleton bean using the |
| annotation. |
| |
| |
| @DependsOn({"SingletonB", "SingletonC"}) |
| @Singleton |
| public class SingletonA { |
| |
| } |
| |
| |
| Circular references are not supported. If BeanA uses @DependsOn to point |
| to BeanB and BeanB also uses @DependsOn to point at BeanA, the result is a |
| deployment exception. Be aware that circular references can happen in less |
| trivial ways such as A referring to B which refers to C which refers to D |
| which refers back to A. We will detect and print all circular dependencies |
| (called circuits) at deploy time. |
| |
| Note that @DependsOn is only required (and should only be used) if a |
| Singleton *uses* another Singleton in its @PostConstruct method or |
| @PreDestroy method. Simply having a reference to another Singleton and |
| using it in other business methods does not require an @DependsOn |
| declaration. The @DependsOn allows the Container to calculate the correct |
| startup order and shutdown order so that it can guarantee the Singletons |
| you need are available in your @PostConstruct or @PreDestroy methods. All |
| Singletons will automatically be available to your business methods |
| regardless if @DependsOn is used. Because of the greater chance of |
| creating circular dependencies, it is better not to use the @DependsOn |
| annotation "just in case" and should only be used when truly needed. |
| |
| <a name="SingletonBeans-XMLandAnnotationOverriding"></a> |
| # XML and Annotation Overriding |
| |
| Singletons can be declared in the ejb-jar.xml as follows: |
| |
| <ejb-jar> |
| <enterprise-beans> |
| <session> |
| <ejb-name>MySingletonBean</ejb-name> |
| <ejb-class>org.superbiz.MySingletonBean</ejb-class> |
| <session-type>Singleton</session-type> |
| <load-on-startup/> |
| <depends-on> |
| <ejb-name>SingletonFoo</ejb-name> |
| <ejb-name>SingletonBar</ejb-name> |
| </depends-on> |
| </session> |
| </enterprise-beans> |
| </ejb-jar> |
| |