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.
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.
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.
In one of my libraries, I use a fixed thread pool executor with 5 threads; my threads are not heavyweight, I .get() with timeouts, but as to the ExecutorService, I create it and after that, this is "live and let die".
You are supposed to .shutdown{,Now}() it when you're done with it; but this being a library, I cannot know in advance how it will be used: with a simple main(), in a webapp which will be managed by the servlet container, others.
This doesn't feel right. How do I do better? Should I just be using something else than an ExecutorService?
EDIT link to the only user: here; daemon threads may be a solution, now I don't know if they have drawbacks I should be aware of...
Ok, this is not really an answer, more like an idea...
As I already mentioned in my earlier comment, your LoadingMessageSourceProvider component maintains state, so someone must be responsible to properly shutdown the component. You could try to implement this as part of the component by registering a shutdown hook (I won't consider finalize here :-).
I'd rather leave it to your components' user (application), as it better knows when to shutdown. In fact you're implementing a lightweight container having a lifecycle - in some way similar to a Java EE 7 container provider implementing JSR-236.
Given that you don't have a JSR-236 container available, you must enable the caller to manage lifecycle. I could think of a factory approach, simplified example:
// maintains the executor service (one service per factory)
private MessageSourceProviderFactory f = MessageSourceProviderFactory.instance();
private void stuff() {
MessageSourceProvider msp = f.newBuilder()/*. [...] */.build();
// work with the provider
}
// at some point in time the caller decides to finish
private void end() {
f.shutdown(); // shutdown the factory and the ExecutorService
}
JSR-236 section 3.1.6.1 is fairly interesting in terms of lifecycle:
3.1.6.1 Java EE Product Provider Requirements This subsection describes additional requirements for ManagedExecutorService
providers.
All tasks, when executed from the ManagedExecutorService, will run with the Java EE component identity of the component that submitted
the task.
The lifecycle of a ManagedExecutorService is managed by an application server. All lifecycle operations on the
ManagedExecutorService interface will throw a
java.lang.IllegalStateException exception. This includes the
following methods that are defined in the
java.util.concurrent.ExecutorService interface: awaitTermination(),
isShutdown(), isTerminated(), shutdown(), and shutdownNow().Final
Release 3-11
No task submitted to an executor can run if task’s component is not started.
When a ManagedExecutorService instance is being shutdown by
the Java EE Product Provider:
All attempts to submit new tasks are rejected.
All submitted tasks are cancelled if not running.
All running task threads are interrupted.
All registered ManagedTaskListeners are invoked
It's not infrequent in my practice that software I develop grows big and complex, and various parts of it use executors in their own way. From the performance point of view it would be better to use different thread pool configurations at each part. But from the maintainability and code-usability points it would be more preferable if all things related to threads, concurrency and CPU-utilization were kept and configured at some centralized place.
Having each class which needs some concurrent execution or scheduling create its own thread pool is not OK, because it is hard to control their life-cycles and overall number of threads.
Creating some kind of ExecutorManager and passing one thread pool around the application is not OK either, because, depending on type of the task and submitting rate, inappropriately configured combination of working queue and thread pool size can harm performance really bad.
So the question is: are there some common approaches that address this issue?
I would create 2 or 3 threadPools that can be configured differently depending on the tasks they execute, if there are more than 3 different concurrent actions you have a bigger problem.
The pools can be injected when needed (e.g. by name), additionally I would create an annotation to execute a defined method with a specific pool/executor using AOP (e.g. aspectj).
The annotation resolver should have access to all the pools/executors and submit the task using the one specified in the annotation.
For example:
#Concurrent ("pool1")
public void taskOfTypeOne() {
}
#Concurrent ("pool2")
public void taskOfTypeTwo() {
}
What you are looking for is Dependency Injection or Inversion of Control. One of the most popular DI frameworks for Java is Spring. You build ordinary Java objects, but with either specific annotations or by configuring them in XML, to wire them together. This way, you can configure your different ExecutorService instances in one place, and request that they be injected (possibly by name) in the client classes which need them.
I have the following situation. I have a job that:
May time out after a given amount of time, and if so occurs needs to throw an exception
If it does not time out, will return a result
If this job returns a result, it must be returned as quickly as possible, because performance is very much an issue. Asynchronous solutions are hence off the table, and naturally tying up the system by hammering isn't an option either.
Lastly, the system has to conform to the EJB standard, so AFAIK using ordinary threads is not an option, as this is strictly forbidden.
Our current solution uses a thread that will throw an exception after having existed for a certain amount of time without being interrupted by an external process, but as this clearly breaks the EJB standard, we're trying to solve it with some other means.
Any ideas?
Edited to add: Naturally, a job which has timed out needs to be removed (or interrupted) as well.
Edited to add 2:
This issue doesn't seem to have any solution, because detecting a deadlock seems to be mostly impossible sticking to pure EJB3 standards. Since Enno Shioji's comments below reflect this, I'm setting his suggestion as the correct answer.
This is more like a request for clarification, but it's too long to fit as a comment..
I'm not sure how you are doing it right now, since from what you wrote, just using the request processing thread seems to be the way to go. Like this:
//Some webservice method (synchronous)
public Result process(Blah blah){
try{
return getResult(TimeUnit.SECONDS, 10);
}catch(InterruptedException e){
//No result within 10 seconds!
throw new ServiceUnavailableException("blah");
}
}
I'm not sure why you are creating threads at all. If you are forced to use threads because the getResult method doesn't timeout at all, you would have a thread leak. If it timeouts after a longer time and thus you want to "shortcut" your reply to the user, that would be the only case I'd consider using a thread like I imagine how you are using it. This could result in Threads piling up under load and I'd strive to avoid such situation.
Maybe you can post some code and let us know why you are creating in your service at all?
Also, what's your client interface? Sounds like it's a synchronous webservice or something?
In that case, if I were you I would use a HashedWheelTimer as a singleton... this mechanism should work great with your requirement (here is an implementation). However, this unfortunately seem to conflict with the ban on threading AND the ban on singleton in the EJB spec. In reality though there really isn't a problem if you would do this. See this discussion for example. We have also used the singleton pattern in our EJB app. which used JBoss. However, if this isn't a viable choice then I might look at isolating the processing in its own JVM by defining a new web service (and deploy it in a web-container or something), and call that service from the EJB app. This would however obviously incur performance hit and now you would have another whole new app.
With Bean Managed Transaction, the timeout for the specific transaction can be specified by using UserTransaction interface.
Modify the timeout value that is
associated with transactions started
by the current thread with the begin
method.
void setTransactionTimeout(int seconds) throws SystemException
Transaction will timeout after specified seconds & may not get propagated further. If exception is not thrown implicitly, then can throw it explicitly based on the result.
Will return a result on successful completion within specified time.
Can use it with stateless session beans so there may not be a performance issue.
Its EJB standard so that will not be an issue to implement.
With little-bit work around, it should work fine in the given scenario.
Edit : Also can use server specific properties to manage transaction timeout.
JBoss : At either at class or method level annotation #TransactionTimeout(100) can be applied.
Weblogic : Specifying the parameters in weblogic-ejb-jar.xml
<transaction-descriptor>
<trans-timeout-seconds>100</trans-timeout-seconds>
</transaction-descriptor>
GlassFish : Using the optional cmt-timeout-in-seconds element in sun-ejb-jar.xml
Stick the process and it's timeout thread in to a class annotated with #WebService, put that class in to a WAR, then invoke the WebService from your EJB.
WARs don't have the same limitations or live under the same contract that EJBs do, so they can safely run threads.
Yes, I consider this a "hack", but it meets the letter of the requirements, and it's portable.
You can create threads using the commonj WorkManager. There are implementations built into WebSphere and Weblogic as they proposed the standard, but you can also find implementations for other appservers as well.
Basically, the WorkManager allows you to create managed threads inside the container, much like using an Executor in regular Java. Your only other alternative would be to use MDB's, but that would be a 'heavier' solution.
Since I don't know your actual platform, you will have to google commonj with your platform yourself 8-)
Here is a non IBM or Oracle solution.
Note: This is not an actual standard, but it is widely available for different platforms and should suit your purposes nicely.
For EJBs, there is a concept of "Container Managed Transactions". By specifying #TransactionAttribute on your bean, or specific method, the container will create a transaction when ever the method(s) are invoked. If the execution of the code takes longer than the transaction threshold, the container will throw an exception. If the call finishes under the transaction threshold, it will return as usual. You can catch the exception in your calling code and handle it appropriately.
For more on container managed transactions, check out: http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Transaction3.html and http://download.oracle.com/javaee/5/tutorial/doc/bncij.html
You could use #TimeOut. Something like:
#Stateless
public class TimedBean {
#Resource
private TimerService timerService;
static private AtomicInteger counter = new AtomicInteger(0);
static private Map<Integer, AtomicBoolean> canIRunStore = new ...;
public void doSomething() {
Integer myId = counter.getAndIncrement();
AtomicBoolean canIRun = new AtomicBoolean(true);
canIRunStore.put(myId, canIRun);
timerService.createTimer(1000, 0, myId);
while (canIRun.get() /* && some other condition */) {
// do my work ... untill timeout ...
}
}
#Timeout
#PermitAll
public void timeout(Timer timer) {
Integer expiredId = (Integer) timer.getInfo();
AtomicBoolean canHeRun = canIRunStore.get(expiredId);
canIRunStore.remove(expiredId);
canHeRun.set(false);
}
}