2013-09-25 26 views
2

我正在尝试使用OmniFaces的小改动动态地将复合组件添加到另一个UIComponent Faces.includeCompositeComponent(...)。我试图重新创建this question的行为,但它不起作用。如何使用“Faces.includeCompositeComponent”?动态添加组件。 Websphere 8和ICEFaces 3

的适应方法的代码如下(我把它从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之下。下面是它的内容:

test.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标签到taglib.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.java:496)行是指以完全相同的代码UIComponent composite = application.createComponent(context, resource);行,这实际上表明没有上一行正在创建的资源:Resource resource = application.getResourceHandler().createResource(resourceName, libraryName);

有没有人有任何想法为什么会发生这种情况?我甚至试图改变资源的位置inc-templates/test.xhtml,甚至只是test.xhtml当调用该方法,但没有任何工作......我总是得到相同的错误。

顺便说一句,我正尝试在WebSphere 8和I'm部署使用ICEFaces的3

提前感谢!

回答

1

看来你是混合复合组件与标签文件。要查看和理解这两个头对这个答案和其中的链接之间的区别:When to use <ui:include>, tag files, composite components and/or custom components?

您的XHTML文件清楚地表示一个复合组件。但是,您将它视为标签文件。它已被放置在/WEB-INF文件夹中,如标记文件而不是/resources文件夹,就像是一个真正的复合文件。它已被注册在.taglib.xml文件中,如标签文件,而不是像真正的组合一样无配置文件。

目前还不完全清楚你到底想要什么。你想以编程方式包含包含文件,标签文件或复合组件吗?假设您实际上想要以编程方式包含复合组件(否则includeCompositeComponent()的整个用法是完全没有意义的)。在这种情况下,XHTML文件移动到像如在所有复合材料部件的教程/resources文件夹(在这样的方式,当你在任意的XHTML模板客户端使用<my:test>也确实有效):

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

摆脱.taglib.xml中不必要的条目,最后使用库名null和资源名/mycomponents/test.xhtml包含它。

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

非常感谢! 正如您所设想的那样,我试图以编程方式包含复合组件。我做了你的建议,它的工作:) – jcrusoe