Comment créer par programme ou dynamiquement un composant composite dans JSF 2
J'ai besoin de créer par programmation composite composants JSF 2. Après quelques jours de recherches et d'expériences je figure sur cette méthode (très inspiré par Lexi à java.net):
/**
* Method will attach composite component to provided component
* @param viewPanel parent component of newly created composite component
*/
public void setComponentJ(UIComponent viewPanel) {
FacesContext context = FacesContext.getCurrentInstance();
viewPanel.getChildren().clear();
//load composite component from file
Resource componentResource = context.getApplication().getResourceHandler().createResource("whatever.xhtml", "components/form");
UIComponent composite = context.getApplication().createComponent(context, componentResource);
//push component to el
composite.pushComponentToEL(context, composite);
boolean compcompPushed = false;
CompositeComponentStackManager ccStackManager = CompositeComponentStackManager.getManager(context);
compcompPushed = ccStackManager.push(composite, CompositeComponentStackManager.StackType.TreeCreation);
//Populate the component with value expressions
Application application = context.getApplication();
composite.setValueExpression("value", application.getExpressionFactory().createValueExpression(
context.getELContext(), "#{stringValue.value}",
String.class));
//Populate the component with facets and child components (Optional)
UIOutput foo = (UIOutput) application.createComponent(HtmlOutputText.COMPONENT_TYPE);
foo.setValue("Foo");
composite.getFacets().put("foo", foo);
UIOutput bar = (UIOutput) application.createComponent(HtmlOutputText.COMPONENT_TYPE);
bar.setValue("Bar");
composite.getChildren().add(bar);
//create composite components Root
UIComponent compositeRoot = context.getApplication().createComponent(UIPanel.COMPONENT_TYPE);
composite.getAttributes().put(Resource.COMPONENT_RESOURCE_KEY, componentResource);
compositeRoot.setRendererType("javax.faces.Group");
composite.setId("compositeID");
try {
FaceletFactory factory = (FaceletFactory) RequestStateManager.get(context, RequestStateManager.FACELET_FACTORY);
Facelet f = factory.getFacelet(componentResource.getURL());
f.apply(context, compositeRoot); //<==[here]
} catch (Exception e) {
log.debug("Error creating composite component!!", e);
}
composite.getFacets().put(
UIComponent.COMPOSITE_FACET_NAME, compositeRoot);
//attach composite component to parent componet
viewPanel.getChildren().add(composite);
//pop component from el
composite.popComponentFromEL(context);
if (compcompPushed) {
ccStackManager.pop(CompositeComponentStackManager.StackType.TreeCreation);
}
}
Problème est que ce code fonctionne pour moi que quand javax.des visages.PROJECT_STAGE est mis à la PRODUCTION (Il m'a fallu toute la journée pour comprendre cela). Si javax.des visages.PROJECT_STAGE est réglé pour le DÉVELOPPEMENT Exception est levée sur le point marqué (<==[ici]):
javax.faces.view.facelets.TagException: /resources/components/form/pokus.xhtml @8,19 <cc:interface> Component Not Found for identifier: j_id2.getParent().
at com.sun.faces.facelets.tag.composite.InterfaceHandler.validateComponent(InterfaceHandler.java:135)
at com.sun.faces.facelets.tag.composite.InterfaceHandler.apply(InterfaceHandler.java:125)
at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:98)
at com.sun.faces.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:93)
at com.sun.faces.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:82)
at com.sun.faces.facelets.impl.DefaultFacelet.apply(DefaultFacelet.java:152)
at cz.boza.formcreator.formcore.Try.setComponentJ(Try.java:83)
at cz.boza.formcreator.formcore.FormCreator.<init>(FormCreator.java:40)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:532)
C'est un problème avec le parent mis en compositeRoot composant (j_id2 est automatiquement généré ID de compositeRoot). Aussi ce code n'est pas testé thorougly assez, donc je ne suis pas sûr si je peux compter sur elle.
Je pense qu'il est très important d'être capable de manipuler des Composants Composites programmaticaly. Sinon Composite Composants sont à moitié inutile.
Merci beaucoup.
source d'informationauteur Ondrej Bozek
Vous devez vous connecter pour publier un commentaire.
Je ne peux pas expliquer le problème concret dans le détail, mais je ne peut que constater et confirmer que l'approche de la question est maladroite et serré couplé à Mojarra. Il y a
com.sun.faces.*
dépendances spécifiques nécessitant Mojarra. Cette approche n'est pas en utilisant la norme méthodes de l'API et, en outre, ne serait pas travailler dans d'autres JSF implémentations comme MyFaces.Voici une approche beaucoup plus simple en utilisant la norme API-méthodes fournies. Le point clé est que vous devez utiliser
FaceletContext#includeFacelet()
pour inclure le composant composite de ressources dans le parent.Imaginez que vous souhaitez inclure
<my:testComposite id="someId">
de URIxmlns:my="http://java.sun.com/jsf/composite/mycomponents"
puis l'utiliser comme suit:Cela a également été ajouté à la JSF bibliothèque utilitaire OmniFaces comme
Components#includeCompositeComponent()
(depuis V1.5).Mise à jour depuis JSF 2.2, le
ViewDeclarationLanguage
la classe a obtenu un nouveaucreateComponent()
méthode de la prise de la taglib URI et le nom de la balise qui pourrait également être utilisé à cette fin. Donc, si vous êtes en utilisant JSF 2.2, l'approche doit être effectuée comme suit:Imaginez que vous souhaitez inclure
<my:testComposite id="someId">
de URIxmlns:my="http://xmlns.jcp.org/jsf/composite/mycomponents"
puis l'utiliser comme suit:Que les deux solutions n'ont pas fonctionné pour moi, je creuse dans le cadre du programme de mise en œuvre pour trouver, comment les statiquement inséré composites sont ajoutés et traitées dans le volet d'arborescence. C'est le code de travail, j'ai enfin terminé avec: