J(2)ee, the basics and beyond
In this series I want to address some topics that are old and well known, but still seem to puzzle developers and administrators in a j2ee environment. Think of anything in or around an application server. When talking of application servers I mostly refer to websphere. Sadly I have no real experience using any other. Yet I aim to keep a broad perspective, not to narrow the audience. The level should be beginner to intermediate.
Part1 Starting your own threads.
As long as I worked with application servers, people have always told me not to start my own threads, because the j2ee specification states that this is forbidden. These threads are also referred to as 'naked' and 'unmanaged'. The danger they pose is doing things that the application server knows nothing about. It could cause resource leaks, no debugging, failing to stop a server or security problems.
Yet there is a number of open source frameworks that do just this, and no one seems to object. Think of quartz, or Log4j (the watchdog that monitors changes in log4j settings). And even the jdk itself is guilty: use of java.util.Timer also causes so called unmanaged threads.
And until now the application servers I know haven´t objected either. So applications were actually free to spawn whatever they want and get away with it.
There was also a reason not to change this situation. The way in which it worked made the application dependent on application server internals. In the case of websphere, the method is fully supported by IBM and didn´t change in websphere 6 for instance; yet developers are reluctant to build software that won´t run on other application servers. This certainly makes migration easier. A disadvantage (of creating your won threads) is that you´re on your own when it comes to transaction management and concurrency control.
The way it worked was:
implement com.ibm.websphere.asynchbeans.Work, obtain a workmanager from jndi and submit the Work class to the manager.
For some time now there is commonj. This is a set of interfaces that have to be implemented by j2ee vendors.
Now you can implement commonj.work.Work, obtain a workmanager from jndi and submit the Work class
The main advantage of this is that commonj can be supported by other application servers. Weblogic 9.0+ does it, geronimo, and sadly no other, until now (afaik). So your application is now only a bit more portable. I think commonj could be made to work with jboss AS. You´d have to implement the workmanager (and other classes) yourself, as an Mbean.
The spring javadoc mentions the lack of official vendor support for commonj with some regret. And I have not been able to find any information about the origins and the future for commonj.
Talking of Spring, they provide a couple of very useful classes that simplify even further the above procedure:
create a org.springframework.scheduling.commonj.WorkManagerTaskExecutor instance, providing a jndi name and submit any Runnable class. You only need commonj on your build path, which is in the spring dependencies.
If you happen to run in websphere 6.1 you´ll have a WorkManager by default using wm/default for the jndi lookup. At lookup a log entry will appear stating that you didn´t use a resource reference. Yet it will all work just fine.
Add the resource reference by putting the next lines in your web.xml
The deployer will have to map this to the actual WorkManager at deploy time.
Spring will add java:comp/env to your jndi name if you set the flag resourceRef to true.
Both commonj and spring also support scheduling of jobs. This could be a safer way than using quartz, especially if your jobs need database access.
Configuring the WorkManager is another thing. Your administrator will have to know how many threads you expect. In Websphere you can also specify if the JAAS subject of the scheduling thread will have to be passed on to the scheduled thread. If disabled, the scheduled thread will have no security context. It will not be able to call EJB´s or other services (unless they do their own login).
The growable property makes the threadpool maximum obsolete and any number of threads can be started. This is all right as long as there are enough resources. It's probably a good setting for finding out the number of threads in certain situations (like under load). Once you´ve established this number, apply it as the maximum for the threadpool and disable growable.
There is no reason to create naked threads. Aapache and two major vendors support commonj. Existing applications and frameworks that run in a j2ee container should be adjusted to at least try to obtain a commonj WorkManager, before resorting to creating threads itself. Spring accomodates for this nicely. Talk to your administrator to sort out the details of the threadpool.