在Servlet中注入OmniFaces ViewScoped bean时的ContextNotActiveException

时间:2013-10-02 13:56:15

标签: jsf servlets cdi omnifaces view-scope

我刚刚将SessionScoped bean更新为OmniFaces(1.6.1)ViewScoped。一切似乎都有效,除了当我的支持bean被注入到我用于处理ajax请求的Servlet中时,我得到以下异常:

org.jboss.weld.context.ContextNotActiveException: WELD-001303 No active contexts for scope type org.omnifaces.cdi.ViewScoped

需要考虑的一些事项:

1)我必须将一个支持bean注入servlet的原因是因为我使用的是jQuery的DataTables插件,(对于服务器端处理表)需要一个ajax请求来检索表数据。所以基本上我不能使用Primefaces'<p:remoteCommand..>或类似的东西。

2)据我所知,视图中没有任何额外的GET请求会破坏并重新创建支持bean。

还有什么可能导致此异常吗?此外,如果无法做到这一点,还有另一种方法可以实现我正在做的事情吗?

1 个答案:

答案 0 :(得分:3)

@ViewScoped注释将bean绑定到特定的JSF视图,而该视图依赖于FacesContext#getViewRoot()和随后UIViewRoot#getViewMap()的存在。两者都没有在“普通香草”servlet中可用。在普通的servlet请求中没有JSF视图的手段,更不用说JSF上下文了。所以,不幸的是,这种行为是“按设计”。

你基本上有两种选择:

  1. 将所需的共享信息存储在会话范围中,该范围由唯一键键入,该唯一键作为HTTP请求参数传递,以便JSF托管bean和servlet都可以从会话范围中获取它。

    E.g。在JSF支持bean中:

    dataId = UUID.randomUUID().toString();
    externalContext.getSessionMap().put(dataId, data);
    

    在JSF视图中:

    <h:outputScript>var dataId = "#{bean.dataId}";</h:outputScript>
    

    在JavaScript中:

    function loadData() {
        $.get("servletURL", { dataId: dataId }, function(response) {
            // ...
        });
    }
    

    在servlet中:

    String dataId = request.getParameter("dataId");
    Data data = (Data) session.getAttribute(dataId);
    

  2. 使用真正的JSF支持bean而不是普通的vanilla servlet。你绝对可以使用<p:remoteCommand>。您可以使用RequestContext#addCallbackParam() in action(listener)方法从Java传递“传递”(“print”在技术上更正确)JSON对象到JS,最后使用oncomplete属性来处理它。鉴于您使用的是OmniFaces,<o:commandScript>Ajax#data()提供了相同的功能。 Ajax#data()具有额外的优势,它可以自动从Java转换为JSON,因此您无需自己执行此操作。

    E.g。在JSF视图中:

    <o:commandScript name="loadData" action="#{bean.loadData}" oncomplete="processData()" />
    

    在JSF支持bean中:

    public void loadData() {
        Ajax.data(data);
    }
    

    在JavaScript中:

    function processData() {
        var data = OmniFaces.Ajax.data;
        // ...
    }