【问题标题】:How to programmatically instantiate a composite component or a tag component?如何以编程方式实例化复合组件或标签组件?
【发布时间】:2013-03-26 16:01:16
【问题描述】:

我想以编程方式实例化复合或标记组件。

此实例化将由自定义组件执行,通常将那些复合或标记组件添加为子组件。

我在爬取论坛时找到的最佳答案是:http://www.java.net/node/701640#comment-791881。它看起来很像我在这个论坛上找到的另一个答案:How to programmatically or dynamically create a composite component in JSF 2

在处理这个问题时,我终于编写了适用于 composite 使用 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>

在标签库中。

提前致谢。

【问题讨论】:

    标签: jsf jsf-2 components


    【解决方案1】:

    好的,我找到了使用 MyFaces 的方法。它还需要一些丑陋的反射......

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

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

    希望对其他人有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-13
      • 2014-08-16
      • 1970-01-01
      • 2015-03-11
      • 2021-12-12
      相关资源
      最近更新 更多