Saturday 21 September 2013

Some new JEE6 Features: Asynchronous EJBs, Singletons and Futures

Asynchronous EJB Methods, Singletons and Futures

In this post I want to explore some new JEE6 features concerning EJBs and run them on the Raspberry Pi.
These features are

  • Singleton EJBs
  • Asynchronous EJB calls
  • Asynchronous EJB calls returning Futures

What are these elements?

Singleton EJB
As the name indicates, a Singleton EJB is a bean that will be instantiated exactly once in your application. Does not sound very spectacular but in fact it is. Whenever you will look up this bean you will always get the same instance. This goes for every client of the application.

Asynchronous EJB calls
It is now possible to code EJB methods that can be called asynchronously. You call the method and it returns immediately while it performs its task in the background. This is calling the method “Send-and-Forget” style. Just like sending a message via JMS.
If you want to keep in touch with the method, your method needs to return a Future object.

Asynchronous EJB calls returning Futures
When an asynchronous method returns a Future, you can keep in touch. The Future is your link to the running method. It offers an API to determine whether the method’s result is already available or not. If a value is ready to be retrieved you can fetch it.
Futures are very handy concept for certain applications. You can trigger a couple of calculations running concurrently, collect the Futures and scan them for results subsequently trickling in.  
There is one little drawback with using Futures in the context of EJBs: Future is just an interface and the Java default implementation AsyncResult is not serializable. An AsyncResult cannot be passed over Remote EJB interfaces. Using Future and AsyncResult requires you to carefully choose between local and remote interfaces and to modularize your EJBs properly.

Demo Application

Let’s have a look on the demo application.
The next picture will give an overview:


The whole thing consists of two JEE applications. A servlet and an ejb-module. Both are separate deployment units:
  • Servlet: LocalAsyncClient
  • Ejb-module: MyAsyncExample
All the new features are coded within the ejb.module. The servlet is only for triggering the action and for displaying the results.

Coding

The application is best described inside out, so let’s start with the heart of the matter, the ejb that offers asynchronous methods.
This bean is called RandomLengthTask. Here is the local interface:
package com.mtag.ejbs.async;
import java.util.concurrent.Future;
import javax.ejb.Asynchronous;
import javax.ejb.Local;

/**
 * EJB’s local interface.
 */
@Local
public interface RandomLengthTaskLocal {
    /**
     * This annotation is all it takes to make this function asynchronous.
     * When it is called it will return the Future immediately.
     */
    @Asynchronous
       public Future<string> performRandomTask();
      
    /**
     * Asynchronous but not returning anything.
     * Will return immediately.
     */
    @Asynchronous
    public void sendAndForget(long duration);
}
As can be seen, turning a regular method into an asynchronous one does not take much. It’s just one annotation.

Returning a Future is notable. The method returns it directly and only later fills in the value. The client can question the Future and eventually extract the result.
The Future is the reason for providing a local interface for our EJB. We cannot pass a Future over a remote connection. We need to structure our application accordingly. More on this structure later.
Let'ts take a look at the EJB's implementation:
package com.mtag.ejbs.async;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Random;
import java.util.concurrent.Future;
import java.util.logging.Logger;

import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;

/**
 * Session Bean implementation class RandomLengthTask
 */
@Stateless
public class RandomLengthTask implements RandomLengthTaskLocal {
 private static final Logger LOGGER = Logger.getLogger(RandomLengthTask.class.getName());
    /**
     * Default constructor. 
     */
    public RandomLengthTask() {
        // TODO Auto-generated constructor stub
    }
    
    /**
     * 
     * @param duration
     * @return void
     * Asynchronous Method returning immediately without a result value
     */
    @Asynchronous
    public void sendAndForget(long duration) {
     LOGGER.info("Send and Forget will take: " + duration + "ms");
     try {
      Thread.sleep(duration);
      LOGGER.info("Send and Forget: Waking up. Slept " + duration + "ms");
     } catch (InterruptedException e) {
      LOGGER.info("Send and Forget: Sleep was interrupted!");
     }
     LOGGER.info("Send and Forget has finished");
    }
    
