Reputation: 301
There is a block of code in Java (a loop) which uses UserTransaction
for processing the transaction. The userTransaction object is declared before the loop, The object is declared as,
private javax.ejb.SessionContext mySessionCtx;
UserTransaction utx=mySessionCtx.getUserTransaction();
Now i have implemeted the particular block of code (the loop) in "MultiThreading". I have passed the object utx
from the class which initiates the thread to the UserTransaction
object in the thread which I have created (because the class which initates the thread implements javax.ejb.SessionBean
and this class is called through EJB.)
This functionality is working absolutely fine in Windows machine. But when deployed in Linux server, it is not working.
In Linux server, before implementing threading, the Statement utx.begin()
worked fine. But after implementing threading, utx.begin()
throws a NullPointerException
. The object utx
has value in it. It is the begin()
statement , which throws the exception.
Does this UserTransaction
behave differently in Windows and Linux servers? Does it depend on any other factors? What could be the reason for it to work fine in Windows server and to throw exception in Linux server??
P.S: I'm working on Java Struts 1.2. and using IBM WebSphere
Upvotes: 1
Views: 1795
Reputation: 389
There are a couple of issues with your approach, but also i have to ask why you are using user managed transactions and multi-threading in a Struts / WebShpere app?
Here are some points that might help -
In a Java EE application the application server is responsible for managing threads for you. If you also manipulate threads, you can mess-up what the application server is doing with its thread management. Typically you can find information on settings you can tune in the application servers administration manual. I am not certain about WebSphere specifically by i expect that each HTTP request incoming is going to get its own thread.
From your description I suspect you are trying to bulk process a bunch of things quickly by using lots of threads. While there are asynchronous EJB calls that you can make, you should also consider placing each of the requests on a simple JMS queue and service them with MessageDrivenBeans this will let multiple threads at them. (If you have an older version of Websphere asynchorous EJB calls might not be availabe)
I have very rarely seen a case where UserTransaction where really needed. When you call and EJB, the default is that a transaction is started (or joined if one already exists) There are settings that you can add to the Session bean method (by deployment descriptor or annotation) to get the behaviour you want.
For example, suppose i want to process a list of items, but it one item half way through the list fails to process, i don't want to roll back the ones that where successfull. In this case I would pass the whole list to a EJB method, then for each item call an second EJB method with a @RequiresNew transaction attribute. Each individual item would be processed in its own transaction.
As to why it worked on windows but not linux specifically, I would also need to know what hardware is involved, but i speculate that the linux machine is making use of more true harware threads and parallel execution.
Upvotes: 0
Reputation: 33936
The EJB UserTransaction object will only work within the scope of an EJB. It will not work if you pass the object to another thread, and it will not work if you return the UserTransaction from an EJB method to a servlet. The NullPointerException was replaced by an IllegalStateException in a later version of the product.
Creating your own threads is not supported by Java EE. You should instead either use asynchronous EJB methods, WebSphere Application Server asyncbeans, the commonj API, or the JSR 236 API depending on which version of the product you're using. All of these APIs will propagate a component context to an external thread, which will allow you to lookup("java:comp/UserTransaction")
, which you should use instead.
Upvotes: 3