如何在“命名空间模式”下使用jsf

问题描述 投票:3回答:1

[在网站中,我们希望集成jsf-applications提供的一些代码片段,考虑使用dashboard-app或“ portal-light”。在分析需求时,我们遇到了Arjan Tjims在jsf 2.3 new features上的博客文章,他在其中提到了新的“命名空间模式”:

在命名空间模式下,该模式专门用于Portlet,但也可以在其他环境中使用,部分响应具有一个ID,该ID被视为“命名容器ID”。所有预定义的回发参数名称(例如“ javax.faces.ViewState”,“ javax.faces.ClientWindow”,“ javax.faces.RenderKitId”等)均带有此前缀和命名分隔符(默认为“:”)。例如javax.faces.ViewState”变为“ myname:javax.faces.ViewState”。当UIViewRoot实例实现NamingContainer接口时,将激活命名空间模式。

我们的应用程序可能是该“命名空间模式”的用例,因此我们想尝试一下。

我们构建了一个MyUIViewRoot,在其中实现了NamingContainer并包装了原始的UIViewRoot实例。我们在MyViewHandler中注册了faces-config.xml,用于处理ViewRoot的环绕。为了进行测试,我们使用了带有两个<h:form>元素的简单计数器应用(似乎很重要)。

[我们发现似乎已激活“命名空间模式”,例如javax.faces.ViewState确实由某个命名空间添加,并变为j_id1:javax.faces.ViewState:0。但是,这两个操作都不再起作用-回发请求不再恢复视图,而是创建一个新视图。因此,使用我们的简单方法,我们会丢失一些内容(顺便说一句,仅从implements NamingContainer中删除MyUIViewRoot,计数器应用仍然可以正常工作)。

  • 是否有一些我们忽略的文档,指导或工作示例?
  • 如何正确激活“命名空间模式”?我们错过了什么才能使回发再次起作用?
  • 我们如何使MyUIViewRoot在ViewState之前加上myNamespace
  • 该应用程序在payara-5应用程序服务器中运行。

我们的index.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
  xmlns:h="http://xmlns.jcp.org/jsf/html"
  xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head/>
<h:body>
  <h:form id="counterForm">
    <h:panelGrid columns="2">
      <h:outputLabel value="Counter" />
      <h:outputText value="#{counterUiController.counter}" />
    </h:panelGrid>
    <h:commandButton value="inc" action="#{counterUiController.incAction}">
      <f:ajax execute="@form" render="@form" />
    </h:commandButton>
  </h:form>
  <h:form id="resetForm">
    <h:commandButton value="reset" action="#{counterUiController.resetAction}">
      <f:ajax execute="@form" render=":counterForm" />
    </h:commandButton>
  </h:form>
</h:body>
</html>

CounterUiController:

@Named
@ViewScoped
public class CounterUiController implements Serializable {

    private int counter;

    public int getCounter() {
        return counter;
    }

    public void incAction() {
        counter++;
    }

    public void resetAction() {
        counter=0;
    }
}

我们的UIViewRoot-实施:

public class MyUIViewRoot extends UIViewRoot implements NamingContainer, FacesWrapper<UIViewRoot> {

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

    private UIViewRoot wrapped;

    public MyUIViewRoot(UIViewRoot wrapped) {
        this.wrapped = wrapped;
        LOG.log(Level.INFO, "new instance created: {0}", this);
    }

    @Override
    public UIViewRoot getWrapped() {
        return wrapped;
    }

    @Override
    public String createUniqueId() {
        return wrapped==null ? null : wrapped.createUniqueId();
    }

    @Override
    public void setId(String id) {
        if( wrapped!=null ) {
            wrapped.setId(id);
        }
    }
    // all other methodes delegated to `wrapped` directly
}

我们的ViewHandler

public class MyViewHandler extends ViewHandlerWrapper {

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

    public MyViewHandler(ViewHandler wrapped) {
        super(wrapped);
    }

    @Override
    public UIViewRoot createView(FacesContext context, String viewId) {
        UIViewRoot retval = super.createView(context, viewId);
        retval = wrapIfNeeded(retval);
        LOG.log(Level.INFO, "view created: {0}", retval);
        return retval;
    }

    @Override
    public UIViewRoot restoreView(FacesContext context, String viewId) {
        UIViewRoot retval =  super.restoreView(context, viewId);
        retval = wrapIfNeeded(retval);
        LOG.log(Level.INFO, "view restored: {0}", retval);
        return retval;
    }

    private UIViewRoot wrapIfNeeded(UIViewRoot root) {
        if (root != null && !(root instanceof MyUIViewRoot)) {
            LOG.log(Level.INFO, "view wrapped: {0}, {1}", new Object[] { root, root.getId() });
            return new MyUIViewRoot(root);
        } else {
            return root;
        }
    }
}

[在网站中,我们希望集成jsf-applications提供的一些代码片段,考虑使用dashboard-app或“ portal-light”。在分析需求时,我们遇到了Arjan Tjims的博客文章...

jsf mojarra jsf-2.3
1个回答
3
投票

您需要替换UIViewRoot而不要包裹它。

© www.soinside.com 2019 - 2024. All rights reserved.