    /**
     * Will return a Future immediately.
     * Eventually the .
     * The length of the task will be randomly generated between 1 second and 1 minute.
     */
    @Asynchronous
    public Future<String> performRandomTask() {
     // record starting time...
     Calendar cal = Calendar.getInstance();
     SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
     String started = sdf.format(cal.getTime());
     LOGGER.info("RandomTask started at: "+started);
     try {
      Thread.sleep(new Random(System.currentTimeMillis()).nextInt(60000)+1000);
     } catch (InterruptedException e) {
      LOGGER.info("RandomTask was interrupted...");
     }
     cal = Calendar.getInstance();
     LOGGER.info("RandomTask finished at: "+sdf.format(cal.getTime()));
     //
     // AsyncResult is the default implementation of the Future interface...
        return new AsyncResult<String>("Random Task Start: "+started+" / finished: "+sdf.format(cal.getTime()));
    }
}
The life of the sendAndForget method is a bit hard to monitor. After calling it lives a life of its own. Best we can do is to log its activities. Later, when running the servlet, we have to take a look at the console output once in a while.
The method takes the duration it is supposed to run as a parameter. We will set this duration from the servlet later.

The performRandomTask is a bit more interesting. It not only returns a Future (in fact it returns an AsyncResult which is the default implementation of Future) but generates its own duration randomly.
When finishing, it returns its start and finish time stamps as a result into the Future. This information can of course be accessed by our servlet.

We now have a bean that offers two types of asynchronous methods: a send-and-forget type returning void immediately and one returning a Future immediately supplying a value into that Future in the future :-).
The bean has a local interface because we cannot transport the Future over a remote call.
We will now write a Decorator bean wrapping the local interface and offering a remote one to the public.
This bean is called InBetweenBean as can be seen in the picture above.
Here is the code of its remote interface:
package com.mtag.ejbs.async;

import java.util.List;
import javax.ejb.Remote;

@Remote
public interface InBetweenBeanRemote {
    /**
     * Calls an asynchronous method and saves the result, a Future, in the
     * SessionManager Bean.
     */
 public void callLenghyTask(String sID);

    /**
     * Calls an asynchronous send-and-forget method with an instruction of how long to 
     * sleep (duration)
     */
 public void sendAndForgetTask(long duration);

     /**
     * Queries the SessionManagerBean for the results asspciated with a giben client (sid)
     * and returns a list of results.
     * @param sid
     * @return
     */
    public List<string> getResultList(String sid);
}

The method "sendAndForgetTask" is easy. It calls our asynchronous send-and-forget method returning void immediately. The amount of time this method shall run must be supplied by the client.
"callLegthyTask" is more interesting a we will see in a minute. It takes a session-id for a parameter which indicates to some session state that has to be handled.
The same goes for the "getResultList" method. It will return a session specific list of results.

Let's have a look at the implementation of this interface.
package com.mtag.ejbs.async;

import java.util.List;
import java.util.concurrent.Future;
import java.util.logging.Logger;

import javax.ejb.EJB;
import javax.ejb.Stateless;

import com.mtag.ejbs.async.SessionManagerLocal;

/**
 * Session Bean implementation class InBetweenBean
 */
@Stateless
public class InBetweenBean implements InBetweenBeanRemote {
 private static final Logger LOGGER = Logger.getLogger(InBetweenBeanRemote.class.getName());
 
 @EJB(mappedName = "java:global/MyAsyncExample/RandomLengthTask!com.mtag.ejbs.async.RandomLengthTaskLocal")
 RandomLengthTaskLocal rltBean;
 
 @EJB(mappedName = "java:global/MyAsyncExample/SessionManager!com.mtag.ejbs.async.SessionManagerLocal")
 SessionManagerLocal sessionManager;
    /**
     * Default constructor. 
     */
    public InBetweenBean() {
        // TODO Auto-generated constructor stub
    }
    
    /**
     * Calls an asynchronous task returning a Future.
     * This Futute is stored within the SessinManager Singleton EJB
     */
    public void callLenghyTask(String sID) {
     LOGGER.info("calling RLTask...");
     Future<String> result = rltBean.performRandomTask();
     //
     // Get SessionState for this Client...
     SessionState ss = sessionManager.getSessionState(sID);
     // Add the Future...
     ss.addResult(result);
     // Give StateObjekt back to SessionManager...
     sessionManager.addSessionState(sID, ss);
     LOGGER.info("RLTask has finished...");
    }
    
    /**
     * Calls a send-and-forget task...
     */
    public void sendAndForgetTask(long duration) {
     LOGGER.info("calling SendAndForget-Task...");
     rltBean.sendAndForget(duration);
     LOGGER.info("SendAndForgetTask finished...");
    }
    
    /**
     * Returns the SessionState of a given client as String-List.
     * A String-List is serializable...
     * @param sid
     * @return
     */
    public List<String> getResultList(String sid) {
     SessionState ss = sessionManager.getSessionState(sid);
     return ss.getResultsAsStringList();
    }
    
}

The first thing I'd like to mention here, are the two @EJB-annotations.
They are injecting EJB references into the respective local variables. Do you still remember how this had to be done in the early days of J2EE? You had to maintain monstrous xml-files describing your beans and including all the references form one to the other. Now one annotation does it all. I don't even have an xml-file to maintain explicitly in this project (though I'm not quite sure if I can keep this up during the course of this blog). Anyway, JEE has come a long way.
In case you ask yourself where theses JNDI-names come from, the JEE specification defines some of those "global" ones. Others are defined by JBoss. One sure way to have them right is to deploy the beans you already implemented. JBoss publishes the names on the console and wrights them to the log-files.

Ok, now we have a reference on the bean that implements the asynchronous methods and a reference on on a bean called SessionManager.
We'll discuss the SessionManager bean later in more detail, because it is another new JEE feature.
For now just take a look at the implementation of the "callLengthyTask" method.
First we call an asynchronous method receiving a Future.
Then we call the Session Manager for the session state of the current client, identified by its session id.
Next we add the Future to this session state and store the session state back to the Session Manager.
Eventually the Future we've just given away to the Session Manager will be supplied with a value from the concurrently running asynchronous method.
To see these values, a client can call the "getResultList" method of our InBetweenBean.
The getResultList-method calls the Session Manager for this client's session state and returns this state as a serializable list of strings. This list can be transported over a remote connection like a remote EJB call.
As you can see, InBetweenBean does not much but wraps functionality supplied by others.

Taking a look at the SessionManager bean and its little POJO helper SessionState wraps up the ejb-module.

Here are interface and implementation of the SessionManager EJB:
package com.mtag.ejbs.async;

import javax.ejb.Local;

@Local
public interface SessionManagerLocal {
    /**
     * @param sessionId
     * @return SessionState
     */
    public SessionState getSessionState(String sessionId);
    
    /**
     * Adds a SessionState to the Hashmap of 
     * @param sid
     * @param ss
     */
    public void addSessionState(String sid, SessionState ss);
}

package com.mtag.ejbs.async;

import java.util.HashMap;
import javax.ejb.Singleton;
import com.mtag.ejbs.async.SessionState;

/**
 * Manages a Hashmap of SessionState objects.
 * Key to the hashmap is a client's session id.  
 * 
 */
@Singleton
public class SessionManager implements SessionManagerLocal {
 private HashMap<String, SessionState> sessions = new HashMap<String, SessionState>();
  
    /**
     * Default constructor. 
     */
    public SessionManager() {
        // TODO Auto-generated constructor stub
    }
    
    /**
     * Store SessionState in the Hashmap
     * @param sid clients session id
     * @param ss  SessionState object
     */
    public void addSessionState(String sid, SessionState ss) {
     sessions.put(sid, ss);
    }
    
