我想以编程方式实例化复合或标记组件。
此实例化将由自定义组件执行,通常将这些复合或标记组件添加为子组件。
我在爬取论坛时找到的最佳答案是:http ://www.java.net/node/701640#comment-791881 。它看起来很像我在这个论坛上找到的另一个答案:如何以编程方式或动态地在 JSF 2 中创建复合组件。
在处理这个问题时,我终于编写了适用于使用 MyFaces 的复合实例化的代码(链接中的示例似乎是特定于 Mojarra 的)。我把它复制到那里,因为我花了一些时间来写它,希望它能帮助别人:
public UIComponent instantiateComposite(String namespace, String componentName) {
FacesContext ctx = FacesContext.getCurrentInstance();
Resource resource = ctx.getApplication().getResourceHandler().createResource( componentName + ".xhtml", namespace );
UIComponent cc = ctx.getApplication().createComponent( ctx, resource );
UIPanel panel = (UIPanel) ctx.getApplication().createComponent( UIPanel.COMPONENT_TYPE );
// set the facelet's parent
cc.getFacets().put( UIComponent.COMPOSITE_FACET_NAME, panel );
FaceletFactory ff = (DefaultFaceletFactory) DefaultFaceletFactory.getInstance();
if(ff == null) {
FaceletViewDeclarationLanguage vdl = new FaceletViewDeclarationLanguage(ctx);
Method createCompiler = null;
Method createFaceletFactory = null;
try {
createCompiler = FaceletViewDeclarationLanguage.class.getDeclaredMethod("createCompiler",FacesContext.class);
createFaceletFactory = FaceletViewDeclarationLanguage.class.getDeclaredMethod("createFaceletFactory",FacesContext.class,org.apache.myfaces.view.facelets.compiler.Compiler.class);
createCompiler.setAccessible(true);
createFaceletFactory.setAccessible(true);
org.apache.myfaces.view.facelets.compiler.Compiler compiler = (org.apache.myfaces.view.facelets.compiler.Compiler) createCompiler.invoke(vdl, ctx);
ff = (FaceletFactory) createFaceletFactory.invoke(vdl, ctx, compiler);
} catch (IllegalAccessException ex) {
Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalArgumentException ex) {
Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvocationTargetException ex) {
Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoSuchMethodException ex) {
Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex);
} catch (SecurityException ex) {
Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex);
}
}
try {
Facelet facelet = ff.getFacelet(resource.getURL());
facelet.apply( ctx, panel );
} catch ( IOException e ) {
e.printStackTrace();
}
return cc;
}
请不要注意丑陋的异常处理:它是由 netbeans 自动生成的......我会问 MyFaces 开发人员是否有办法避免丑陋的反射黑客。
我怎样才能对标签组件做同样的事情,我的意思是组件声明如下:
<tag>
<description>blah blah</description>
<tag-name>myWonderfulTag</tag-name>
<source>tags/mwl/myWonderfulTag.xhtml</source>
<!-- attributes -->
</tag>
在标签库中。
提前致谢。