I have developed the following program/architecture:
A) A Java servlet receives POST requests, gets the Parameters from the POST requests and stores them in a public static LinkedList:
public static LinkedList incomingQueue = new LinkedList<myObjects>();
That is, for every POST request I do this:
incomingQueue.push(myObject);
Now, I want to periodically access the Queue and perform processing on the Objects:
while(true){
doProcessing(incomingQueue);
wait(someTime);
}
Obviously, I don't have a main class to do this. How do I create such a class that has access to the incomingQueue without being triggered by the servlet? What is the correct architecture to do this?
Thank you for your time.
First of all the queue should be placed in servlet context attributes (see: ServletContext.setAttribute(). Also access to this queue must be synchronized, consider ArrayBlockingQueue.
In plain servlets you can use ServletContextListener by starting a thread in contextInitialized() and interrupting it in contextDestroyed.
If you are using spring you can use #Scheduled annotation, in ejb: TimerService or #Schedule.
Finally there is a Timer class in standard Java. Last but not least, have a look at jms, it might be a better choice in your situation.
You have several options:
Use a scheduling library like Quartz
If you don't want to use a separate library, you should add a Listener to your web.xml that extends ServletContextListener and starts a separate thread on contextInitialized().
Also: Note the comment by #BrianRoach. The point about the synced list is rather important.
You need to synchronize your methods for concurrent access.
A very hard core solution would be to implement it like producer and consumer. Here is an example that uses stack and 1 producer and 3 consumers.
Much neater solution would be to use JMS.
Related
This question already has answers here:
How to run a background task in a servlet based web application?
(5 answers)
Closed 7 years ago.
Having read a lot of different things and not being totally familiar with the correct terms for some of these things, I am wondering what the correct way is for creating threads at time of tomcat startup that have a specific purpose. I am using a linux system.
I am not trying to create a thread from a servlet, and I have a good idea of why this is bad. When tomcat starts up, I want two different threads that have a distinct purpose to start. The first thread runs on a period, every 30 minutes, to audit back-end data. The second thread is responsible for sending emails. When a request runs a servlet where an email must be sent, instead of holding up the servlet waiting for the email to be sent, I want to send a request to this email thread and move on. So one runs periodically, and one runs on demand. I never need to increase the number of threads performing these tasks, I just need these two going, and for it to be going as long as the webapp is running, and if the webapp has to halt, I don't really care about graceful shutdown.
There are a few approaches I know that I could take:
Create a process running outside of tomcat and define a way to communicate with that process from my servlet. I'd like to avoid this if possible, because I'd like for these two threads to first be directly associated with start up and shut down of the webapp, and for them to be able to access data in the ServletContext, and to not have to ser/des data across a communication channel.
Spawn two threads in the init method of one of my servlets. This seems dirty and hackish, but it would definitely get the job done.
Create a ServletContextListener that extends a ThreadPoolExecutor or other ExexutorService. This seems appealing and correct, and I suppose I could do a fixed thread pool of 2 threads because I don't need any more. But is this the recommended way to do what I am trying? I understand that an ExecutorService is really more meant for executing Runnables on the fly without having to lose the overhead of creating a thread. I don't know if that is totally right, but if it is, I would not be using an executor for its meant purpose.
Maybe there are more methods that I do not know about, or a correct way to implement one of the above.
i will not go on implementing the Thread pool itself, but on your question:
Correct way to create task threads in tomcat at startup
as others said, your third approach is almost correct BUT this depends on your Service Structure.
i'll give you an example and then explain it:
public class YourServletContextListener implements ServletContextListener{
#Override
public void contextDestroyed(ServletContextEvent sce) {
}
#Override
public void contextInitialized(ServletContextEvent sce) {
}
}
From the Docs:
contextInitialized:
All ServletContextListeners are notified of context initialization
before any filter or servlet in the web application is initialized.
if i understand your approach correctly, then i would ask you: how would you like to start a service or send any request to a servlet that is still not been initialized?
this would work, if Services you would like to start do not communicate/need any servlet or Filter or any Data from the web App directly. later, after startup the container, they can sure communicate with each other.
as i said before, which way is the best to use depends on the Service Structure/Logic.
One other method may be using a filter:
void init(FilterConfig filterConfig) throws ServletException
Called by the web container to indicate to a filter that it is being
placed into service. The servlet container calls the init method
exactly once after instantiating the filter.
void destroy()
Called by the web container to indicate to a filter that it is being
taken out of service. This method is only called once all threads
within the filter's doFilter method have exited or after a timeout
period has passed. After the web container calls this method, it will
not call the doFilter method again on this instance of the filter.
This method gives the filter an opportunity to clean up any resources
that are being held (for example, memory, file handles, threads) and
make sure that any persistent state is synchronized with the filter's
current state in memory.
but a filter is not designed for such approachs!
Use a Filter if you want to intercept on HTTP requests maching a
specific URL pattern because you want to check/modify the HTTP
request/response. Use a ServletContextListener if you want to
intercept on webapp's startup and/or shutdown.
Please refer to the following Q&A: tomcat 6 thread pool for asynchronous processing.
Also, instead of Executors.newFixedThreadPool you'll probably need Executors.newScheduledThreadPool to create instance of ScheduledExecutorService which is capable of executing repeating tasks.
Hope this helps...
EDITED SHORT VERSION OF THE POST:
Haven't had enough views, so I'm summarizing the question:
My architecture is completely stateless and async, the front-end makes a petition to a REST API and then long-polls for the response. This Rest API queues petitions into a messaging queue, and each petition is dequeued and processed by the Back-end.
I want this Back-end to follow the "traditional" Spring #Service interface and ServiceImpl approach, however is kind of hard because of how I'm doing it.
One Thread dequeues the petition (Producer), spawns a new Thread (Consumer), and then it processes all the petition within that thread, which later sends back to a "responses pool" where it gets polled. That petition might need to use several #Service's and merge the responses from each, maybe even the same #Service twice.
How would you do it? For more information, check the description below!
ORIGINAL LONG POST:
I have a large application with 3 layers like this:
Front-end (Spring-MVC): Views and Controllers, "Model" are async requests to REST API in Middleware to queue the petition first and then long-polling for an answer
Middleware (Spring-MVC): The rest API. Two main functions: receives a petition from front-end and queues it, receives an answer from Backend and stores it on responses cache until retrieved by front-end
Back-End (Spring Standalone App): Producer/Consumer pattern, ONE Producer dequeues petition and creates a Prototype Consumer for each petition. The consumer implements InitializingBean, so it goes something like this: It is initialized, many Autowired fields are initialized and then afterPropertiesSet is executed and many fields which depends on the petition are set.
I also have a Repository Layer of HibernateDaos, which does all the querying to the database.
I'm missing a properly built Service Layer and that's what this question is all about.
Let me put a little bit more of context. What I have right now is like one only HUGE service with 221 functions (The Consumer's file is very long), and one petition may need to invoke several of this functions, and the result of each is merged into a List of DTOs, which is later received by the front-end.
I want to split this one and only service into several, in a logical match to "it's" corresponding Repository, however I've faced the following problems:
Keep this in mind:
One petition has many Actions, one action is a call to a function of a Service.
Each Consumer is a single and unique Thread.
Every time a Consumer Thread starts, a transaction is started and right before returning it is commited, unless rollbacked.
I need all the services of that petition to be executed in the same thread and transaction.
When the consumer runs afterPropertiesSet, several fields specific to that request are initialized by some parameters which are always sent.
With a good Service Layer I want to acomplish:
I don't want to have to initialize all these parameters always for each service of the petition, I want them to be global to the petition/Thread, however, I don't want to have to pass then as parameters to all the 221 functions.
I want to lazily initialize the new services, only if needed, and when it is initialized, I want to set all the parameters I mentioned above. Each service needs to be a Prototype to the petition, however I feel like is dumb initializing it twice if needed within the same petition (2 actions for the same service on one petition), i.e. I want it to behave like a "Request" scope, however, it is not a request since it is not Web Based, it is a new Thread initialized by the Producer when de-queuing a petition.
I was thinking of having a prototype ServicesFactory per Consumer which is initialized with all the parameters afterPropetiesSet in the Consumer, inside this ServicesFactory all possible Services are declared as Class fields, and when a specific service is requested, if it's field is null it is initialized and all fields are set, if not null, the same instance is returned. The problem with this approach, I that I'm losing Dependency Injection on all the Services. I've been reading about ServiceFactoryBean thinking maybe this is the way to go, however I really can't get a hold to it. The fact that it needs all the parameters of the Consumer, and that it needs to be an unique ServiceFactoryBean per Consumer is really confusing.
Any thoughts?
Thanks
Based on the description I don't think this is a good case for using the protoype scope, in this case the ideal scope seems to be thread scope.
As a solution, the simplest would be to make all services singleton. Then the consumer reads the petition from the inbound queue and starts processing.
One of the services that is also singleton and gets injected in all services needed, let's call it PetitionScopedService.
This service internally uses a ThreadLocal, which is a thread scoped holder for a variable of type PetitionContext. PetitionContext on it's turn contain all information that is global to that petition.
All the consumer needs to do is to set the initial values of the petition context, and any caller of PetitionScopedService on the same thread will be able to read those values in a transparent way. Here is some sample code:
public class PetitionContext {
... just a POJO, getters and setters etc.
}
#Service
public class PetitionScopedService {
private ThreadLocal<PetitionContext> = new ThreadLocal<PetitionContext>();
public doSomethingPetitionSpecific() {
... uses the petition context ...
}
}
#Service
public class SomeOtherService {
#Autowired
private PetitionScopedService petitionService;
... use petition service that is a singleton with thread scoped internal state, effectivelly thread scoped ...
}
Points 2 and 3 need more reorganizing, prefer to check "Spring Integration" for both "Middleware" and "(Spring Standalone App): Producer/Consumer pattern" actually spring integration made to solve these 2 points, and using publish/subscribe if you are doing 2 or more actions at same time, the other point why you are using REST in "Middleware" are these "Middleware" services exposed by another app rather than your front end, in this case you can integrate this part in your Spring-MVC front end app using "content negotiation", otherwise if you are going to use "Spring Integration" you will find multiple ways for communication.
This question has been asked previously and discussed before but i want to ask it further.
Are Servlets Singleton or not ?
According to me they are initialized only by the container but they are still not singleton ?? why ??
Are Servlets Single Thread or multi Threaded (Forget about javax.servlet.SingleThreadModel class)
i.e. What happens when there are multiple requests for a single servlet ??
If they are executed conncurrently, that means it is multi threaded ??
and if its multi threaded then each thread will have an instance of the servlet, which contradicts with the 1st point !!
What i think is,
Whenever theres a new request, The container creates a new Thread for the incoming Request say Req1, in that it calls or dispatches the control to the service method of servlet. Now this execution happens concurrenlty.. i guess so...
Does my working stands the same in a MVC envirionment ?? (say Struts 1/2, Springs)
The fact that exists just one instance doesn't means it isn't multithread. More thread can concurrently call tha same method of the same instance.
Servlets are absolutly multithread.
Servlets are multithreaded - this is the base for their efficiency.
One can use "implements SingleThreadModel" to make a servlet single-threaded, so for every request a new object will be created.
Recently this interface SingleThreadModel was deprecated
It depends on the implementation. The servlet interface doesn't specify.
http://docs.oracle.com/javaee/5/api/javax/servlet/Servlet.html
However, if you see the HttpServlet then you can see it specifies that it should be synchronized.
http://docs.oracle.com/javaee/5/api/javax/servlet/http/HttpServlet.html
Perhaps, the diagram given in the link below illustrates everything...
http://www.tutorialspoint.com/servlets/servlets-life-cycle.htm
I have a class which acts as a simple crawler and I want to invoke this class within a servlet.
My idea is to get an url from user then url request will be passed to the servlet and servelt pass the url to the class and class will start the crawling. and I want my servlet to create only one instance of this class.the retrieved data from crawlwer will be added to the DB directly by the class.
I want to control the behavior of the class like running/halting/stopping from servlet
(for this matter I think I am able to create a simple xml file which will be shared between servlet and class and if servlet change the status code class should response to the status change)
But I have some doubts about how to control the behavior of the class such as command it to run/halt/stop and since my class is not multithreaded I don't have any idea what will happen to invoked class after calling it from servlet and since this class needs to read from network obviously I'll have some gap/freezing phase during running it.
How can I solve the problem of concurrency in this situation?or in other word will I have any concurrency issue or not?
regards.
It depends on the Servlet container you are using. Some containers spawn a new Thread per user request (almost always this is the desired behavior), so you should definitely design for concurrency.
You can make the Servlet class implement SingleThreadModel, then in the service method you can directly call the crawler class code, as only a thread will enter service at a time.
This implies only an URL can be processed at a given time, which is probably not what you want, so instead of that, don't implement SingleThreadModel and create a singleton executor service in the init method:
ExecutorService ex = Executors.newFixedThreadPool(20); //Only 20 tasks at a given time
Then, in the service method create a new CrawlingTask (Runnable) with the URL specified in the request, then submit the task to the executor.
That way you could also shutdown it:
ex.shutdown();
As ExecutorService is thread-safe, you don't have to worry about concurrency when enqueuing tasks.
First, understand the difference between a Class and a Thread. A class is just code, a thread is where the code is executed. You don't stop/halt a class, you stop or halt a thread that is executing code in a class.
I would suggest you start reading up on Java concurrency programming. since what you are describing is very much about multithreading and thread synchronization.
I knew only one servlet instance (One instance for one servlet basis) will be avilable in the web container. Is it possible to make a pool of instance in the web container ? Like a database connection? If i make a pool of servlet instance then how i can make that as a thread safe? (But i studied we can make only one servlet instance per servlet).
I understand that it was an interview question. I would have answered it as follows:
You can let the servlet implement SingleThreadModel to get the container to create a pool of multiple instances of the same servlet class. The maximum pool size depends on the container used, on Tomcat for example, this is 20. But, a big but, this interface is deprecated since Servlet 2.4! We should actually be writing servlets in a thread-safe manner, without assigning request- and/or session scoped data as an instance variable of the servlet. This way it's safe to use a single servlet instance across multiple threads (read: across multiple HTTP requests).
See also:
How do servlets work? Instantiation, sessions, shared variables and multithreading
Question is, why would you want to do that?
Servlet container instantiates single instance for each servlet declaration. That means, that you can have multiple servlet instances, but you need to declare the servlet as many times as many instances you want/need. This also brings the question of how servlets would be invoked ... they would need to be mapped to different paths.
Another way you can do this is to make a pool of handlers which your single servlet may call.
Re how to make them thread-safe: that depends on what exactly you want to do in those handlers. It's hard to tell you in general.
If you're asking about thread-safe pool, you can use Apache Commons Pool library, or some BlockingQueue (e.g. LinkedBlockingQueue) in Java: queue may contain your handlers. Servlet will take() first handler, use it, and put() it back after it's done. (This is just an example of course, there are many ways to implement pool).
But ... make sure you really need design like this, maybe your requirements can be satisfied by something simpler? (If your goal is to limit number of concurrent requests handled at the same time, maybe it's enough to just limit number of HTTP worker threads in your container? Or if that's not enough, you can use a limiting filter?)
Defining a pool of servlets does not make sense as the Servlet itself is not a thread. The Web Container (e.g. Tomcat) maintains a thread pool which calls the Servlet instance. So if you want to increase the throughput (concurrent users) you have to increase your web containers' pool size.