Java 从无状态EJB访问SessionScoped对象

Java 从无状态EJB访问SessionScoped对象,java,jakarta-ee,cdi,Java,Jakarta Ee,Cdi,我确实上了一节课。对于每个用户访问,我需要这个类的一个自己的实例。很长一段时间一切都很好。 但是现在我还需要在没有任何用户交互的情况下从后端访问这些对象。 我确实有一个无状态企业bean,但每当我想访问会话范围的对象时,我都会得到一个例外。 下面是一个简单的示例代码: @SessionScoped public class SessionObj implements Serializable { public String getValue() { return "He

我确实上了一节课。对于每个用户访问,我需要这个类的一个自己的实例。很长一段时间一切都很好。 但是现在我还需要在没有任何用户交互的情况下从后端访问这些对象。 我确实有一个无状态企业bean,但每当我想访问会话范围的对象时,我都会得到一个例外。 下面是一个简单的示例代码:

@SessionScoped
public class SessionObj implements Serializable {

    public String getValue() {
        return "Hello World";
    }
}

@Stateless
public class StatelessBean {

    private static final Logger LOG=Logger.getLogger(StatelessBean.class);

    @Inject
    private SessionObj sessionObj;

    public void test() {
        LOG.info("session object: "+sessionObj);
        LOG.info("Method call: "+sessionObj.getValue());
    }

}
@Stateless
public class StatelessBean {

    private static final Logger LOG=Logger.getLogger(StatelessBean.class);

    @Inject
    private BoundSessionContext sessionContext;

    @Inject
    private SessionObj sessionObj;

    public void test() {
        Map<String,Object> myMap=new HashMap<String,Object>();
        sessionContext.associate(myMap);
        sessionContext.activate();

        LOG.info("session object: "+sessionObj);
        LOG.info("Method call: "+sessionObj.getValue());

        sessionContext.invalidate();
        sessionContext.deactivate();
    }

}
但调用测试方法会导致以下异常:

12:19:10,484 ERROR [org.jboss.as.ejb3.tx.CMTTxInterceptor] (EJB default - 6)    javax.ejb.EJBTransactionRolledbackException: WELD-001303 No active contexts for scope type javax.enterprise.context.SessionScoped
12:19:10,484 ERROR [org.jboss.ejb3.invocation] (EJB default - 6) JBAS014134: EJB Invocation failed on component StatelessBean for method public void package.StatelessBean.test(): javax.ejb.EJBTransactionRolledbackException: WELD-001303 No active contexts for scope type javax.enterprise.context.SessionScoped
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleInCallerTx(CMTTxInterceptor.java:139) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInCallerTx(CMTTxInterceptor.java:204) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:306) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:190) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.1.Final.jar:1.1.1.Final]
    ...
Caused by: org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active    contexts for scope type javax.enterprise.context.SessionScoped
    at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:598) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
    at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:71) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
    at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:79) [weld-core-1.1.5.AS71.Final.jar:2012-02-10 15:31]
    at package.SessionObj$Proxy$_$$_WeldClientProxy.toString(SessionObj$Proxy$_$$_WeldClientProxy.java) [ws_core_job_manager.jar:]
    at java.lang.String.valueOf(String.java:2826) [rt.jar:1.6.0_21]
    at java.lang.StringBuilder.append(StringBuilder.java:115) [rt.jar:1.6.0_21]
    at package.StatelessBean.test(StatelessBean.java:29) [ws_core_job_manager.jar:]
    ...
所以我的问题是: *是否有任何选项可以通过任何技巧在没有会话的情况下访问对象? *在我的无状态类中是否有生成一个会话的选项

我理解异常的原因,但我希望对现有代码的这种新用法有一个“全局”会话。实际上,这当然不是那么容易,将会话范围的代码更改为POJO和会话范围的容器也不是那么容易

环境:

  • JDK1.6
  • JBOSS 7.1.1
解决方案: 正如Jan提到的: 扩展无状态bean,如下所示:

@SessionScoped
public class SessionObj implements Serializable {

    public String getValue() {
        return "Hello World";
    }
}

@Stateless
public class StatelessBean {

    private static final Logger LOG=Logger.getLogger(StatelessBean.class);

    @Inject
    private SessionObj sessionObj;

    public void test() {
        LOG.info("session object: "+sessionObj);
        LOG.info("Method call: "+sessionObj.getValue());
    }

}
@Stateless
public class StatelessBean {

    private static final Logger LOG=Logger.getLogger(StatelessBean.class);

    @Inject
    private BoundSessionContext sessionContext;

    @Inject
    private SessionObj sessionObj;

    public void test() {
        Map<String,Object> myMap=new HashMap<String,Object>();
        sessionContext.associate(myMap);
        sessionContext.activate();

        LOG.info("session object: "+sessionObj);
        LOG.info("Method call: "+sessionObj.getValue());

        sessionContext.invalidate();
        sessionContext.deactivate();
    }

}
@无状态
公共类无状态bean{
私有静态最终记录器LOG=Logger.getLogger(无状态bean.class);
@注入
私有边界会话上下文会话上下文;
@注入
非公开会议;
公开无效测试(){
Map myMap=newhashmap();
sessionContext.associate(myMap);
sessionContext.activate();
LOG.info(“会话对象:+sessionObj”);
LOG.info(“方法调用:”+sessionObj.getValue());
sessionContext.invalidate();
sessionContext.deactivate();
}
}
这个例子是有效的!
现在我只需要了解细节;-)

您不能使用无状态bean访问会话或在其中存储某些内容,这就是为什么它们被称为无状态的!您唯一可以访问的是EjbContext,您可以从中获得调用方主体和凭据,但不要忘记首先配置登录模块。

问题不是访问会话范围的bean本身,问题是会话未处于活动状态,可能是因为它从未启动过(例如EJB远程处理)


您可以手动启动
BoundSessionContext
,看看。我这样做是为了谈话,效果很好。

那不是真的。您当然可以将有状态对象(如经过身份验证的用户)注入无状态对象。从技术上讲,你甚至可以在SLSB中存储东西,但当然,你绝对不能保证你能够检索到它……就这样!你救了我一周!使用您的解决方案,
SessionObj
的实例将在调用
test
完成时丢失(变得不可访问),对吗?每次都会得到一个新实例。这就是你想要的吗?@Tom-解决方案没有问题,因为对
SessionObj
的引用是代理的,