    /**
     * Retrive the session state of a given client.
     * If this is the first call a clien, a session state object will
     * created, stored and returned.
     * @param sessionId
     * @return SessionState
     */
    public SessionState getSessionState(String sessionId){
     SessionState state = null;
     state = sessions.get(sessionId);
        if (state == null) {
         state = new SessionState();
         sessions.put(sessionId, state);
        }
     return state;
    }
}
And finally the SessionState class: a POJO maintained by the SessionManager:
package com.mtag.ejbs.async;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * 
 * @author vkoster
 *
 * Store for Session State, both
 * - Session State and
 * - Resource State
 * Substitutes a little database 
 */
public class SessionState implements java.io.Serializable {
 private static final long serialVersionUID = 1L;
 private List<Future<String>> myList = new ArrayList<Future<String>>();
 
 public void addResult(Future<String> f) {
  myList.add(f);
 }
 
 /**
  * Transform a list of Futures into a list of strings
  * @return
  */
 public List<String> getResultsAsStringList() {
  List<String> rl = new ArrayList();
  
  for (Future<String> f : myList) {
   try {
    if (f.isDone()){
     rl.add(f.get());
    } else {
     rl.add("No reuslt yet!");
    } 
   } catch (CancellationException e) {
    rl.add("Calculatioin cancled!");
   } catch (ExecutionException e) {
    rl.add("Execution error!");
   } catch (InterruptedException e)  {
    rl.add("Calculation interrupted!");
   }
  }
  return rl;
 }
}

The SessionManager bean is annotated as @Singleton.
This is all it takes to accomplish the following:
  • The EJB is a singleton (obviously)
  • There will only be one instance of this bean, regardless of how many clients will access it
  • All clients will get exactly this one instance when they call this bean
  • The bean is comparable to a process with identity and addressability
Who is responsible for managing all this concurrency?
If you don't say otherwise, the ejb-container will do it for you. This is called "Container Managed Concurrency". If you prefer to take things into your own hands, there are annotations for this too.
I can do with container managed concurrency in this example.

A Singleton comes in handy for our purposes. It stores the session state of all the clients concurrently using out asynchronous ejb-module.
Whenever a client uses our ejb-module by calling a method that returns a Future, we add this Future to the session state of this client and store it within the Singleton. All the client has to do is to supply a Session ID to identify itself in subsequent calls.

The Session State itself is a simple List of Futures.
Remember: these Futures will receive their results eventually.
SessionState offers to translate the current state of this list of Futures into a String-list.
The String-list can be sent to remote clients which then can visualize the current state of the session.

Deployment



...to be continued...

Sunday 18 August 2013

Running JBoss AS7 on Raspberry Pi

Running JBoss

Choose a Mode

The JBoss installation on our Pi offers a couple of different configurations out of the box.
The first choice to be taken is whether to start JBoss in standalone or domain mode. 
Doman mode is a special management mode which we might inspect later. For now we will set off in standalone mode. This just means we will have to configure each instance individually. We can still cluster our standalone instances and even go for high availability in standalone mode.

Choose a Configuration

All the scripts for starting JBoss are located in JBOSS_HOME/bin.
JBoss is started in standalone mode by running standalone.sh:
standalone.sh
Without any parameters, standalone.sh will use the configuration defined in standalone.xml, located in JBOSS_HOME/standalone/configuration directory.
You can choose another configuration by specifying it on the command line:
standalone.sh –server-config=standalone-full.xml

My approach is to backup standlone.xml and to edit the original according to my needs. I’m going for standalone.xml to have a small footprint to start with. Additional features can be included later, either by editing standalone.xml or by using the management console or the command line interface CLI.

JBoss and Java

Standalone.sh inspects first JAVA then JAVA_HOME environment variable for a hint, where java is installed. If both variables are not set, JAVA is simply set to java which means the PATH variable determines if and where Java will be found.
And it will be found like this:
  • We find /usr/bin in our classpath (verify by typing $PATH on a Pi console)
  • /usr/bin contains “java”
  • Java is a softlink into alternatives  (/etc/alternatives/java)
  • Following this link, we find: java -> /usr/lib/jvm/java-7-openjdk-armel/jre/bin/java
And that is what we get when we run Java on the Pi.
Everything depends on soft links and the alternatives concept. This makes it very easy to switch to another Java installation in the future.
To make a long story short, leave everything as it is.

Making JBoss available within Your Network

All my Pis have static IP addresses within my private network. This can be configured within your router.
If you want to be able to reach a JBoss instance running on a Pi, you have to configure JBoss’ “Public Interface”.
This configuration is done standalone.xml located in /JBOSS_HOME/standalone/configuration.
Find the interfaces section and edit the public and the management interface like this:
<interfaces>
        <interface name="management">
            <inet-address value="xxx.xxx.xxx.xxx"/>
        </interface>
        <interface name="public">
            <inet-address value="xxx.xxx.xxx.xxx"/>
        </interface>
</interfaces>
Where xxx.xxx.xxx.xxx is the IP you configured in your rooter for this specific Pi.

Save the changes.

Create JBoss Users

In order to access JBoss’ admin console, we need to create a management-realm user.
This is done by running the add-user.sh script located in /JBOSS_HOME/bin directory.
Be sure to select management realm.







For later use, we create an application-realm user.
For now, assign the guest role to this user.







Starting JBoss

Let’s give JBoss a test run.
Switch to /JBOSS_HOME/bin and run standalone.sh in a Pi terminal window:
sh standalone.sh











When JBoss is up, you can access the web-server from any client within your network.
If you assigned a name to your Pi within your router, you can use this name to access the Pi. If not, use the Pi’s IP address.

 From here, you should be able to access the management console. As credentials, enter the admin-user you just created using add-user script.













Stopping JBoss

The best way to stop JBoss is by using the CLI.
Open another terminal session on the Pi and switch to /JBOSS_HOME/bin.
Run
jboss-cli.sh
The CLI starts in “disconnected” mode, so you have to connect.
Type connect xxx.xxx.xxx.xxx (IP address of your Pi)
When connected successfully, enter
:shutdown
JBoss will shut down and you can exit the terminal session.











Summary

Now we have Java and JBoss installed on our Pi(s).
JBoss is now accessible from anywhere within our network.
We created a management-user and an application-user.
We can start and stop JBoss on the Pi and have access to its management console.
In the next post we will develop our first JEE application and deploy it to the Pi.
See you then…

Tuesday 13 August 2013

Side Note: Accessing the Pi

Accessing the Pi

This blog assumes that your Pi is connected to a network, preferably with access to the internet for easy updates. But of course, everything discussed here can be done in a closed network too.
Apart from the network you don’t need anything. No monitor, no keyboard.
You can easily access your Pi remotely when you enable the ssh service during setup.
From now on you can access it from any client within your network.

Use ssh from any Linux client or putty from a windows client.

Let’s do something practical: Connecting to the Pi from a windows client and checking the Java installation.
Power up your Pi.
Open a putty session on a windows machine, selecting ssh as connection type.

This will start a terminal window where you will have to enter your credentials.
Check the Java installation by typing:
java -version
You should see something like this:

Ok, openJDK seems to be installed properly.
In order to shut your pi down, type:
sudo shutdown –h now

and close the terminal window.

Thursday 8 August 2013

Setting up the Raspberry Pi installing Debian. Java and JBoss

Setting up the Pi  

Before we can start playing JEE on the Raspberry Pi, a few things need to be set up.
As this is not too interesting, I try to cover it in a hurry. Please leave a note if you want one topic or the other dealt with in more detail.

What this post will cover:

  • Choosing and installing a suitable operating system for your Pi
  • Installing Java on the Pi
  • Installing JBoss on the Pi
  • Setting up the Pi network

Choosing and installing a suitable operating system for your Pi

The first task now is to choose and install a suitable operating system for your Pi.
There are several options available on the download page of the Raspberry Pi Foundation: http://www.raspberrypi.org/downloads
We go for Soft-float Debian “wheezy” for the reasons described on the page:
This image is identical to the Raspbian “wheezy” image, but uses the slower soft-float ABI. It is only intended for use with software such as the Oracle JVM which does not yet support the hard-float ABI used by Raspbian.”
 If we want to run java, what we do, we must stick to an operating system offering a soft-float ABI.
