Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
401 views
in Technique[技术] by (71.8m points)

java - Accessing request scoped beans in a multi-threaded web application

Scenario: We have a Spring managed web application that runs inside Websphere. (Spring 3.0.x, WAS 7) The webapp leverages Websphere's work manager via Spring's WorkManagerTaskExecutor (configured with a thread pool size of 10) to execute computational intensive db read operations. So basically, a request comes in to generate, lets say, 10 different documents. To generate the documents only db reads are needed to gather/process the data. So we basically spawn 10 threads to process the 10 documents and at the end gather the 10 documents returned from the 10 workers and merge them and write back one big response to the client. What we identified is that while the 10 threads are gathering/processing the data there are bunch of similar db calls made. So what we came up with is to create an Aspect around the most-executed db methods to cache the response. The aspect is configured as a singleton, and the cache the aspect uses is autowired into the aspect with a scope set to request-scope so that each request has its own cache.

Problem: Now the problem with this approach is that when the threads are doing their db calls and the Aspect is interjects we are getting java.lang.IllegalStateException: No thread-bound request found exception. Which I understand is totally valid as the threads are being executed outside the request context.

Is there a way to circum-navigate this issue? Is it possible to apply the aspect with a request scoped cache to the methods invoked by these threads?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I don't think you can do this directly. Even if you could, it would be a bit ugly. However, you can generate a unique request identifier (or even - use the session id, but careful with multiple tabs), and pass that to each processing thread. Then the aspect can use that id as the key to the cache. The cache itself will also be singleton, but there will be Map<String, X>, where String is the ID and X is your cached result.

To make things easier to handle, you can have @Async methods (rather than manually spawning threads), and each @Async method can have the cache id passed as its first parameter.

(Of course, your asynchronous methods should return Future<Result> so that you can collect their results in the request thread)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...