使用可选的facelet标记库

时间:2015-08-04 13:52:03

标签: jsf jsf-2

我有一个使用可选模块的Web应用程序。这些模块是作为Web Fragment项目实现的,根据构建配置文件,它们的jar可能会也可能不会与war一起部署。

模块可以包含自己的module.taglib.xml http://company.com/module命名空间和一些标记。

war xhtml模板使用这样的模块标签:

<ui:composition ... xmlns:mod="http://company.com/module">

<c:if test="#{moduleDeployed}">
    <mod:someTag />
</c:if>

问题。

  1. 当未部署模块时,war页面工作正常,但在ProjectStage.Development中我收到FacesMessage警告:
      

    警告:此页面调用XML命名空间   http://company.com/module用前缀mod声明但没有   该命名空间存在taglibrary。

  2. 据我所知,当模板使用不存在的标记库时,JSF规范没有定义会发生什么。因此,使用我当前的方法,war页面可能会在升级或切换到其他JSF实现后停止工作。
  3. 问题。

    1. 是否有(非常难看的)方法来禁用此特定警告?
    2. 使用可选的facelet标记库是否有更好的方法?
    3. 截至目前,我计划尽可能禁用警告:例如如果必须,覆盖消息渲染器并检查消息字符串。如果问题2出现,请为未部署的模块创建构建供应占位符taglib.xml文件。

1 个答案:

答案 0 :(得分:0)

尽管占位符taglib似乎是一个非常好的解决方案,但它们似乎也难以实现和维护。

所以最后我去了过滤消息。这可能是Mojarra特有的:消息文本,迭代器允许删除的事实(这不是规范禁止的,但它也不是必需的)。众所周知,它与Mojarra 2.2.8至2.2.13一起使用。

public class SuppressNoTaglibraryExistsFacesMessage implements SystemEventListener {
    private static final Pattern PTTRN_NO_TAGLIBRARY_EXISTS_FOR_NAMESPACE =
            Pattern.compile("Warning: This page calls for XML namespace \\S+ declared with "
            + "prefix \\S+ but no taglibrary exists for that namespace.");

    @Override
    public void processEvent(SystemEvent event) {
        Iterator<FacesMessage> messages = FacesContext.getCurrentInstance().getMessages();
        while (messages.hasNext()) {
            String messageSummary = messages.next().getSummary();
            if (PTTRN_NO_TAGLIBRARY_EXISTS_FOR_NAMESPACE.matcher(messageSummary).matches()) {
                messages.remove();
            }
        }
    }

    @Override
    public boolean isListenerForSource(Object source) {
        return true;
    }
}

仅在开发项目阶段绑定侦听器。

public class SubscribeListenersAfterApplicationPostConstructListener
        implements SystemEventListener {
    @Override
    public void processEvent(SystemEvent event) throws AbortProcessingException {
        Application application = (Application) event.getSource();
        if (ProjectStage.Development.equals(application.getProjectStage())) {
            application.subscribeToEvent(PostAddToViewEvent.class, UIViewRoot.class,
                    new SuppressNoTaglibraryExistsFacesMessage());
        }
    }

    @Override
    public boolean isListenerForSource(Object source) {
        return source instanceof Application;
    }

}

在faces-config.xml中:

<system-event-listener>
    <system-event-listener-class><packages>.SubscribeListenersAfterApplicationPostConstructListener</system-event-listener-class>
    <system-event-class>javax.faces.event.PostConstructApplicationEvent</system-event-class>
</system-event-listener>