Have you ever wondered how stateless an EJB3 Stateless Session Bean is? Well, I have, I wrote a test program and I got some interesting and – for me – surprising results, that I wanted to share.

My original understanding (or let’s call it mis-understanding) was, that the JEE server has a pool of EJB instances for each bean class, that you get one of those beans injected for each @EJB annotation, and that all those injections happen immediately upon entrance into the container via a top-level call.

A call to a service bean via SOAP is such a top-level call. I expected, that the injections not only happen in the called bean, but also somehow happen along the whole call graph, meaning that not only EJB references in the top-level service bean would be satisfied via injection, but also in beans referenced by that bean and so on.

Finally I expected that if two beans reference the same type of bean, they would actually get the same instance. I really have never thought the whole thing through, I simply expected some diffuse sort of magic.

The idea was, that some ServiceBean would get a value, either via parameters or from elsewhere (actually I thought of HTTP headers), store that information in some StorageBean, and then call a WorkerBean. The WorkerBean or some other code down the call graph would then retrieve that information from the StorageBean. In order for this to work, the StorageBean injected into the ServiceBean would have to be the same instance as the StorageBean injected into the WorkerBean, and the StorageBean would have to be exclusively allocated to that one thread for the whole duration of the top-level call, or else there would be a time interval between when the value gets being set and the time when it is read in the WorkerBean, leading to the usual multi-threading troubles.

I wanted a StorageBean to have some instance variables, wanted to fill them somewhere in the program, and wanted to read them elsewhere, without having to pass them around as parameters. In other words, I wanted a Stateless Session Bean to have some state, and I hoped that the container would guarantee consistency of this state for the time of one top-level call.

I’m pretty sure this is still not clear, so let’s look at some code. Here is a Singleton that generates random numbers:

package com.manessinger.test.stateless.backing;
 
import java.util.Random;
 
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.LocalBean;
 
@LocalBean
@Singleton
public class RandomGen {
 
    private Random r;
 
    @PostConstruct
    public void init() { r = new Random(); }
 
    public int nextInt() { return r.nextInt(); }
}

The StorageBean could be something like

package com.manessinger.test.stateless.backing;
 
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
 
@LocalBean
@Stateless
public class StorageBean {
 
    private int value;
 
    public void setValue(int value) { this.value = value; }
    public int getValue() { return value; }
}

A first shot at the ServiceBean could be

package com.manessinger.test.stateless.service;
 
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.jws.WebService;
 
import com.manessinger.test.stateless.backing.RandomGen;
import com.manessinger.test.stateless.backing.StorageBean;
import com.manessinger.test.stateless.backing.WorkerBean;
 
@Stateless
@WebService
public class ServiceBean {
 
    @EJB StorageBean s;
    @EJB WorkerBean  w;
    @EJB RandomGen   rand;
 
    public boolean test1() {
        int i = rand.nextInt();
        s.setValue(i);
        boolean isCorrect = w.verify1(i);
        return isCorrect;
    }
}

and here is finally the worker:

package com.manessinger.test.stateless.backing;
 
import javax.ejb.EJB;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
 
@LocalBean
@Stateless
public class WorkerBean {
 
    @EJB StorageBean s;
 
    public boolean verify1(int i) {
        int value = s.getValue();
        boolean isCorrect = (value == i);
        if (!isCorrect) {
            System.err.println(String.format("Error: expected %d, got %d", value, i));
        }
        return isCorrect;
    }
}

Thus the ServiceBean retrieves a random value, uses it to set the value of the StorageBean, and then passes the value into a verify() method of the worker. The worker retrieves the value from the StorageBean, compares it with its parameter, and returns true if they are the same value.

Try it for yourself: call the ServiceBean from the web service tester in the GlassFish Administration Console and it will just work. It’s EJB3 and EJBs are just POJOs after all, right?

Wrong. Sure, it does work, but now try to call the test method from a load testing application like Apache Jakarta JMeter. Try a thread group with 15 threads, a ramp-up period of one second, and 50 iterations. This makes for a total of 750 calls with a high degree of parallelity. Now look at the server log and you will see lines like

...
SEVERE: Error: expected 781730157, got -1784951881
SEVERE: Error: expected 781730157, got -1093939097
SEVERE: Error: expected -1093939097, got 540930629
SEVERE: Error: expected -1093939097, got 1481982330
...

Funny, huh? And look at the numbers: this is a typical effect in a program that is not thread-safe. Consecutive calls get mixed up.

My next idea was a variant:

    public boolean test2() {
        int i = rand.nextInt();
        s.setValue(i);
        boolean isCorrect = w.verify2(i, s);
        return isCorrect;
    }

and

    public boolean verify2(int i, StorageBean sParam) {
        int value = sParam.getValue();
        boolean isCorrect = (value == i);
        if (!isCorrect) {
            System.err.println(String.format("Error: expected %d, got %d", value, i));
        }
        return isCorrect;
    }

This means that I don’t let the StorageBean be injected into the worker, instead I pass it down as a parameter. Funnily enough, this did not work either. Under load it showed the same effect. Only when I finally passed the value in something that was really only a POJO, it did work:

package com.manessinger.test.stateless.backing;
 
public class StorageNonBean {
 
    private int value;
 
    public void setValue(int value) { this.value = value; }
    public int getValue() { return value; }
}
    public boolean test3() {
        int i = rand.nextInt();
        StorageNonBean snb = new StorageNonBean();
        snb.setValue(i);
        boolean isCorrect = w.verify3(i, snb);
        return isCorrect;
    }

and

    public boolean verify3(int i, StorageNonBean snbParam) {
        int value = snbParam.getValue();
        boolean isCorrect = (value == i);
        if (!isCorrect) {
            System.err.println(String.format("Error: expected %d, got %d", value, i));
        }
        return isCorrect;
    }

Of course the latter is trivial, but the consequences of this little test are clear:

Stateless Session Beans are really meant to be stateless. In fact the EJB 3.0 final specification says in section 4.5 that:

Because all instances of a stateless session bean are equivalent, the container can choose to delegate a client-invoked method to any available instance. This means, for example, that the container may delegate the requests from the same client within the same transaction to different instances, and that the container may interleave requests from multiple transactions to the same instance.

The only thing that the container guarantees, is that one bean will be exclusively allocated to a transaction (and therefore a thread) for the time of the invocation of one of its own methods. This does not extend to other EJBs that it calls. There is no guarantee that we call the same instance of StorageBean, if we call storage.setValue() and storage.getValue() even consecutively from the same ServiceBean, one call immediately after the other, and even if it were the same instance, there is no guarantee, that the storage has not been modified by another instance of the service bean.

Why did I ever get the idea that this construct could work? Well, probably it’s the fact, that the injection of a persistence context always gives you access to the same context (or at least the same data). I don’t know, but in any case I found it important to clarify things, because I have the impression that my mis-understanding is not completely uncommon, and when you fall into that pit, you may not recognize it until your system is under heavy load.

 

It’s only a few days since I’ve posted my Eclipse / GlassFish / Java EE 6 Tutorial, but due to the fact that it took me so long to write it, the toolset that I used is already outdated.

In the meantime Oracle has published a bugfix release to GlassFish v3, their reference implementation of Java EE 6 (and still the only implementation available), and of course Eclipse 3.6, code name “Helios”, has arrived. The last two days I had a deeper look into the combination, and I can tell that it works :)

Overall Impressions

Some bugs have been fixed, for example it is no problem now to restart the server, and the bug with libraries having been added to an EAR’s lib directory being “forgotten”, is gone as well.

At the moment I see only one major annoyance, and that is that re-publishing an application to the server tends to fail. The workaround is, to not manually re-publish, but instead use Add and Remove from the server’s context menu, Remove the application, Finish, followed by Add and Remove / Add / Finish. The bug has been reported on Java.net, but so far the guys responsible for the GlassFish plugin claim, that it is a bug in Eclipse. I fully expect some ping pong between the two development teams until the bug gets fixed :D

At work, under Linux, I have played once through my whole tutorial and found no showstopper. Thus, when I begin to teach Java EE 6 from next week, this is the combination that I’ll use.

Software versions and installation

I have used the following software versions:

  • JDK 6 Update 21 (JDK!!!): There are 32 bit and 64 bit versions, under Linux I have used the 32 bit version, on my laptop, where I’m just writing this, I run the 64 bit version. No problem with either.
  • Java EE 6 SDK: There is only one version, but the SDK is mostly JARs anyway. This time there is no “GlassFish Tools Bundle for Eclipse”, so be sure to download the right package. On the download page is a matrix that shows, which packages include what version. You will want the full Java EE 6 SDK, not the “Web Profile”.
  • Eclipse IDE for Java EE Developers is available for 32 bit and 64 bit as well. Under Linux I have used 32 bits, under Windows 7 the 64 bit version.
  • The Aquarium blog lists a temporary Eclipse update site for the GlassFish plugin, that’s how I have installed it. In the long run, the GlassFish plugin will be merged into the Oracle Enterprise Pack for Eclipse, the plugin that covers Oracle’s commercial application servers.

First thing to install is the JDK. Under Windows I have installed it to the default location. The JDK installs a JRE (runtime only) as well.

When you install the Java EE 6 SDK, you are asked to choose the JDK to be used. Unfortunately the stupid updatetool installation still has not been fixed. The installer asks you if it should be installed and you really ought to do that. Included with the installer is only a bootstrap version. Unfortunately (and unlike the full version) the bootstrap version can’t easily cope with authenticating proxies. At work under Linux, I had to supply username/password as part of the http_proxy environment variable, and because our proxy needs a Windows domain name in front of the user name, with a backslash as separator, I was in quoting hell :)

What I did after installing to ~/Applications/GlassFish_v3.01 was this:

cd ~/Applications/GlassFish_v3.01/bin
sh
http_proxy='http://DOMAIN\\\\USER:PASSWORD@PROXYSERVER:PROXYPORT' ./updatetool
http_proxy='http://DOMAIN\\\\USER:PASSWORD@PROXYSERVER:PROXYPORT' ./updatetool
^D

Starting sh disables the commandline history. Passwords don’t belong into histories :)

The first call to updatetool actually calls the bootstrap tool, the second call is to the real thing, a GUI tool, and there I’ve installed the two updates that are currently available, and then I have disabled automatic updates.

The four backslashes are necessary, because the bootstrap tool is a shell script, and the value is obviously evaluated two times. Whatever.

This was only a problem under Linux, because our fabulous proxy understands NTLM, and the Windows machine at work where I tried it, automatically authenticated via NTLM.

After the Java EE 6 SDK is installed (and with it GlassFish v3.01), don’t start the server. In your develpoment environment you will want to start it from Eclipse.

Next thing to install is Eclipse Helios. Simply unpack the ZIP where you want it. Start Eclipse, go to the Workbench, use Window > Preferences > Install/Update > Available Software Sites > Add to add the location http://download.java.net/glassfish/eclipse/helios, for instance under the name GlassFish Plugin.

Close the Preferences dialog and use Help > Install New Software. Make sure that Group items by category is not checked, at the top under Work with select the site you’ve just added, and now you should see three entries in the list, Oracle GlassFish Server Tools and the documentations for Java EE 5 and Java EE 6. Install all three. After the installation, Eclipse will prompt you to restart the application. Do so, and after marveling at the changed intro screen, go to the Workbench again.

Now we need to make sure, that we use the right JDK. Use Window > Preferences > Java > Installed JREs and check, that the path really points to the JDK that you’ve just installed, and not to the JRE, that was installed along with it.

Finally you can go to the Servers view and from its context menu add a server. As server type choose GlassFish Server Open Source Edition 3 (Java EE 6). Supply the directory, where you’ve installed the server (actually the glassfish directory within the directory, where you’ve instaleld the Java EE 6 SDK).

From then on, you can start the server via Eclipse and follow the tutorial.

Within the next days I will adapt the tutorial to the new versions and remove the discussion of bugs that have been fixed, but I will keep the old version for those people, who can’t update yet.

 

Version 1.4, last updated May 23, 2011 – 11:10

