未为 myfaces 中的 Head 触发 PostAddToView 事件

PostAddToView event not fired for Head in myfaces

我正在向所有页面动态注入一些 JS,这在 Mojarra 中运行良好,但我发现它在 myfaces 中失败了。

我的事件侦听器配置为:

<application>
    <system-event-listener>
        <system-event-listener-class>a.b.HeadResourceListener</system-event-listener-class>
        <system-event-class>javax.faces.event.PostAddToViewEvent</system-event-class>
        <source-class>javax.faces.component.UIOutput</source-class>
    </system-event-listener>
</application>

代码类似于:

public class HeadResourceListener implements SystemEventListener {

  @Override
  public boolean isListenerForSource(Object source) {
    return "javax.faces.Head".equals(((UIComponent) source).getRendererType());
  }

  @Override
  public void processEvent(SystemEvent event) {
    UIComponent outputScript = new UIOutput();
    outputScript.setRendererType("javax.faces.resource.Script");
    UIOutput content = new UIOutput();
    content.setValue("var abc='';");
    outputScript.getChildren().add(content);
    context.getViewRoot().addComponentResource(context, outputScript, "head");
  }
}

不幸的是,对于 myfaces,源的 rendererType 从来不是 javax.faces.Head(我只发现 javax.faces.resources.Script 和 javax.faces.resources.Stylesheet)

这里的行为不同有什么具体原因吗? 对其他解决方案有什么建议吗?

编辑

如建议的那样,当将此侦听器链接到 source-class 时,它会在 myfaces 中触发。但是,在回发时,我收到重复的 ID 错误...

Caused by: org.apache.myfaces.view.facelets.compiler.DuplicateIdException:    Component with duplicate id "j_id__v_7" found. The first component is {Component-  Path : [Class: javax.faces.component.UIViewRoot,ViewId: /user/login.xhtml][Class:  org.apache.myfaces.component.ComponentResourceContainer,Id:  javax_faces_location_head][Class: javax.faces.component.UIOutput,Id: j_id__v_7]}
at  org.apache.myfaces.view.facelets.compiler.CheckDuplicateIdFaceletUtils.createAndQueueException(CheckDuplicateIdFaceletUtils.java:148)
at [internal classes]
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:73)
at org.apache.myfaces.tomahawk.application.ResourceViewHandlerWrapper.renderView(ResourceViewHandlerWrapper.java:169)
at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:73)

这是 MyFaces 中的错误。

JSF 2.3 specification 在 table 9.2 中表示以下内容:

TABLE 9-2 Standard HTML RenderKit Tag Library

getComponentType()     getRendererType()
javax.faces.Output     javax.faces.Head

根据同一规范的第 4.1.10.1 章,javax.faces.Output 映射到 javax.faces.component.UIOutput

4.1.10.1 Component Type

The standard component type for UIOutput components is “javax.faces.Output”.

因此,<h:head> 必须是 UIOutput 的实例。

如果我们回顾一下 table 9.2,javax.faces.Output 可以有多个渲染器,所以你确实只能监听 javax.faces.component.UIOutput<source-class> 并且你会必须手动检查其渲染器类型为 javax.faces.Head。你的 HeadResourceListener 是正确的。

另请参阅: