执行新的可运行对象时丢失ApplicationContext

时间:2018-09-10 21:48:26

标签: java spring struts2 executorservice applicationcontext

我知道我是这个春季的新手,但是我整天都被困住了。我不太喜欢问问题,但也许我会有所想法。

这是我的问题: 我正在尝试创建一个队列来处理后端的东西。我是通过在带有帮助程序方法的组件类中创建静态executorservice来运行它们的。它看起来像我想要的那样工作,当我加入类时,我可以进入那些类,但是似乎当那些类正在运行时,它们会丢失应用程序上下文(或者这只是我的猜测)。

我确定有更好的方法来执行此操作,但是在我正在使用的自定义框架中,有许多功能对我不起作用。我没有spring-config.xml,不能使用@Configuration

执行器服务组件

@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();
}
}

可运行组件-注意appdateutils有一个方法,该方法可以调用在我的典型tomcat环境中可以正常工作的组件

@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());
}
}

从struts 2动作调用(测试)我知道我可以从

调用appdateutils.gettime方法
    for (int i = 0; i < 50; i++) {
        FifoComponent.executeNewTestJob(i);
    }

这是我最终要付出的代价的例外 “范围'请求'对于当前线程无效”

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.

4 个答案:

答案 0 :(得分:0)

“我相信有更好的方法可以做到这一点”

基于此,您需要在调用另一个线程之前创建/查找所有请求和会话作用域的组件。实际上,请求注入是线程本地的,在您的情况下不起作用。

答案 1 :(得分:0)

我认为您是否要删除

Thread.sleep(100);

在OrderAllocationTestJob中

job.sleep(100);

在FifoComponent中可以解决您的问题

答案 2 :(得分:0)

我通过扩展可运行对象的ConcurrentLinkedQueue并将它们保留在我在ServletContextListener的initialize方法中实例化的管理器中来解决了该解决方案。通过覆盖ConcurrentLinkedQueue的offer()方法以不断轮询直到队列为空,我可以同步处理可运行对象。

不幸的是,这将锁定请求线程,直到可运行性完成为止,我将不得不让我的用户注意它,并让我知道页面是否最终运行了很长时间,但是至少在我的测试环境中,该过程似乎不到一秒,即使我一次打20也可以,所以我现在还可以。

我仍然希望从Tomcat容器执行ExecutorService,但超出请求的范围,但除非有人可以回答问题,否则我将不得不暂时将其保留

答案 3 :(得分:0)

您在寻找类似的东西吗?

@Component 公共类AsynchronousThread扩展了线程{

public static final Logger LOGGER = LoggerFactory
        .getLogger(AsynchronousThread.class);

@Autowired
private Writer writer;


private BlockingQueue<IndexContextDTO> blockingQueue = new LinkedBlockingQueue<IndexContextDTO>(
        500);

/**
 * 
 */
public AsynchronousThread() {
    super("AsynchronousThread");
}


@PostConstruct
public void init() {
    Integer internalQueueSize = 100;
    this.blockingQueue = new LinkedBlockingQueue<>(internalQueueSize);
    this.start();
}


@Override
public void run() {

    while (true) {
        // Do stuff
    }
}


public void putInQueue(IndexContextDTO message) {
    try {
        this.blockingQueue.put(message);
    } catch (InterruptedException interruptedException) {
        // This exception will be thrown in very rare case.
        LOGGER.error("An error while putting message in the queue. "
                + message, interruptedException);
    }
}

}