I tried the Java8 preview offered by Oracle here: http://jdk8.java.net/download.html which is supposed to support the hard-float ABI. But sorry, this works only when running Java in client mode. As soon as your software needs server-mode, you are out of the game.
This is also true for the embedded version of the Standard Edition.
Do we need server mode? Yes, because software like JBoss AS7 needs it.
So as of now (at the time of this writing) the soft-float Debian “wheezy” seems like a good idea for starting off:
  • Download soft-float Debian “wheezy” image
  • Bring the image to your sd-card
  • Start the Pi and run through the config-script that will start up on first boot
Hint: The config-script now offers to assign a hostname to your Pi. It is a good idea to make use of this. Later, when you have a couple of console windows open on your desktop machine pointing to different Pis, you will be glad to see meaningful prompts identifying the Pis respectively (of course you can change the hostname of your Pi later, but using the config-script is easier).
Later, when plugging your Pis into your network, you want to add these names to your router’s configuration.

Installing Java JDK on the Pi

The next step is installing Java on your Pis.
Software like the Oracle Java 8 preview would have to be installed manually.
The regular Java versions are maintained in the Debian software repositories and can easily be installed by Debians package manager.
I chose this package and installed it with apt-get.
Open up a console and enter:

sudo apt-get install openjdk-7-jdk

After the dust has settled, you have an openJDK 7 on your Pi.

Installing JBoss AS7 on the Pi

When installing JBoss, a little bit more manual effort is required. Here is what you have to do:

Step 1: Download the package

At the time of this writing, JBoss AS7 was available in version 7.1.1.Final.
You can download this package from the console using wget:

sudo wget http://download.jboss.org/jbossas/7.1/jboss-as\
 -7.1.1.Final/jboss-as-7.1.1.Final.tar.gz

Step 2: Extract the download 

Now that we have the tar-file on the pi we have to extract it into a suitable directory.
/usr/local is a good choice:

sudo tar zxvf jboss-as-7.1.1.Final.tar.gz -C /usr/local

(don't forget the -C option or the necessary directories will not be created)

Step 3: Smoothen the installation directory

JBoss AS7 is now installed in /usr/local/jboss-as-7.1.1.Final
If you find this to be a bit unhandy, change it like this:

sudo mv jboss-as-7.1.1.Final/ jboss7

Step 4: Make pi the owner of the installation

I like my pi user to be the owner of the installation.
You can do this with the Change Owner command:
sudo chown -R pi:pi /usr/local/jboss7/

JBoss AS7 is now installed and ready to run on your Raspberry Pi.
Quite some heavy lifting for a little Pi like that. But we'll see JBoss behaves itself very well.

Network configuration

My setup consists of 3 Raspberry Pis plugged into the local network behind my router.
On the router assigned static IP addresses and logical names to them. The Pis are named “frodo”, “samwise” and “gandalf”. 
Naming your Pis according to your rooter's configuration will help you to stay on top of things later.

Before getting serious with playing JEE on the Pi we'll have to do some minor configurations on JBoss.
But I leave this for the next post.

Wednesday 7 August 2013

Why this blog?

Why this blog?

This blog was inspired by a very interesting enterprise architecture project I had the pleasure of being part of. Two reasons made this project somehow more interesting than others. The architecture was supposed to cover service integration spanning the cloud, data center hosted services and services running on small and very small devices operated in the field. On top of that a lot of these field devices were manufactured by the customer himself, making them quite propriety.
This translates into distributed enterprise computing in a very heterogeneous environment.
Perfect fit for the by now quite mature JEE technologies?
In the end, only time will tell. But what we’ve seen so far looks really promising.
Anyway, we used a lot of “heavy weight” JEE technologies on very limited devices. And we are still experimenting.
This blog describes some of these efforts.
I choose the Raspberry Pi, or Pi for short, for representing our small field devices because it is easily available and quite cheap. Two or three Pis in a local network and JEE computing suddenly becomes very tangible and a lot of fun (if you have the kind of humor for this).

If you find this to be interesting, keep on reading and let me know what you think.