2

I have to programmatically lookup a session scoped bean managed by CDI from a servlet.

So far I've managed to lookup default scoped beans using a BeanManager instance. However for session scoped beans the lookup fails with the following message:

org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type javax.enterprise.context.SessionScoped
    org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:598)
    org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:71)
    org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:79)
    de.eb.mdsd.prototype.server.SessionStuff$Proxy$_$$_WeldClientProxy.test(SessionStuff$Proxy$_$$_WeldClientProxy.java)
    de.eb.mdsd.prototype.server.FooServlet.doGet(FooServlet.java:21)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:734)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
    org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
    org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
    org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
    org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
    org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383)
    org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
    org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)

Is there any way to manually set the active session scope? The application is currently running on JBoss 7, so the CDI implementation is Weld, however a generic solution not limited to Weld would be best.

Here's the code I've been using so far:

public class FooServlet extends HttpServlet {

    private static final long   serialVersionUID    = 1L;

    @Override
    protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
        final SessionStuff sessionStuff = lookup(SessionStuff.class);
        sessionStuff.test();
    }

    private BeanManager getBeanManager() {
        try {
            return (BeanManager) InitialContext.doLookup("java:comp/BeanManager");
        }
        catch (final NamingException e) {
            throw Exceptions.propagate(e);
        }
    }

    @SuppressWarnings("unchecked")
    private <T> T lookup(final Class<T> clazz) {
        final BeanManager bm = getBeanManager();
        final Iterator<Bean<?>> iter = bm.getBeans(clazz).iterator();
        if (!iter.hasNext()) {
            throw new IllegalStateException("CDI BeanManager cannot find an instance of requested type " + clazz.getName());
        }
        final Bean<T> bean = (Bean<T>) iter.next();
        final CreationalContext<T> ctx = bm.createCreationalContext(bean);
        return (T) bm.getReference(bean, clazz, ctx);
    }

}
Johannes
  • 133
  • 2
  • 11
  • This seems like it should work. But I see you're using Shiro and it can use http sessions or use it's own session management. Just in case you're using Shiro's session management features, try switching it to http sessions just in case there is some interference with CDI. – rdcrng May 29 '13 at 13:28
  • 1
    Have you considered Deltaspike? Specifically MyBean myBean = BeanProvider.getContextualReference(MyBean.class, false); http://deltaspike.apache.org/deltaspike/core.html Good luck! – Karl Kildén May 29 '13 at 14:24
  • @rdcrng I've disabled Shiro, but it had no effect. But AFAIK the application was already using "normal" HTTP sessions, so this was to be expected. – Johannes May 29 '13 at 14:40
  • @KarlKildén Using DeltaSpike seems to solve the problem. Thanks! I'll have to look into the source to see what kind of black magic they're using :) – Johannes May 29 '13 at 14:52
  • 2
    I'm not sure why you need to do it this way. Servlet a support injection. – LightGuard May 29 '13 at 15:09
  • I bet the problem lies in the fact that you never called BeanManager#resolve() on your set of beans. Instead, you just grabbed the first one out of the iterator. But, take a look at the DS source, I bet they call resolve :) – rdcrng May 29 '13 at 15:20
  • @Johannes np thank LightGuard and the others behind deltaspike ;) – Karl Kildén May 29 '13 at 16:15
  • There are configurations diferences between CDI 1 and CDI 2 [link](https://stackoverflow.com/questions/8166187/can-i-and-how-lookup-cdi-managed-beans-using-javax-naming-contextlookup-in-ej/28971109#28971109) – Halley Nov 10 '17 at 11:45

0 Answers0