新线程导致ContextNotActiveException

时间:2014-06-10 15:15:04

标签: java multithreading jboss wicket

我正在尝试在Wicket框架应用程序中启动一个新线程,我得到了:

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

如何避免此错误?

3 个答案:

答案 0 :(得分:1)

你不应该在JavaEE环境中打开Threads。

相反,您应该使用@Asynchronous

public class EmailSender {

  @Resource("java:jboss/mail/Default")
  private Session mailSession;

  @Asynchronous
  public void sendNotification(String recipient) {
    // mail sending code
  }
}

@Inject这个进入你的控制器。然后,您只需调用sendNotification并在其自己的线程中执行,但由应用程序服务器(可以依次使用线程池,监视等)进行管理。

答案 1 :(得分:0)

我明白了,做Runnable r = new Runnable()破坏了上下文。 正确的方法是使用一个接口注入它而不是实例化类,如下所示:

@Inject
EmailSenderMt emailSenderMultithread;

然后:

emailSenderMultithread.setParameters(destinatarios,notificador,mensaje);

    Thread t = new Thread(emailSenderMultithread);
    t.start();

你不能实例化其中有注射的任何类,而是注入它,所以

没有新的Object(); 但

@注入 对象对象;

如果Object使用任何@Inject

答案 2 :(得分:0)

异常消息:

  

范围类型javax.enterprise.context.RequestScoped没有活动的上下文

表示您从线程引用由CDI(Weld?)管理的对象。

您不应该从线程引用由CDI(Weld?)管理的任何Java对象。我建议你只在线程中使用POJO。

另一个解决方案可能是将引用对象的范围从javax.enterprise.context.RequestScoped更改为javax.enterprise.context.ApplicationScoped - 但只有在此对象是线程安全的情况下才能执行此操作!