• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

How to synchronize between several concurrent threads in a HTTP servlet request/response cycle ?

 
Ranch Hand
Posts: 558
2
Hibernate Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Hello All,

We are developing REST based webservices using Spring MVC framework and we have a requirement of logging asynchronously some details of the service request. So, we have a setup like below

When the client hits a service say http://<<domain>>:<<port>>/<<context>>/<<servicename>>....

In a filter, before sending the request to Controller, another method is called which has @Async (org.springframework.scheduling.annotation.Async), call it as Thread# 1

using AOP @AfterReturning, another thread is created again using @Async, call it Thread#2

So, we have three threads here for every single service request

Thread#1 - inserts a record to a database table, with status of the service call as "IN_PROGRESS". Each such record is identified by an id, which is returned back. This thread, puts this as a request attribute.
Thread # 2 - Updates the record, based on the id, taken from request attribute and changes the status as "COMPLETED" or "FAILED".
Main thread - actually deals with handling the service request.

Thread #1 aTnd Thread # 2, synchronize on HttpServetRequest (probably a bad idea), before setting and getting id from attributes

Some times, this setup is working fine and some times it is failing, specially when Thread #1 and Thread #2 are delayed for any reason and main thread already sent back the response to the client.

What is the best way to synchronize these threads and share information, beyond the life cycle of HTTP Servlet Request object ?

Thanks
 
Ranch Hand
Posts: 43
Spring Tomcat Server Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What is wrong if thread 1 and 2 not finished yet when main thread completes?

What is the link or dependency between the main and the 2 other threads?
 
Saloon Keeper
Posts: 27762
196
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Servlets should not be spawning threads. It's a violation of the J2EE specification and it can potentially corrupt not only the webapp, but the entire webapp container.
 
Kumar Raja
Ranch Hand
Posts: 558
2
Hibernate Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@John,

What is wrong if thread 1 and 2 not finished yet when main thread completes?



There is possibility of Thread #1 and Main run in concurrent fashion. But Thread 2 does not start until returned back from controller


What is the link or dependency between the main and the 2 other threads?


Thread#1 inserts a log for auditing returning an audit id and Thread # 2 updates the record using the audit Id, after the successful/failed execution of the service.
 
Kumar Raja
Ranch Hand
Posts: 558
2
Hibernate Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@Tim

Servlets should not be spawning threads. It's a violation of the J2EE specification and it can potentially corrupt not only the webapp, but the entire webapp container.



Threads are not actually being created from the servlet, but the are created from a Filter (for Thread # 1) and Thread # 2 is created after @AfterReturning AOP of the controller method. Both Threads are created by @Async annotation of Spring.

I guess, in Servlet 3.0, there is Asynchronous processing. Does that not create a new thread ?
 
John Cruz
Ranch Hand
Posts: 43
Spring Tomcat Server Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Basing on the logic that you said, it seems that it should work. When you say "some times it is failing", what actually is happening? I mean, an exception shown? database not updated? etc.? Why do you say it is failing?

You should look also at what Tim said. It can crash your precious server.
 
Tim Holloway
Saloon Keeper
Posts: 27762
196
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The reason that servlets are prohibited from spawning threads is that threads are not dedicated to specific servlets. When a web request comes in, a thread is pulled from the common request thread pool and the request is dispatched to the indicated servlet using that thread. If the servlet were to spawn a thread, then complete with the thread still running then the thread would be returned to the pool with trash hanging on it. Every thread in the pool is SUPPOSED to be identical with every other one while they're in pooled state. If that thread was later assigned to another request while the spawned thread were still active, the results are unpredictable. Since threads are generic, the next time the thread was handed out, in fact, it might be running a servlet request in some entirely different web application.

I cannot say for certain without checking, but I'll lay good odds that servlet filters run under the servlet threads that they're filtering, which means that you have the same issues as you would in the main servlet service code.

Before asynchronous processing came along, there were 2 options for spawning threads safely.

1) You could spawn them in the init() method of a servlet, since the init method runs under the container's thread context, not under a servlet thread context. This approach has been discouraged for a long time.

2) You can spawn threads in a servletcontextlistener. This is the preferred method. Again, the parent thread for the methods in this class is the servlet container, not a servlet thread and that thread is guaranteed to be available until after the end-of-context listener method has been called, thus the end-of-context listener can tell the threads to shut down cleanly. And they won't get in the way of the server or app internals.

The asynchronous processing feature of servlet 3.0 is more intended to support persistent (comet-style) servlet operation as I read it. At any rate, I looked at using it a couple of months back but it didn't appear to do what I needed - unless I missed something. Which isn't impossible.
 
Kumar Raja
Ranch Hand
Posts: 558
2
Hibernate Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you Tim, for a detailed explanation.

It seems I need to explore other options than threads, to do asynchronouse logging of the webservices.
 
John Cruz
Ranch Hand
Posts: 43
Spring Tomcat Server Chrome
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
JMS is a great solution.

You can use either the common Spring JMS support, or the Spring Integration support.


For your problem above:
1. The filter sends a JMS message (message must include the log key) to a queue where a new service MyJmsService1 is listening. This MyJmsService1 does what is inside your thread1.
2. Your controller should know the key to the log entry, so find a way for the filter to pass this to the controller.
3. The controller, when done processing, sends JMS messge (message must include the log key) to a second queue where new service MyJmsService2 to update the log, using the key. This MyJmsService2 does what is inside your thread2.
4. One problem is if the MyJmsService2 tries to update before MyJmsService1 completes inserting. In Spring Integration, you can make a dependency for the 2nd JMS message to wait until the first JMS message arrives, based on the key.

Try the Spring Integration. It is short and clean. You can initially not use a real JMS server and simulate it using same-thread (main thread, and of course this is synchronous so is only for your unit testing; use real JMS server for integration test etc.) message system.

 
Kumar Raja
Ranch Hand
Posts: 558
2
Hibernate Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you John
 
Curse your sudden but inevitable betrayal! And this tiny ad too!
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic