Access SessionScoped object from stateless EJB

11,236

The problem is not to access to a session-scoped bean itself, the problem is that the session is not active, probably because it has never been started (e.g. EJB remoting).

What you can do is starting a BoundSessionContext manually, have a look here. I did that for conversations, and it worked fine.

Share:
11,236
Martin Metz
Author by

Martin Metz

Updated on June 28, 2022

Comments

  • Martin Metz
    Martin Metz almost 2 years

    I do have a SessionScoped class. For each user access I need an own instance of this class. All went fine for a long time. But now I also need access to this objects from the backend without any user interaction. I do have a stateless enterprise bean but whenever I want to access the session scoped object I get an excepiton. A simple example code is as following:

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

    But calling the test method ends in an exception like:

    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:]
        ...
    

    So my question is: * Is there any option to access the object even without a session by any trick? * Is there any option to generate one session from within my stateless class?

    I understand the cause of the exception but I want to have one 'global' session for this new usage of the existing code. In reallity of course it's not so easy and changing the session scoped code to a POJO and a session scoped container is not so easy.

    Environment:

    • JDK 1.6
    • JBOSS 7.1.1

    Solution:

    As mentioned by Jan: Extend the StatelessBean as following:

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

    And the example is working! Now I just have to understand the details ;-)

  • Jan Groth
    Jan Groth almost 12 years
    That's not true. You can certainly inject a stateful object (like an authenticated user) into a stateless object. Technically you can even store stuff in SLSB, but of course you will have absolutely no guarantee that you'll be able to retrieve it..
  • Martin Metz
    Martin Metz almost 12 years
    That's it! You saved my week!