代码之家  ›  专栏  ›  技术社区  ›  jcrusoe

如何使用“Faces.includeCompositeComponent”动态添加组件?。Websphere 8和ICEFaces 3

  •  2
  • jcrusoe  · 技术社区  · 11 年前

    我正在尝试使用OmniFaces的一个小的改编将一个复合组件动态添加到另一个UIComponent Faces.includeCompositeComponent(...) 我试着重现 this question 但它不起作用。

    适用方法的代码如下(我取自 OmniFaces v1.6版本 )

    /**
       * Create and include the composite component of the given library ane
       * resource name as child of the given UI component parent and return the
       * created composite component. This has the same effect as using
       * <code>&lt;my:resourceName&gt;</code>. The given component ID must be unique
       * relative to the current naming container parent and is mandatory for
       * functioning of input components inside the composite, if any.
       * 
       * @param parent The parent component to include the composite component in.
       * @param libraryName The library name of the composite component.
       * @param resourceName The resource name of the composite component.
       * @param id The component ID of the composite component.
       * @return The created composite component, which can if necessary be further
       *         used to set custom attributes or value expressions on it.
       * @since 1.5
       */
      public static UIComponent includeCompositeComponent(UIComponent parent, String libraryName, String resourceName, String id)
      {
        // Prepare.
        FacesContext context = FacesContext.getCurrentInstance();
        Application application = context.getApplication();
        FaceletContext faceletContext = (FaceletContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
    
        // This basically creates <ui:component> based on <composite:interface>.
        Resource resource = application.getResourceHandler().createResource(resourceName, libraryName);
        UIComponent composite = application.createComponent(context, resource);
        composite.setId(id); // Mandatory for the case composite is part of UIForm!
                             // Otherwise JSF can't find inputs.
    
        // This basically creates <composite:implementation>.
        UIComponent implementation = application.createComponent(UIPanel.COMPONENT_TYPE);
        implementation.setRendererType("javax.faces.Group");
        composite.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, implementation);
    
        // Now include the composite component file in the given parent.
        parent.getChildren().add(composite);
        parent.pushComponentToEL(context, composite); // This makes #{cc} available.
        try
        {
          faceletContext.includeFacelet(implementation, resource.getURL());
        }
        catch (IOException e)
        {
          throw new FacesException(e);
        }
        finally
        {
          parent.popComponentFromEL(context);
        }
    
        return composite;
     }
    

    这就是我尝试使用它的方式

    JSFUtils.includeCompositeComponent(panelGroup, "comp", 
       "../inc-templates/test.xhtml", JSFUtils.createUniqueId());
    

    此外,我创建了“test.xhtml”文件,并将其放在 WEB-INF/inc-templates/test.xhtml 。内容如下:

    测试.xhtml

    <?xml version='1.0' encoding='UTF-8' ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:cc="http://java.sun.com/jsf/composite"
          xmlns:ui="http://java.sun.com/jsf/facelets"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:f="http://java.sun.com/jsf/core"
          xmlns:p="http://primefaces.org/ui"
          xmlns:composite="http://java.sun.com/jsf/composite">
        <!-- INTERFACE -->
        <cc:interface>
    
        </cc:interface>
    
        <!-- IMPLEMENTATION -->
        <cc:implementation>
            <h:outputText value="TEST"/>
        </cc:implementation>
    </html>
    

    最后但同样重要的是,我将test.xhtml标记添加到 标签库.xml ,如下所示:

    <tag>
      <tag-name>test</tag-name>
      <source>../inc-templates/test.xhtml</source>
    </tag>
    

    问题是,当我运行代码并尝试插入组件时,我会得到以下异常

    Caused by: java.lang.NullPointerException: Argumentfehler: Parameter componentResource ist null
            at com.sun.faces.util.Util.notNull(Util.java:314)
            at com.sun.faces.application.ApplicationImpl.createComponent(ApplicationImpl.java:928)
            at org.my.JSFUtils.includeCompositeComponent(JSFUtils.java:496)
    

    和线路 网址:org.my.JSFUtils.includeCompositeComponent(JSFUtils.cava:496) 确切地指代码行 UIComponent composite = application.createComponent(context, resource); ,这实际上表明资源不是在前一行中创建的: Resource resource = application.getResourceHandler().createResource(resourceName, libraryName);

    有人知道为什么会发生这种事吗?。我甚至尝试将资源的位置更改为 inc-templates/test.xhtml 甚至只是 测试.xhtml 调用该方法时,但什么都不起作用。。。我总是犯同样的错误。

    顺便说一句,我正在尝试在Websphere 8中进行部署,我正在使用ICEFaces 3。

    提前谢谢!

    1 回复  |  直到 4 年前
        1
  •  1
  •   Community ahmed    7 年前

    似乎您将复合组件与标记文件混合在一起。要查看并理解两者之间的差异,请参阅此答案及其内部的链接: When to use <ui:include>, tag files, composite components and/or custom components?

    XHTML文件清楚地表示了一个复合组件。然而,您将其视为一个标记文件。它被放置在 /WEB-INF 文件夹类似于标记文件,而不是 /resources 文件夹就像一个真正的合成。它已在 .taglib.xml 像标签文件一样的文件,而不是像真正的复合文件那样的无配置文件。

    目前还不完全清楚你到底想要什么。是否要以编程方式包含包含文件、标记文件或复合组件?让我们假设您实际上想要以编程方式包含一个复合组件(否则 includeCompositeComponent() 完全没有意义)。在这种情况下,将XHTML文件移动到 /资源 文件夹,如所有复合组件教程中所示(这样,当您使用 <my:test> 在任何任意XHTML模板客户端中):

    WebContent
     |-- WEB-INF
     |    `-- lib
     |-- resources
     |    `-- mycomponents
     |         `-- test.xhtml   <---
     `-- some.xhtml
    

    清除中不必要的条目 .taglib.xml 最后使用的库名称将其包括在内 null 和的资源名称 /mycomponents/test.xhtml .

    includeCompositeComponent(parent, null, "/mycomponents/test.xhtml", uniqueId);