简体   繁体   English

如何以编程方式实例化复合组件或标签组件?

[英]How to programmatically instantiate a composite component or a tag component?

I would like to programmatically instantiate composite or tag components. 我想以编程方式实例化复合或标记组件。

This instantiation would be performed by a custom component, typically adding those composite or tag components as children. 此实例化将由自定义组件执行,通常将这些组合或标记组件添加为子组件。

The best answer I found when crawling forums is : http://www.java.net/node/701640#comment-791881 . 我在抓取论坛时找到的最佳答案是: http//www.java.net/node/701640#comment-791881 It looks a lot like another answer I found on this forum : How to programmatically or dynamically create a composite component in JSF 2 . 它看起来很像我在这个论坛上找到的另一个答案: 如何以编程方式或动态创建JSF 2中的复合组件

While working on this question, I finally wrote code that works for composite instanciation using MyFaces (examples in link seems to be Mojarra specific). 在处理这个问题时,我最终编写了一些代码,用于使用MyFaces进行复合实例化(链接中的示例似乎是Mojarra特有的)。 I copy it there as it took me some time to write it and hope it will help someone else : 我把它复制到那里因为我花了一些时间来写它并希望它能帮助别人:

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;
}

Please do not pay attention to ugly exception handling : it is just as automatically generated by netbeans... I will ask MyFaces developpers if there is a way to avoid ugly reflection hacks. 请不要注意丑陋的异常处理:它就像netbeans自动生成的......如果有办法避免丑陋的反射黑客,我会问MyFaces开发人员。

How can I do the same with tag components , I mean components declared like : 我如何对标签组件做同样的事情,我的意思是组件声明如下:

<tag>
    <description>blah blah</description>
    <tag-name>myWonderfulTag</tag-name>
    <source>tags/mwl/myWonderfulTag.xhtml</source>
<!-- attributes -->
</tag>

in taglib. 在taglib中。

Thanks in advance. 提前致谢。

ok, I found how to do it with MyFaces. 好的,我发现如何用MyFaces做到这一点。 It also requires a bit of ugly reflection... 它还需要一些丑陋的反思......

public static UIComponent instantiateTagComponent(Location loc, String namespace, String localPrefix, String componentName, TagComponentParam params[]) {
    final String ERROR_MESSAGE = "Erreur lors de  l'instanciation d'un tag component";
    FacesContext ctx = FacesContext.getCurrentInstance();
    AbstractFaceletContext fctx = (AbstractFaceletContext) ctx.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
    fctx.pushPageContext(new PageContextImpl());

    FaceletViewDeclarationLanguage vdl = new FaceletViewDeclarationLanguage(ctx);

    UIPanel panel = (UIPanel) ctx.getApplication().createComponent( UIPanel.COMPONENT_TYPE );

    try {
        Method createCompiler = FaceletViewDeclarationLanguage.class.getDeclaredMethod("createCompiler",FacesContext.class);
        Method 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);
        FaceletFactory ff = (FaceletFactory) createFaceletFactory.invoke(vdl, ctx, compiler);
        TagLibrary tl = compiler.createTagLibrary();
        TagConfig tc = new JSFUtilsTagUnit(tl, namespace, localPrefix, componentName,params,loc);
        TagHandler th = tl.createTagHandler(namespace, componentName, tc);
        Field declaredField = FaceletCompositionContext.class.getDeclaredField("FACELET_COMPOSITION_CONTEXT_KEY");
        declaredField.setAccessible(true);
        FaceletCompositionContextImpl faceletCompositionContextImpl = new FaceletCompositionContextImpl(ff,ctx);
        Class<?> dfcClass = Class.forName("org.apache.myfaces.view.facelets.impl.DefaultFaceletContext");
        Field fMCTX = dfcClass.getDeclaredField("_mctx");
        fMCTX.setAccessible(true);
        fMCTX.set(fctx, faceletCompositionContextImpl);
        FacesContext.getCurrentInstance().getAttributes().put((String)declaredField.get(null),faceletCompositionContextImpl);
        FaceletCompositionContext mctx = (FaceletCompositionContext) FaceletCompositionContext.getCurrentInstance(fctx);
        mctx.startComponentUniqueIdSection();
        th.apply( fctx, panel );
    } catch (IOException ex) {
        log.error(ERROR_MESSAGE, ex);
    } catch (InvocationTargetException ex) {
        log.error(ERROR_MESSAGE, ex);
    } catch (NoSuchMethodException ex) {
        log.error(ERROR_MESSAGE, ex);
    } catch (NoSuchFieldException ex) {
        log.error(ERROR_MESSAGE, ex);
    } catch (SecurityException ex) {
        log.error(ERROR_MESSAGE, ex);
    } catch (ClassNotFoundException ex) {
        log.error(ERROR_MESSAGE, ex);
    } catch (IllegalArgumentException ex) {
        log.error(ERROR_MESSAGE, ex);
    } catch (IllegalAccessException ex) {
        log.error(ERROR_MESSAGE, ex);
    }
    finally {
        fctx.popPageContext();
    }
    return panel;
}

The JSFUtilsTagUnit class is : JSFUtilsTagUnit类是:

static class JSFUtilsTagUnit implements TagConfig {

    private final TagLibrary library;
    private final String namespace;
    private final String name;
    private Tag tag;

    public JSFUtilsTagUnit(TagLibrary library, String namespace, String localPrefix, String name, TagComponentParam params[], Location loc) {
        this.library = library;
        this.namespace = namespace;
        this.name = name;
        if(loc == null) {
            loc = new Location("virtual", -1, -1);
        }
        TagAttribute[] tas;
        if((params != null) && (params.length > 0)) {
            tas = new TagAttribute[params.length];
            int iCurrent = 0;
            for(TagComponentParam tcpCur : params) {
                tas[iCurrent] = new TagAttributeImpl(loc,"",tcpCur.getName(), tcpCur.getName(), tcpCur.getValue());
                iCurrent++;
            }
        } else {
            tas = new TagAttribute[0];
        }
        TagAttributes tattrs = new TagAttributesImpl(tas);
        tag = new Tag(loc, namespace, name, localPrefix+":"+name, tattrs);
    }

    public FaceletHandler getNextHandler() {
        return new FaceletHandler() {

            public void apply(FaceletContext ctx, UIComponent parent) throws IOException {
            }
        };
    }

    public Tag getTag() {
        return tag;
    }

    public String getTagId() {
        return "-1";
    }

}

Hope it will help someone else ! 希望它会帮助别人!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM