I'm trying to create a thread which runs a set of tasks and, if it does not finish within a specific time (say 100 seconds), throws an exception. Currently I am trying to do this by encapsulating the tasks into a runnable
object and using ExecutorService
and Future
classes to do the timeout executions. However, when I start my Webservice I get this exception:
java.util.concurrent.ExecutionException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.localhostInterpolatorHealthCheck': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:202)
I read online that it's not as simple as defining your own threads and starting them to get a thread started on Spring, so I am wondering how to do this? What am I missing?
2 Answers
Answers 1
Try this :
/** * Executes a task with a specified timeout. */ public final class TimeoutController { /** * Do not instantiate objects of this class. Methods are static. */ private TimeoutController() { } /** * Executes <code>task</code>. Waits for <code>timeout</code> * milliseconds for the task to end and returns. If the task does not return * in time, the thread is interrupted and an Exception is thrown. * The caller should override the Thread.interrupt() method to something that * quickly makes the thread die or use Thread.isInterrupted(). * @param task The thread to execute * @param timeout The timeout in milliseconds. 0 means to wait forever. * @throws TimeoutException if the timeout passes and the thread does not return. */ public static void execute(Thread task, long timeout) throws TimeoutException { task.start(); try { task.join(timeout); } catch (InterruptedException e) { /* if somebody interrupts us he knows what he is doing */ } if (task.isAlive()) { task.interrupt(); throw new TimeoutException(); } } /** * Executes <code>task</code> in a new deamon Thread and waits for the timeout. * @param task The task to execute * @param timeout The timeout in milliseconds. 0 means to wait forever. * @throws TimeoutException if the timeout passes and the thread does not return. */ public static void execute(Runnable task, long timeout) throws TimeoutException { Thread t = new Thread(task, "Timeout guard"); t.setDaemon(true); execute(t, timeout); } /** * Signals that the task timed out. */ public static class TimeoutException extends Exception { /** Create an instance */ public TimeoutException() { } } }
Answers 2
You can have several @async methods instead, and then run them from your main code flow, obtain list of futures. After timeout passes you can get result or stop execution (cancel/terminate).
This has benefits as you will call spring managed beans, thus all dependency injected properties will be available for you. But you should be careful on the amount of jobs/threads you submit.
In order to use @async annotation you need to enable async stuff by using either specific line in your xml configuration or AsyncEnabled annotation on your bean.
0 comments:
Post a Comment