The content of this tutorial is still relevant, but you may also consider my new open source Azzyzt JEE Tools, a set of Eclipse plugins that greatly simplify the process of creating a Java Enterprise application using the patterns outlined in this tutorial. See the Azzyzt JEE Tools home page and especially the tutorial “Using Azzyzt JEE Tools“.

In “4 – Equipment” I have committed myself to using Eclipse and the Java Enterprise Edition as my tools, while in “5 – Patterns And Languages” I’ve declared my high-level goals for implementing a next step of design pattern-based tools. Now, for a deeper understanding of design patterns, you first have to use them. This post in the form of a tutorial shows some very basic project setups using Eclipse and GlassFish.

I am no expert in this field, some important things may be missing, so just take the following as a set of things that work for me.

As I am not immune to learning, and as I am going the use these things a lot, it is inevitable that my understanding of certain aspects will change. I suppose that means, I will have to make changes to this post whenever it happens. If I ever do so, I will post a short notice.

Applicability

This is a tutorial about using Eclipse and the GlassFish v3 Java application server to implement Java EE 6 applications. I will show how to use different Eclipse project types for different purposes, will show how to do manual tests and how to implement automatic unit tests. We will not create a complete application, but more a vertical slice through an application. The idea is to just touch all relevant areas, not to finish a project.

The tutorial assumes the existence of a relational database, and it concentrates on the Java application used as a backend. Using JSF or another server-based GUI framework is definitely out of scope.

Where’s the beef?

At an equivalent of approximately 80 printed pages, the full tutorial is much too long for a regular blog post. It would break the size limit of feeds syndicated via Google’s Feedburner server. In fact it did. I had no choice but to move the text to a separate page. On the other hand, that’s quite OK, I want my tutorials (this won’t be the last) to be available as pages from a tutorial menu anyway.

Unfortunately I noticed the feed problems only after I had already published the URL of this post a few times. Thus, if you arrive here from a link, please go on to the actual page containing the full Eclipse / GlassFish / Java EE 6 tutorial. Sorry for the inconvenience.

 

My original plan was to work on Linux. The only problem is, that my private computers in Vienna and Carinthia, as well as the laptop run Windows 7. This is mostly because two crucial pieces of my software don’t run on Linux: my image database IMatch and of course Photoshop.

Normally when I need Linux on my computers, I fire up Kubuntu in a VirtualBox, and while this works fine for my image upload scripts and the like, it is not such a good idea to run Eclipse and the GlassFish v3 application server in that environment. It’s not that it doesn’t work, but I don’t want to give the virtual box more than 1 GB of memory, and that’s definitely no environment that’s fun to work in.

On the other hand, when I tried to install the GlassFish Tools Bundle for Eclipse v1.2 (exactly what I use at work on Linux) under Windows 7, I quickly ran into a problem: Although everything installed just fine, I couldn’t start the integrated GlassFish v3 server from Eclipse. Some stack traces rushed by in the console view, and then a dialog told me that

Starting bundled GlassFish v3 Java EE 6 has encountered a problem. Wrong user name or password.

WTF?? This normally just works. Inspecting the console log revealed the real problem:

java.net.BindException: Address family not supported by protocol family

Also not exactly self-explanatory, especially along with that username/password dialog. Well, searching for the quote literally brought me to this discussion thread, and there I found the solution.

In Windows 7 (and seemingly Vista as well), the definition of localhost in Windows\System32\drivers\etc\hosts is in IPv6 notation, i.e. ::1 instead of 127.0.0.1, but trying to bind to localhost, GlassFish seemingly expects the IPv4 notation. I have no idea if there has been an update to GlassFish v3 in the meantime, but at least the bundle is still what was released on December 12. Hmm … one would expect such a bug to be highly unlikely to slip through quality control :)

Anyway. If you encounter the problem, just edit Windows\System32\drivers\etc\hosts and change ::1 to 127.0.0.1. I found no problem with Windows so far, and now GlassFish starts up happily. Just thought I’d have to share that.

© 2010 Andreas Manessinger Suffusion theme by Sayontan Sinha