I have a web application running over Jetty, and I need to spawn a thread for idle connection handling. This thread is being started in the spring context.
I know it's not a good practice to spawn threads in a container, but couldn't find a better way to do this. Any ideas?
You can have the container set up a timer or thread pool for you. See the docs.
The traditional way to handle such resources is in a servlet context listener. Check the Servlet API.
Related
As #Balus has explained in Spawning threads in a JSF managed bean for scheduled tasks using a timer
EJB available? Use #Schedule
If you target Java EE 6 or newer (e.g. JBoss AS, GlassFish, TomEE, etc and thus not a barebones JSP/Servlet container such as Tomcat), then use a #Singleton EJB with a #Schedule method instead. This way the container will worry itself about pooling and destroying threads via ScheduledExecutorService.
So i am curious to know by using #Schedule, the background process will run asynchronously by container managed threads (magically) or it is like a java.util.timer which creates single thread and all process run within this threads??
if #Schedule creates only single thread just to manage the scheduler then would it be safe to use further ScheduledExecutorService within #Schedule? and this ScheduledExecutorService contains further runnable tasks based on multiple threads.
I have a long running process including file manipulation, data processing and email generating, but really should i rely only on this single #Schedule annotation without using any executorservices/creating further threadpool?? BTW i am using Glassfish.
My question is about this answer here that seems to work for my case (tomcat). However I see that it uses a newSingleThreadScheduledExecutor(). In my case the periodical task that has to be executed could be long lasting and I want to make sure that it will not block my web site until it has completed (run as a separated Thread). In addition I want to make sure that my task Runnable will be able to share mySQL connection pool (through hibernate) that the web site is using.
So, is that still the correct approach or do I have to use something else?
I want to make sure that it will not block my web site until it has
completed (run as a separated Thread)
The HTTP connector thread pool and the thread pool allocated to run timer tasks are different. They are not dependent on each other and will not block your website.
In addition I want to make sure that my task Runnable will be able to
share mySQL connection pool (through hibernate) that the web site is
using. So, is that still the correct approach or do I have to use
something else?
Configure a common connection pool using a framework like commons DBCP and lookup the resource on the JNDI. Once you lookup that DataSource and the work on the connection has terminated, return the connection back to the pool.
The approach is fine.
I have a problem with web service via JAX-WS. If I start thread in web method, it will be ended while connection with client ended.
Example:
#WebMethod(operationName="test")
public boolean test()
{
Thread th = new MyThread();
th.start();
// Thread is running
...
return true;
// Now thread th ends;
}
Is there any solution to keep thread th running?
The problem is that you are trying to start a Thread on a Java EE app server. Manual threading is in violation of the Java EE specs, which is why you are running into problems. on some app servers you can't even start a separate thread at all. From the 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.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.
If you need to do the work on a separate thread, you need to use the facilities provided by the app server for asynchronous work. some options are queueing the data to a JMS queue for processing by an MDB or possibly using an asynchronous ejb request (think that's in Java EE 6).
If you just want to be sure before returning that the thread has finished - easiest way is th.join(). This method waits for the thread to die.
I have spring web application and found that
org.springframework.orm.hibernate3.LocalSessionFactoryBean
creates 2 timer threads that don't stop after tomcat shutdown.
Does it possible to configure to stop these threads after tomcat received shutdown command or need use some kind of aspect?
Thanks.
I have a Web application using spring and hibernate and struts (it runs on Tomcat)
The call sequence is something like this...
Struts action calls spring service bean which in turn calls Spring DAO bean. The DAO implementation is a Hibernate implementation.
The question is
Would all my spring beans be running in the same thread ?
Can I store something in the ThreadLocal and get it in another bean?
I am quite sure this would not work in Stateless Session Bean.
The EJB container can (or will) spawn a new thread for every call to the session bean
Will the spring container do the same? i.e. run all beans in the same thread ?
When I tried a JUnit test - I got the same id via Thread.currentThread().getId() in the Test Case and the two beans- which leads me to believe there was only one thread in action
Or is the behavior unpredictable?
Or will it change when running on Tomcat server ?
Clarification
I do not wish to exchange data between two threads. I want to put data in the ThreadLocal and be able to retrieve it from all beans in the call stack. This will work only if all beans are in the same thread
Spring doesn't spawn the threads. Tomcat does. Spring is just creating and wiring up the objects for you.
Each request from the browser is processed in one request. It is Tomcat that handles the request. It is Tomcat that creates the thread to process the request.
Assuming you have just created a singleton bean in Spring called "X". Then the same instance of X is used by all requests.
The Spring beans don't live in a thread. They are just allocated on the heap.
Would all my spring beans be running
in the same thread ? Can I store
something in the ThreadLocal and get
it in another bean?
AFAIK for the components you mentioned (service bean, DAO bean - i guess they are plain spring beans), Spring does not spawn a new thread. I do not understand your use case (ie, exchanging data between two threads).
For most webapps, a new thread is spawned for each new request, and if you want to share data between two requests you normally:
- use the get/post parameters to pass the data
- use the session to share data
To answer your question, I'm pretty sure the spring container does not spawn threads for most components.
Yes, you can do this. The same thread will be used to execute your action so the ThreadLocal will work. Typically, the same thread is used for the stateless session bean as well, assuming it is running in the same app server instance. I would not depend on this though, as it is probably vendor dependent.
We use this technique to access the callers identity anywhere in the code. We use session beans and jms as well, but explicitly pass the information between containers and set the ThreadLocal at each entry point. This way it doesn't matter if the bean (session or mdb) are local or not.
In addition to all the other answers, I will just add the following:
Normally the only reason to switch threads is because of some requirement for parallellity. Since this normally does not come for free in terms of complexity, you will usually be clearly informed when this happens.
Switching threads within what appears to be a single-threaded processing of a request is actually extremely complex. This will normally only happen at one place in a container, and this is usually handled by tcp/ip socket readers that receive the request from the external clients. These reader threads usually determine which thread(pool) should process the request and forward the request to that thread. After that the request stays with that thread.
So normally the only thing that will/can happen is that additional threads get created for parallelity or asynchronous processing (like JMS).