Search code examples
javaspringstruts2executorserviceapplicationcontext

Losing ApplicationContext when executing new runnables


I know I'm new to this spring stuff but I've been stuck on this all day. I don't much like asking questions but maybe I'll get an idea.

So here's my problem: I'm trying to create a Queue for processing stuff on the back end. I did this by creating a static executorservice in a component class with helper methods to run them. it seems to work like i want, and when i wire in classes i can get into those classes, but it seems like when those are running they lose application context (or something this is just my guess).

I'm sure There are better ways to do this, but in the custom framework I am working in there are a number of features that will not work for me. I have no spring-config.xml, cannot use @Configuration

executor service component

@Component
public class FifoComponent {
public static ExecutorService executors = Executors.newSingleThreadExecutor();
private static Lock lock = new ReentrantLock(true);

public static void executeNewTestJob(int i) {
    lock.lock();
    OrderAllocationTestJob job = new OrderAllocationTestJob(i);
    executors.execute(job);
    lock.unlock();
}
}

Runnable component - note appdateutils has a method that calls a component that and works fine in my typical tomcat environment

@Component
public class OrderAllocationTestJob implements Runnable {
int i;

public OrderAllocationTestJob(int i) {
    this.i = i;
}

@Override
public void run() {
    try {
        Thread.sleep(100);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println("Asynchronous task " + i);
    System.out.println(AppDateUtils.getCurrentTimeStamp());
}
}

call from a struts 2 action (test) i know I can call the appdateutils.gettime method from

    for (int i = 0; i < 50; i++) {
        FifoComponent.executeNewTestJob(i);
    }

here's the exception i end up with for what it's worth "Scope 'request' is not active for the current thread"

Exception in thread "pool-15-thread-50" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dateTimestampDao': 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.

Solution

  • I solved this solution by extending ConcurrentLinkedQueue for my runnables and keeping them in a manager I instantiated in the initialize method of a ServletContextListener. By overriding the offer() method of the ConcurrentLinkedQueue to continually poll until the queue was empty I was able synchronously process runnables.

    Unfortunately this locks down the request thread until the runnable is done and I will have to have my users keep an eye on it and let me know if the pages end up running long, but at least in my test environment the process seems sub-second even when i hit it with 20 at a time so I'm OK for now.

    I would still prefer an ExecutorService executed from my Tomcat container but outside the scope of the requests but unless someone can answer the question I'm just going to have to leave it for now