Java 新线程正在导致ContextNotActivieException
我正在尝试在Wicket framework应用程序中启动一个新线程,我得到:Java 新线程正在导致ContextNotActivieException,java,multithreading,jboss,wicket,Java,Multithreading,Jboss,Wicket,我正在尝试在Wicket framework应用程序中启动一个新线程,我得到: Exception in thread "Thread-14" org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type javax.enterprise.context.RequestScoped at org.jboss.weld.manager.BeanManagerIm
Exception in thread "Thread-14" org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type javax.enterprise.context.RequestScoped
at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:598)
at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:71)
此新线程位于web服务中,如下所示:
@GET
@Override
@Path("notificarPadres")
public String notificarPadres(@QueryParam("centroDeCostosId") Integer centroDeCostosId, @QueryParam("userNotificadorId") String userNotificadorId, @QueryParam("mensaje") final String mensaje) {
String result = GradienteConstants.STRING_TRUE;
final Set<User> destinatarios = new HashSet<User>();
List<CentroDeCostos> listCentroCostoPadres = listCentroDeCostosPadresById(String.valueOf(centroDeCostosId));
final User notificador = getUserById(userNotificadorId.toLowerCase());
for (CentroDeCostos centroCosto : listCentroCostoPadres) {
if (hasCentroDeCostoResponsable(centroCosto)) {
User responsable = getResponsableByCc(centroCosto);
createNotificacion(responsable, notificador, mensaje);
if (isUserForMail(responsable)) {
destinatarios.add(responsable);
}
}
}
sendMailNewThread(destinatarios, notificador, mensaje);
return result;
}
private void sendMailNewThread(final Set<User> destinatarios, final User notificador, final String mensaje) {
Runnable r = new Runnable() {
@Override
public void run() {
sendEMail(destinatarios, notificador, mensaje);
}
};
Thread thread = new Thread(r);
thread.start();
}
@GET
@凌驾
@路径(“通知地址”)
公共字符串notificarPadres(@QueryParam(“centroDeCostosId”)整数centroDeCostosId,@QueryParam(“userNotificadorId”)字符串userNotificadorId,@QueryParam(“mensaje”)最终字符串mensaje){
字符串结果=GradienteContents.String\u TRUE;
最终集destinatarios=新HashSet();
List listCentroCostoPadres=LISTCENTRODECOSTOPANDERSBYID(String.valueOf(centroDeCostosId));
最终用户notificador=getUserById(userNotificadorId.toLowerCase());
适用于(CentroDeCostos centroCosto:listCentroCostoPadres){
如果(HasCentroDecosToResponsible(centroCosto)){
用户负责=getResponsableByCc(centroCosto);
创建通知(负责人、通知人、门萨杰);
if(iUserFormail(负责)){
目的。添加(负责);
}
}
}
sendMailNewThread(Destinatoros、notificador、mensaje);
返回结果;
}
私有void sendMailNewThread(最终设置目的、最终用户通知、最终字符串mensaje){
Runnable r=新的Runnable(){
@凌驾
公开募捐{
发送电子邮件(目的地、通知人、门萨耶);
}
};
螺纹=新螺纹(r);
thread.start();
}
如何避免这个错误?我明白了,执行Runnable r=new Runnable()会破坏上下文。 正确的方法是使用接口将其注入,而不是像这样实例化类:
@Inject
EmailSenderMt emailSenderMultithread;
然后:
emailSenderMultithread.setParameters(destinatarios、notificador、mensaje)
您不能实例化其中有注入的任何类,而是注入它,所以
没有新对象();
但是
@注入
对象对象
如果对象使用任何@Inject异常消息: 作用域类型javax.enterprise.context.RequestScoped没有活动上下文 表示引用了由CDI(焊接?)从线程管理的对象 您不应该从线程引用由CDI(Weld?)管理的任何Java对象。我建议您仅在线程中使用POJO
另一个解决方案可能是将被引用对象的范围从javax.enterprise.context.RequestScoped更改为javax.enterprise.context.ApplicationScoped,但只有在该对象是线程安全的情况下才这样做 您不应该在JavaEE上下文中打开线程 相反,你应该使用 和
@将此注入控制器。然后您只需调用sendNotification
,它在自己的线程中执行,但由应用程序服务器管理(应用程序服务器反过来可以使用线程池、监控等)
Thread t = new Thread(emailSenderMultithread);
t.start();
public class EmailSender {
@Resource("java:jboss/mail/Default")
private Session mailSession;
@Asynchronous
public void sendNotification(String recipient) {
// mail sending code
}
}