I have a servlet which spawns a number of threads which perform database queries. The main thread acts as a kind of watchdog and cuts-off long running queries after a certain time. Note I am using JDBC and there are no EJBs.
We are in the process of migrating from Websphere 4 to Websphere 5 and I am now getting warnings which basically say that threads in servlets are not J2EE conform and that support for threads may be withdrawn completely in the future.
Does anyone have any opinons on this? Was it a bad idea to use threads in the first place? Are there better ways to ignore long-running queries?
Servlets should also not attempt to maintain state. For one thing, in a clustered environment, the next user hit may be to a different instance of the same servlet in a different JVM or even on a different machine.
If a process is too long-running to execute directly, you should pass the request to a background processor of some sort. My ususal choice is what I call a "null servlet", which is a servlet that has no get/post processors, but starts up the engine as a background thread from its init() method and then stands by to recieve requests. Although that might conceivably break too, depending whether a new system bans all threading or just request/response threading. Two other ways of handling this situation are to use (vendor-specific) startup classes (which is not portable) or use a system such as JMS.
Originally posted by Paul Ramsden
...getting warnings which basically say that threads in servlets are not J2EE conform and that support for threads may be withdrawn completely in the future.
I'm confused about what is meant by "support for threads". How can they possibly prevent you from running threads in a servlet? I believe it is common for servlets to call other objects that start mutiple threads themselves. This is good object oriented programming but I don't see how it's fundamentally different than the servlet starting multiple threads itself.
The application is a front-end to a wide range of legacy data. It allows the user to search for information from this pool and the results of n different queries are presented in the browser. Because the input criteria are quite loose it is possible that some queries will run too long. The idea behind using threads was to set all queries running in parallel and to use the parent thread to cut-off after a certain time.
The warning which I am getting from Websphere seems to be EJB specific but we don't use EJBs. Here is the text:
J2CA0075W: An active transaction should be present while processing method allocateMCWrapper. J2CA0075W: An active transaction should be present while processing method initializeForUOW
Application gets the following warning messages in the SystemOut.log:
[4/11/03 11:53:41:711 PDT] 891a0 ConnectionMan W J2CA0075W: An active transaction should be present while processing method allocateMCWrapper.
[4/11/03 11:53:41:815 PDT] 891a0 ConnectionMan W J2CA0075W: An active transaction should be present while processing method initializeForUOW.
These messages are being produced due to an "unsupported" environment. When application has spun its own threads from an EJB, accessing a database is not supported (per the J2EE specification). If a Servlet is spinning its own threads and accessing a database, the J2EE specification is not clear on this, so WebSphere Application Server 5.0 will allow it at this time. IBM is working with Sun to clarify this in the specification, so eventually (i.e. J2EE 1.4) spun threads from a Servlet accessing a database outside of a transaction will not be supported either.
Since we don't want to promote the usage of these "naked" threads accessing databases, we are producing the warning messages. Although they may be filling up the logs, we feel that these are necessary to warn the user that they are doing something not in-line with the intended usage. Customers should consider changing their application to comply with the
Your message is complaining that your doing stuff outside a transaction. Is it possible for you to change your code so that it runs within a transaction? I don't know how to do that with Websphere.
On a side note, I understand that transactions are used to enable a rollback of multiple tasks but I don't understand why it should matter whether those task are run in separate threads or sequentially. Can anyone out there answer that?