I have a Stateless EJB method(ejbMethod1) that needs to call a web service operation(wsOper1), if this call fails It needs to call another web service operation(wsOper2).
My problem is: I don't need the returning of wsOper2 to return from ejbMethod1! I want to delegate this work to another piece of my application and return immediately.
Option1:: My first approach to this problem was to use a global LinkedBlockingQueue for storing an Object representing the wsOper2 I needed to do, and have N threads retrieving elements from this queue and executing the call.
Option2:: Create a Runnable and delegate to some global thread pool. There is one that I can use?
Or is another option that I'm not contemplating?
...
PS:
Im using Glassfish 4.1 & JRE8 and I'm new to the Java EE world :P
UPDATED:
I used a ManagedExecutorService to execute wsOper2 asynchronously as a Runnable.
#Resource
private ManagedExecutorService executor;
Thanks Ryan :)
From the EJB spec:
The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt to start, stop, suspend, or resume a thread, or to change a thread’s priority or name. The enterprise bean must not attempt to manage thread groups.
See Adam's Blog for more information on EJBs and threading.
Related
I work on the backend of a java web application. I added some multithreading to speed up a big data retrieval, and I used a few ExecutorServices I created in the process. However, I've read that it might not be a good idea to be creating threads this way in a web app, and that the 'com.ibm.websphere.asynchbeans.WorkManager' is maybe an option instead. It seems not very friendly to use in the backend though. According to the documentation, the work manager is a 'thread pool created for Java Platform, Enterprise Edition (Java EE) applications that use asynchronous beans'. I, as a very front end ignorant back end guy, don't even entirely know what a bean is. It doesn't really seem like the work manager is what I want, but if it's actually a bad idea to manually create an ExecutorService, I'm not sure what the best approach is.
Creating your own threads in the back end of a webapp is a bad idea for the following reason: Application Server container manages threads for you. So if you create your own threads in your app the container won't know about them and won't be able to manage them. Thus if you mismanage threads your app can cause memory leaks and other thread related problems. In theory the best way is to register some thread pool in your App Server and requests threads from the container using JNDI. But it might be an overkill. So sometimes, you may want to manage your own threads. So, in this case ExecutorService is the best way to go as it provides very nice API to manage your threads. Just make sure that as your application shuts down you shutdown your ExecutorService so no orphan threads are left behind. If you are careful about it then you can create your own threads. Just use them sparingly and be careful that you you shut down your ExecutorService when done or when Application shuts down. BTW there is a similar issue with ThreadLocal variables. You absolutely MUST invoke metod remove() in them when done, otherwise they will remain in the memory even if your app is shutdown, and only Application Server restart will clear them. This is a dangerous memory leak.
Just to expand on Michael Gantman's answer, which is a pretty good explanation, the JavaEE approach to allowing the container manage your threadpool is super easy to actually implement:
#Stateless
public class Foo {
#Asynchronous
#Override
public void doSomething() {
//all calls to this function are asynchronous
}
}
The #Aysnchronous takes care of the magic here, specifying to the container that this function should be called asynchronously and it's the container's responsibility to figure out what that means. Then calling out to your container managed threadpool to execute your function is as simple as:
#Stateless
public class Bar {
#EJB
Foo myFooEJB;
public void businessMethod() {
myFooEJB.doSomething();
}
}
Checkout these for more reading: javax.ejb.Asynchronous, Asynchronous method invocation. Getting maybe a little too into specifics because I know you're using IBM products, in JBoss, your Asynchronous comes as part of a subsystem configuration by specifying <async thread-pool-name="poolName"/> (https://docs.jboss.org/author/display/WFLY8/EE+Subsystem+Configuration)
where poolName should reference a pool such as:
<thread-pools>
<thread-pool name="poolName">
<max-threads count="10"/>
<keepalive-time time="100" unit="milliseconds"/>
</thread-pool>
</thread-pools>
But there is a better way if you're trying to submit, just some task to an ExecutorService which can be managed by the container:
#Resource
ManagedExecutorService executorService;
#Resource
ManagedScheduledExecutorService scheduledExecutorService;
java.io.PrintWriter out = ...;
void scheduleSomeStuff(){
scheduledExecutorService.schedule(new Runnable() {
#Override
public void run() {
out.println("Print out after roughly 15 seconds.")
}
}, 15, TimeUnit.SECONDS);
executorService.submit(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
out.println("Print only once, when the task is run by the executor service's discretion.");
}
};
}
These two resources, specifically that I've reference here, run on different thread pools. At that, I originally posted something here using the #Asynchronous thread pool as an executor, but it's unnecessary since the container should already have one for you; hence the updated answer you see here now.
This, again, might be a little specific to JBoss, but in JBoss this is configured as a subsystem managed-scheduled-executor-services and managed-executor-services. These two subsystems have their own distinct thread pools that they utilize.
EDIT April, 2020
So I somehow found this answer again, and reread and am very confused at myself for not calling out the EJB specification explicitly. Not only is it a bad idea to do, you would be in direct violation of the EJB spec if you created your own threads.
JSR 345: Enterprise JavaBeans, Version 3.2 EJB Core Contracts and Requirements
Section 16.2.2 Bean Provider’s Responsibilities, Programming Restrictions:
The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt to start, stop, suspend, or resume a thread, or to change a thread’s priority or name. The enterprise bean must not attempt to manage thread groups.
These functions are reserved for the EJB container. Allowing the enterprise bean to manage threads would decrease the container’s ability to properly manage the runtime environment.
In other words, NEVER attempt to manage your own threads in a web application. This quote is for the EJB spec but even within a ResourceAdapter, for example, the container provides a WorkManager via the BootstrapContext (see ResourceAdapter#start(BootstrapContext), BootstrapContext#getWorkManager()). There's never a reason to attempt to create/manage your own thread in a web application; never do it for any reason.
we have a situation where we want to perform some tasks at the end of a request or transaction. More specifically, we need to collect some data during that request and at the end we use that data to do some automatic database updates.
This process should be as transparent as possible, i.e. users of the EJBs that require this should not have to worry about that.
In addition we can't control the exact call stack since there are multiple entry points to the process.
To achieve our goal, we're currently considering the following concept:
certain low level operations (that are always called) fire a CDI event
a stateless EJB listens for those events and upon receiving one it collects the data and stores it into a scoped CDI bean (either request scope or conversation scope would be fine)
at the end of the request another event is fired which causes the data in the scoped CDI bean to be processed
So far, we managed to get steps 1 and 2 up and running.
However, the problem is step 3:
As I already said, there are multiple entry points to the process (originating from web requests, scheduled jobs or remote calls) and thus we thought of the following approach:
3a. A CDI extension scans all beans and adds an annotation to every EJB.
3b. An interceptor is registered for the added annotation and thus on every call to an EJB method the interceptor is invoked.
3c. The first invocation of that interceptor will fire an event after the invoked method has returned.
And here's the problem (again in the 3rd step :) ):
How would the interceptor know whether it was the first invocation or not?
We thought of the following, but neither worked so far:
get a request/conversation scoped bean
fails because no context is active
get the request/conversation context and activate it (which then should mark the first invocation since in subsequent ones the context should be active)
the system created another request context and thus WELD ends up with at least two active request contexts and complained about this
the conversion context stayed active or was deactivated prematurely (we couldn't yet figure out why)
start a long running conversation and end it after the invocation
failed because there was no active request context :(
Another option we didn't try yet but which seems to be discouraged:
use a ThreadLocal to either store some context data or at least to use invocation context propagatation as described here: http://blog.dblevins.com/2009/08/pattern-invocationcontext-propagation.html
However, AFAIK there's no guarantee that the request will be handled entirely by the same thread and thus wouldn't even invocation context propagation break when the container decides to switch to another thread?
So, thanks to all who endured with me and read through all that lengthy description.
Any ideas of how to solve this are welcome.
Btw, here are some of the software components/standards we're using (and which we can't switch):
JBoss 7.1.0.Final (along with WELD and thus CDI 1.0)
EJB 3.1
Hibernate 3.6.9 (can't switch to 4.0.0 yet)
UPDATE:
With the suggestions you gave so far, we came up with the following solution:
use a request scoped object to store the data in
the first time an object is stored in that object an event is fired
a listener is invoked before the end of the transaction (using #Observes(during=BEFORE_COMPLETION) - thanks, #bkail)
This works so far but there's still one problem:
We also have MBeans that are managed by CDI and automatically registered to the MBean server. Thus those MBeans can get EJB references injected.
However, when we try and call an MBean method which in turn calls an EJB and thus causes the above process to start we get a ContextNotActiveException. This indicates that within JBoss the request context is not started when executing an MBean method.
This also doesn't work when using JNDI lookups to get the service instead of DI.
Any ideas on this as well?
Update 2:
Well, seems like we got it running now.
Basically we did what I described in the previous update and solved the problem with the context not being active by creating our own scope and context (which activated the first time an EJB method is called and deactivated when the corresponding interceptor finishes).
Normally we should have been able to do the same with request scope (at least if we didn't miss anything in the spec) but since there is a bug in JBoss 7.1 there is not always an active request context when calling EJBs from MBeans or scheduled jobs (which do a JNDI lookup).
In the interceptor we could try to get an active context and on failure activate one of those present in the bean manager (most likely EjbRequestContext in that case) but despite our tests we'd rather not count on that working in every case.
A custom scope, however, should be independent from any JBoss scope and thus should not interfere here.
Thanks to all who answered/commented.
So there's a last problem though: whose answer should I accept as you all helped us get into the right direction? - I'll try to solve that myself and attribute those points to jan - he's got the fewest :)
Do the job in a method which is annotated with #PreDestroy.
#Named
#RequestScoped
public class Foo {
#PreDestroy
public void requestDestroyed() {
// Here.
}
}
It's invoked right before the bean instance is destroyed by the container.
What you're looking for is SessionSynchronization. This lets an EJB tie in to the transaction lifecycle and be notified when transactions are being completed.
Note, I am being specific about Transactions, you mention "requests and transactions" and I don't know if you specifically mean EJB Transactions or something tied to your application.
But I'm talking about EJB Transactions.
The downside is that it is only invoked when the specific EJB is invoked, not to "all" transactions in general. But that may well be appropriate anyway.
Finally, be careful in these interim call back areas -- I've had weird things happen with transactional at these lifecycle methods. In the end, ended up putting stuff in to a local, memory based queue that another thread reaped for committing to JMS or whatever. Downside is that they were tied to the transaction at hand, upside was that they actually worked.
Phew, that's a complex scenario :)
From how I understand what you've tried so far you are pretty advanced with the CDI techniques - there is nothing big you are missing.
I would say that you should be able to activate a conversation context at the entry point (you've probably seen the relevant documentaton?) and work with it for the whole processing. It might actually be worthwhile considering implementing an own scope. I did that once in a distantly related scenario where we could not tell whether we've been invoked by HTTP-request or EJB-remoting.
But to be honest, all this feels far too complex. It's a rather fragile construct of interceptors notifying each other with events which all in all seems just too easy to break.
Can it be that there is another approach which better fits your needs? E.g. you might try to hook on the transaction management itself and execute your data accumulation from there?
Can I start /spawn new java thread from within a MDB?
I have a requirement to do some parallel processing from code in MDB and then return the control back to MDB.
Requirement:
Message come to MDB , then some processing of code. Then two new slave thread are started which do some parallel work. Till then MDB is waiting. when threads finish the work. Then control is returned back to MDB, which completes the the related final/cleanup work.
Is it good idea to start a new thread ( Runnable) from MDB? If not then what should be the alternative?
It is a bad idea, if you are performing transactional work in the threads.
A thread that is currently performing work in a transaction started by the EJB container, is associated with a transaction context. In your case, the onMessage method in the MDB initiates a new transaction (unless you have specified a NotSupported descriptor), and the thread performing this transaction would be associated with a transaction context. Starting a new thread, does not propagate the transaction context to the child thread. This would result in a new transaction being created when the container detects that the child thread is attempting to access a transactional resource without a transaction context.
Although some (or most?) transaction managers support the presence of multiple threads possessing the same transaction context, this might (and most likely will) not apply to application initiated threads.
Starting new threads with in MDB is bad practice. It will work but the new threads are not in control of application container so can behave unpredictably. They can even mess-up the thread management which container is trying to maintain. Worst affect is if the application is deployed in cluster then user defined threads will fail miserably.
In your scenario : Instead of starting new threads , create new MDB with logic of thread ( This way it will be managed by contaner now) then send message to these new MDB. If you want the control back to parent MDB then, I think , use your parent MDB in global transactional so that parent MDB will wait for child MDB to finish and control will return back.
Starting a thread from an MDB violates the specification.
Enterprise JavaBeansTM,Version 3.0, EJB Core Contracts and Requirements states in section 21.1.2 Programming Restrictions:
An enterprise bean must not use thread synchronization primitives to synchronize execution of multiple instances.
The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt
to start, stop, suspend, or resume a thread, or to change a thread’s priority or name. The enterprise bean must not attempt to manage thread groups.
You are fundamentally missing the point of Java EE and MDBs.
A Java EE container is a managed runtime environment. The principle idea behind the Java EE container is that by delegating certain orthogonal concerns, such as transaction management, to the container, the component remains focused on business logic and (in utopia) be a reusable component that makes little assumption about its runtime environment.
Prior to MDBs, the Java EE container was a passive-reactive system that allowed no means for coordinating the action of a container side asynchronous active agents. Message Driven Beans then addressed this, providing a standard way for you to kick off an asynchronous action, server side.
You have an original event e0 which is consumed by MBD0. On message, MDB0 will generate e1 and queue a message in response to MBD1, which will then do its work and send msg to MDB2, etc.
There you have a simple workflow of n sequential steps using pub/sub messaging semantics (and o/c with asynchronous semantics), and all threads involved are managed by the container. If you wish to have concurrent actors working and then collecting results and kicking off a final action, consider using patterns involving JMS topics.
The EJB 3.0 specification does not allow a business method of a stateless session bean to create new threads. Why is that? What is wrong with creating additional worker threads that only do raw computations and never call into the app server?
Say, my session bean implements a service that lets users to upload images, and the business method does cpu-intensive image processing on these images. Then it can only use one cpu core to do this job, even if the machine has 8 or more cores? If i utilize a third party image processing library, that internally creates worker threads, i would also violate the EJB specs, even though that library and these threads have nothing to do with the EJB container at all. This does not seem right.
What can happen if i ignore the EJB rules and still create some worker threads to do cpu intensive processing? Of course these threads will never touch any app server objects and the bean thread will join them before returning. Can still something bad happen?
The EJB 3.0 specification does not allow a business method of a stateless session bean to create new threads. Why is that?
Short version: managing threads from EJBs is disallowed because it would harm resource management, transaction management, security (technical reasons) and also because this is something the EJB model doesn't want to promote (philosophical reason).
The EJB specification puts it like this:
21.1.2 Programming Restrictions
...
The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt to start, stop, suspend, or resume a thread, or to change a thread’s priority or name. The enterprise bean must not attempt to manage thread groups.
These functions are reserved for the EJB container. Allowing the enterprise bean to manage threads would decrease the container’s ability to properly manage the runtime environment.
See also
Why is thread creation and management disallowed? in the EJB Restrictions FAQ
Why are beans not allowed to create their own threads?
Concurrency Utilities for Java EE
Section 2.1 "Container-Managed vs. Unmanaged Threads"
(...) If i utilize a third party image processing library, that internally creates worker threads, i would also violate the EJB specs, even though that library and these threads have nothing to do with the EJB container at all. This does not seem right.
What can I say, don't use EJBs if you don't like this.
What can happen if i ignore the EJB rules and still create some worker threads to do cpu intensive processing? Of course these threads will never touch any app server objects and the bean thread will join them before returning. Can still something bad happen?
Whether these threads are touching the app server objects or not doesn't matter. Rules are rules, you don't want to follow them, you're on your own and the behavior is undefined. Some container might be more permissive and allow it, some other won't, your application won't be portable, etc. But it's still explicitly forbidden.
If you want to "spawn" threads in a standard way, use the WorkManager API, or use JMS.
Related Questions
How can an EJB parallelize a long, CPU intensive process?
In my simplified understanding, it's like running a company. You're the boss (the container), and there's an employee which suddenly just hire 100 people out of the blue without any notice (the bean).
But you can still easily do multithreading with the #Asynchronous annotation (there are other ways too).
#Stateless
public class Employee {
#Asynchronous
public Future<Void> work(Project projectThatTakeTooLong) {
// work work work
return new AsyncResult<Void>(null);
}
}
#Stateless
public class Boss {
#Inject
private Employee randomStatelessEmployee;
public void giveWork() {
Future<Void> result1 = randomStatelessEmployee.work(new Project());
Future<Void> result2 = randomStatelessEmployee.work(new Project());
Future<Void> result3 = randomStatelessEmployee.work(new Project());
result1.get();
result2.get();
result3.get();
}
}
There's also a better example here:
Jboss Java EE container and an ExecutorService
One type of workaround:
import java.util.concurrent.Executor;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;
#Stateless
public class TransactionalExecutor implements Executor {
#Override #Asynchronous
public void execute(Runnable command) {
command.run();
}
}
Now you can use TransactionalExecutor as an executor:
#Stateless
public class SlowService {
#Inject
Executor command;
public void invoke(){
Runnable command = new Runnable() {
#Override
public void run() {
// heavy task
}
};
command.execute(command);
}
}
This is known restriction not to use threads in J2EE applications.
Application server should take care of parallel execution of the program
Yes, you can ignore the EJB rules but can face with extremely unpredictable behaviour.
My question is about threads being queued. For my example I have one Spring context. I have a method named CalculateTax in a stateless class. A request comes in, a thread is created (tA) and it eventually enters the CalculateTax method. Within the same "time frame" another request comes in and another thread is created (tB). Now, here is what I want to understand. AFAIK tB cannot execute CalculateTax until tA has exited the method. Is this true?
As long as CalculateTax only uses local variables (i.e. declared in the method), you will not have any thread sync issues and multiple threads can call the method without a problem.
However if for some reason CalculateTax uses variables defined at the class level, and you are using the Singleton pattern (you tagged your question with "singleton", so I guess you are), you may have thread sync issues.
No it is not true if they are parallel thread, each thread is in its own stack of execution so it should be able to execute while tA is executing.
This is what Threads are for.
Generally speaking the answer is undefined. If your 'request' comes from remote client the answer depends on implementation details of the mechanism used for service exposing.
However, I'm not aware about remote communication frameworks that really make the proxy serializing the requests, i.e. that is assumed to be addressed by target service developer (e.g. its your task to provide thread-safety for the service implementation OR serialize all requests using explicit synchronization etc).