Jboss 是否有方法将SessionContext传播到新线程(获取WELD-001303)?

Jboss 是否有方法将SessionContext传播到新线程(获取WELD-001303)?,jboss,ejb,wildfly,weld,picketlink,Jboss,Ejb,Wildfly,Weld,Picketlink,我在@Stateless bean中注入了一个会话范围的bean“Identity”,该bean实现了Runnable: @Stateless @LocalBean public class Test implements Runnable { @Inject Identity identity; @Inject Logger log; @Override public void run() { log.warn("Test: "

我在@Stateless bean中注入了一个会话范围的bean“Identity”,该bean实现了Runnable:

@Stateless
@LocalBean
public class Test implements Runnable {
    @Inject
    Identity identity;
    @Inject
    Logger log;

    @Override
    public void run() {
        log.warn("Test: " + this + " " + identity.getAccount().getId());
    }
}
还有一个bean异步调用上述Runnable:

@Stateless
@LocalBean
public class BeanContextExecutor implements Executor {
    @Asynchronous
    @Override
    public void execute(Runnable command) {
        command.run();
    }
}
最后,调用如下所示:

@Stateless
public class OtherBean {
    @Inject
    BeanContextExecutor executor;
...
        executor.execute(command);
...
}
运行此命令时,我遇到以下错误:

...
Caused by: org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.SessionScoped
...
有没有办法将SessionContext传播到后台线程

我还尝试将此Runnable提交给ManagedExecutorService,甚至使用ContextService为其创建代理并提交代理,但仍然收到相同的错误


谢谢你的帮助

作为BeanContextExecutor中的一种解决方法,我使用BoundSessionContext为新线程创建虚拟会话上下文,还必须手动复制所需的会话bean,以使其状态在后台线程中可用:

@Inject
BoundSessionContext boundSessionContext;
// Backed by a ConcurrentHashMap<Runnable, Identity> which stores the state of the session scoped bean before spawning a new thread
@Inject
GlobalExecutionContext globalExecutionContext;
@Inject
Instance<Identity> identityInstance;
@Inject
Cloner cloner;
@Inject
private BeanManager beanManager;

@Asynchronous
@Override
public void execute(Runnable command) {
    HashMap<String, Object> storage = new HashMap<>();
    boundSessionContext.associate(storage);
    boundSessionContext.activate();

    Identity identity = globalExecutionContext.remove(command);
    Bean<Identity> bean = (Bean<Identity>) beanManager.resolve(beanManager.getBeans(Identity.class));
    Identity localIdentity = beanManager.getContext(bean.getScope()).get(bean, beanManager.createCreationalContext(bean));

    cloner.copyPropertiesOfInheritedClass(identity, localIdentity);

    command.run();

    boundSessionContext.invalidate();
    boundSessionContext.deactivate();
    boundSessionContext.dissociate(storage);
}
@Inject
BoundSessionContext BoundSessionContext;
//由ConcurrentHashMap支持,它在生成新线程之前存储会话范围bean的状态
@注入
GlobalExecutionContext GlobalExecutionContext;
@注入
实例识别立场;
@注入
克隆人克隆人;
@注入
专用BeanManager BeanManager;
@异步的
@凌驾
public void execute(Runnable命令){
HashMap存储=新建HashMap();
boundSessionContext.associate(存储);
boundSessionContext.activate();
Identity=globalExecutionContext.remove(命令);
Bean=(Bean)beanManager.resolve(beanManager.getBeans(Identity.class));
Identity localIdentity=beanManager.getContext(bean.getScope()).get(bean,beanManager.createCreationContext(bean));
cloner.CopyPropertiesFinheritedClass(标识、本地身份);
command.run();
boundSessionContext.invalidate();
boundSessionContext.deactivate();
解离(存储);
}
该示例旨在演示该方法,可以像支持传递任意类型的bean一样对其进行改进。但我一点也不喜欢这种方法。对于上下文传播问题,应该有更好的解决方案

更新:
我希望在后台线程中保留调用方标识,即使初始会话已过期,上面的解决方案似乎适用于此。

作为BeanContextExecutor中的一个解决方案,我使用BoundSessionContext为新线程创建了一个虚拟会话上下文,还必须手动复制所需的会话bean,以使其状态在后台线程中可用:

@Inject
BoundSessionContext boundSessionContext;
// Backed by a ConcurrentHashMap<Runnable, Identity> which stores the state of the session scoped bean before spawning a new thread
@Inject
GlobalExecutionContext globalExecutionContext;
@Inject
Instance<Identity> identityInstance;
@Inject
Cloner cloner;
@Inject
private BeanManager beanManager;

@Asynchronous
@Override
public void execute(Runnable command) {
    HashMap<String, Object> storage = new HashMap<>();
    boundSessionContext.associate(storage);
    boundSessionContext.activate();

    Identity identity = globalExecutionContext.remove(command);
    Bean<Identity> bean = (Bean<Identity>) beanManager.resolve(beanManager.getBeans(Identity.class));
    Identity localIdentity = beanManager.getContext(bean.getScope()).get(bean, beanManager.createCreationalContext(bean));

    cloner.copyPropertiesOfInheritedClass(identity, localIdentity);

    command.run();

    boundSessionContext.invalidate();
    boundSessionContext.deactivate();
    boundSessionContext.dissociate(storage);
}
@Inject
BoundSessionContext BoundSessionContext;
//由ConcurrentHashMap支持,它在生成新线程之前存储会话范围bean的状态
@注入
GlobalExecutionContext GlobalExecutionContext;
@注入
实例识别立场;
@注入
克隆人克隆人;
@注入
专用BeanManager BeanManager;
@异步的
@凌驾
public void execute(Runnable命令){
HashMap存储=新建HashMap();
boundSessionContext.associate(存储);
boundSessionContext.activate();
Identity=globalExecutionContext.remove(命令);
Bean=(Bean)beanManager.resolve(beanManager.getBeans(Identity.class));
Identity localIdentity=beanManager.getContext(bean.getScope()).get(bean,beanManager.createCreationContext(bean));
cloner.CopyPropertiesFinheritedClass(标识、本地身份);
command.run();
boundSessionContext.invalidate();
boundSessionContext.deactivate();
解离(存储);
}
该示例旨在演示该方法,可以像支持传递任意类型的bean一样对其进行改进。但我一点也不喜欢这种方法。对于上下文传播问题,应该有更好的解决方案

更新: 即使初始会话已过期,我也希望将调用方标识保留在后台线程中,看起来上面的解决方案适用于此