webtier@glassfish.java.net

Re: Programmatic or dynamic construction of composite components

From: <webtier_at_javadesktop.org>
Date: Sun, 28 Feb 2010 13:21:13 PST

After that I've read the following topics:

http://forums.java.net/jive/thread.jspa?threadID=63877
http://forums.java.net/jive/thread.jspa?messageID=384548

The solution sketched out there basically repeats the functionality of the CompositeComponentTagHandler. The user janderssn wrote that he's got the basic solution, but things like composite:insertChildren and composite:renderFacet don't work. The reason why these things did not work was that the composite component must have been pushed and poped from/to EL. I have reworked the code a bit an now here's the working version (with facets and children):

[pre]
public void setComponent3(UIComponent component) {

                Application application = facesContext.getApplication();
                Resource resource = application.getResourceHandler().createResource(
                                "test.xhtml", "components/dynamicfaces");

                // Create the composite component
                // See CompositeComponentTagHandler#createComponent
                UIComponent compositeComponent = facesContext.getApplication()
                                .createComponent(facesContext, resource);

                compositeComponent.pushComponentToEL(facesContext, compositeComponent);
                boolean compcompPushed = false;
                CompositeComponentStackManager ccStackManager = CompositeComponentStackManager
                                .getManager(facesContext);
                compcompPushed = ccStackManager.push(compositeComponent, TreeCreation);


                // Important: set the id - otherwise newly created components get
                // different ids
                // and "old" request values are not decoded.
                compositeComponent.setId("composite");

                // Populate the component with value expressions
                compositeComponent.setValueExpression("value", application
                                .getExpressionFactory().createValueExpression(
                                                facesContext.getELContext(), "#{stringValue.value}",
                                                String.class));

                // super.applyNextHandler

                // Populate the component with facets and child components
                UIOutput foo = (UIOutput) application
                                .createComponent(HtmlOutputText.COMPONENT_TYPE);

                foo.setValue("Foo");
                compositeComponent.getFacets().put("foo", foo);

                UIOutput bar = (UIOutput) application
                                .createComponent(HtmlOutputText.COMPONENT_TYPE);
                bar.setValue("Bar");
                compositeComponent.getChildren().add(bar);

                // applyCompositeComponent

                FaceletFactory factory = (FaceletFactory) RequestStateManager.get(
                                facesContext, RequestStateManager.FACELET_FACTORY);

                final UIComponent compositeRoot = application
                                .createComponent(UIPanel.COMPONENT_TYPE);
                compositeRoot.setRendererType("javax.faces.Group");

                // See CompositeComponentTagHandler#applyCompositeComponent(...)

                try {
                        Facelet f = factory.getFacelet(resource.getURL());
                        f.apply(facesContext, compositeRoot);
                        compositeComponent.getFacets().put(
                                        UIComponent.COMPOSITE_FACET_NAME, compositeRoot);
                } catch (IOException ioex) {
                        throw new FaceletException(ioex);
                }

                // Add the created composite component to the tree
                component.getChildren().add(compositeComponent);
                compositeComponent.popComponentFromEL(facesContext);
                if (compcompPushed) {
                        ccStackManager.pop(TreeCreation);
                }
                // Black magic ends here

                // Not important: finally assign the component to the inner field
                this.component = component;
        }
[/pre]

As I said above, this code [b]does[/b] work as expected. Figuring it out was like alchemy - trying different things in different orders and so on.

My problem with this code is that it is very very complicated. This is not what client code should be. It's just black magic, nothing else.
[Message sent by forum member 'lexi' (valikov_at_gmx.net)]

http://forums.java.net/jive/thread.jspa?messageID=389244