EJB3.1 Singleton Beans in AS 6.0.0 M3

Overview

 

 

JBoss AS 6.0.0.M3 which was released on May 5th 2010, introduces support for EJB3.1 Singleton beans.

 

 

What to download and how to use

 

 

You can download JBoss AS 6.0.0.M3 from here. After downloading the AS, start and stop it once to make sure it boots without any issues.

 

 

The next step would be to deploy a EJB3.1 Singleton bean into this server.

 

 

EJB3.1 Singleton bean:

 

 

Note that the examples shown below are just for the sake of illustrating the usage of singleton beans and as such don't hold much meaning.

 

 

Let's deploy a very simple singleton bean which exposes a remote view:

 

 

package org.jboss.ejb3.singleton.example;


public interface Counter
{
    void incrementCount();
    
    void decrementCount();
    
    int getCount();
}


 

 

package org.jboss.ejb3.singleton.example;


import javax.ejb.EJB;
import javax.ejb.Remote;
import javax.ejb.Singleton;


import org.jboss.ejb3.annotation.RemoteBinding;


@Singleton
@Remote(Counter.class)
@RemoteBinding (jndiBinding = "SimpleCounterRemoteJNDIName")
public class SimpleCounter implements Counter
{


    // we use a calculator to increment/decrement the count
   @EJB
   private Calculator calculator;


    // Maintains the current count
   private int count;


   @Override
   public int getCount()
   {
      return this.count;
   }


   @Override
   public void incrementCount()
   {
      this.count = this.calculator.add(this.count, 1);
      
   }


   @Override
   public void decrementCount()
   {
      this.count = this.calculator.subtract(this.count, 1);
      
   }
}

 

 

 

package org.jboss.ejb3.singleton.example;


import javax.ejb.Singleton;


@Singleton
public class Calculator
{
   public int add(int a, int b)
   {
      return a + b;
   }
   
   public int subtract(int a, int b)
   {
      return a - b;
   }
}


 

 

So in the example above, we have a Counter interface which is exposed as the remote view for the SimpleCounter Singleton bean. Notice that the SimpleCounter class is marked with @Singleton annotation:

 

 

@Singleton
@Remote(Counter.class)
@RemoteBinding (jndiBinding = "SimpleCounterRemoteJNDIName")
public class SimpleCounter implements Counter
{
...


 

 

The SimpleCounter internally uses a Calculator to do the increment and decrement operations. As you can see, the Calculator is being injected into the SimpleCounter by using a @EJB annotation:

 

 

    // we use a calculator to increment/decrement the count
   @EJB
   private Calculator calculator;


 

 

If you look at the Calculator class, you will notice that it is a singleton bean with a no-interface view:

 

 

@Singleton
public class Calculator
{
...

 

 

So effectively, in this example, we have 2 singleton beans. One is exposing a remote view and the other is exposing a no-interface view.

 

 

Now package all these classes into a .jar and deploy it to the server which you downloaded earlier. That's it! You now have the beans deployed on the server. The next step is to write a simple client which access the Counter to perform the operations. In this example, let's use a standalone java class which through its main() method, looks up the remote view of the SimpleCounter and invokes the operations. Here's the client:

 

 

package org.jboss.ejb3.singleton.example.client;
 
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.jboss.ejb3.singleton.example.Counter;
 
public class Client
{
   public static void main(String args[]) throws Exception
   {
      Context ctx = new InitialContext();
      // lookup the counter bean
      Counter counter = (Counter) ctx.lookup("SimpleCounterRemoteJNDIName");
      
      System.out.println("Initial count is " + counter.getCount());
      
      // let's increment once
      counter.incrementCount();
      
      System.out.println("Count after increment is " + counter.getCount());
      
      // now let's just look up the counter once more
      // and see whether the incremented state is still maintained (it should be!)
      Counter oneMoreCounter = (Counter) ctx.lookup("SimpleCounterRemoteJNDIName");
      
      // should be 1
      System.out.println("Count from another counter is " + oneMoreCounter.getCount());
      
      // now let's decrement
      oneMoreCounter.decrementCount();
      
      // should be 0
      System.out.println("Count after decrementing is " + counter.getCount());
   }
 
}

 

 

In the client code, we first lookup the SimpleCounter singleton bean and try out a couple of operations through it. We then again lookup the same singleton bean and try out some more operations on it. Remember that since it's a singleton bean, all these operations will finally end up being called on the same singleton bean instance. So effectively, you will have a single state irrespective of the proxy instance on which you are invoking the operations.

 

 

 

What should I try next?

 

 

The above example was just to get you started with EJB3.1 Singleton beans. Try out the singleton beans within your own applications and let us know if you run into any issues. Feel free to start a discussion about any issues around this, in our EJB3 user forum or ping us on IRC. The more issues you find now, the better - because we can get some of them fixed before AS 6.0.0.M3 is released.

 

 

 

I have some tutorial for singleton beans, Can I contribute?

 

 

Similar to our other EJB3 tutorials, we are going to include a tutorial for singleton beans. Infact, the example that is posted here in the wiki, can perhaps be just added as a tutorial in SVN. If anyone of you wants to contribute a different tutorial and a chapter in our guide, then feel free to let us know - either through the forums or IRC.

 

 

Known issues:

 

 

Currently there are a couple of known-issues in the singleton bean implementation:

 

 

1) PostConstruct/PreDestroy are not invoked in a transactional context EJBTHREE-2070

2) The @DependsOn for a Singleton bean is not yet implemented