我刚刚将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。
还有什么可能导致此异常吗?此外,如果无法做到这一点,还有另一种方法可以实现我正在做的事情吗?
答案 0 :(得分:3)
@ViewScoped
注释将bean绑定到特定的JSF视图,而该视图依赖于FacesContext#getViewRoot()
和随后UIViewRoot#getViewMap()
的存在。两者都没有在“普通香草”servlet中可用。在普通的servlet请求中没有JSF视图的手段,更不用说JSF上下文了。所以,不幸的是,这种行为是“按设计”。
你基本上有两种选择:
将所需的共享信息存储在会话范围中,该范围由唯一键键入,该唯一键作为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);
使用真正的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;
// ...
}