执行新的可运行程序时丢失 ApplicationContext
Losing ApplicationContext when executing new runnables
我知道我是这个 spring 的新手,但我一整天都被困在这个问题上。我不太喜欢问问题,但也许我会想到一个主意。
所以这是我的问题:
我正在尝试创建一个队列来处理后端的东西。我通过在组件 class 中使用辅助方法 运行 创建一个静态 executorservice 来做到这一点。它似乎像我想要的那样工作,当我输入 classes 时,我可以进入那些 classes,但似乎当它们处于 运行ning 时,它们会丢失应用程序上下文(或这只是我的猜测)。
我确信有更好的方法可以做到这一点,但在我工作的自定义框架中,有许多功能对我不起作用。我没有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);
}
这是我最终得到的例外,因为它的价值
"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.
"I'm sure There are better ways to do this"
基于此,在调用另一个线程之前,您需要 create/lookup 所有请求和会话范围的组件。实际上,请求注入是线程本地的,在您的场景中不起作用。
我想如果你删除
Thread.sleep(100);
在 OrderAllocationTestJob 到
job.sleep(100);
FifoComponent 将解决您的问题
我通过为我的可运行对象扩展 ConcurrentLinkedQueue 并将它们保存在我在 ServletContextListener 的初始化方法中实例化的管理器中来解决此解决方案。通过覆盖 ConcurrentLinkedQueue 的 offer() 方法以不断轮询直到队列为空,我能够同步处理可运行对象。
不幸的是,这会锁定请求线程,直到 runnable 完成,我将不得不让我的用户关注它并让我知道页面是否结束 运行 长,但至少在我的测试环境这个过程似乎是亚秒级的,即使我一次用 20 个来打它,所以我现在还可以。
我仍然希望从我的 Tomcat 容器中执行一个 ExecutorService,但在请求范围之外,但除非有人能回答这个问题,否则我现在只能暂时离开它
你看起来像那样吗?
@组件
public class 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);
}
}
}
我知道我是这个 spring 的新手,但我一整天都被困在这个问题上。我不太喜欢问问题,但也许我会想到一个主意。
所以这是我的问题: 我正在尝试创建一个队列来处理后端的东西。我通过在组件 class 中使用辅助方法 运行 创建一个静态 executorservice 来做到这一点。它似乎像我想要的那样工作,当我输入 classes 时,我可以进入那些 classes,但似乎当它们处于 运行ning 时,它们会丢失应用程序上下文(或这只是我的猜测)。
我确信有更好的方法可以做到这一点,但在我工作的自定义框架中,有许多功能对我不起作用。我没有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);
}
这是我最终得到的例外,因为它的价值 "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.
"I'm sure There are better ways to do this"
基于此,在调用另一个线程之前,您需要 create/lookup 所有请求和会话范围的组件。实际上,请求注入是线程本地的,在您的场景中不起作用。
我想如果你删除
Thread.sleep(100);
在 OrderAllocationTestJob 到
job.sleep(100);
FifoComponent 将解决您的问题
我通过为我的可运行对象扩展 ConcurrentLinkedQueue 并将它们保存在我在 ServletContextListener 的初始化方法中实例化的管理器中来解决此解决方案。通过覆盖 ConcurrentLinkedQueue 的 offer() 方法以不断轮询直到队列为空,我能够同步处理可运行对象。
不幸的是,这会锁定请求线程,直到 runnable 完成,我将不得不让我的用户关注它并让我知道页面是否结束 运行 长,但至少在我的测试环境这个过程似乎是亚秒级的,即使我一次用 20 个来打它,所以我现在还可以。
我仍然希望从我的 Tomcat 容器中执行一个 ExecutorService,但在请求范围之外,但除非有人能回答这个问题,否则我现在只能暂时离开它
你看起来像那样吗?
@组件 public class 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);
}
}
}