2011-03-20 18 views
10

में प्रोग्रामेटिक रूप से या गतिशील रूप से एक समग्र घटक बनाने के लिए मुझे जेएसएफ 2 में प्रोग्रामेटिक रूप से समग्र घटक बनाने की आवश्यकता है। खोज और प्रयोगों के कुछ दिनों के बाद मैं इस विधि को समझता हूं (java.net पर लेक्सी द्वारा अत्यधिक प्रेरित):जेएसएफ 2

/** 
* 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); 
    } 
} 

समस्या यह है कि यह कोड केवल मेरे लिए काम करता है जब javax.faces.PROJECT_STAGE उत्पादन पर सेट होता है (यह मुझे इसे समझने के लिए पूरे दिन ले जाता है)। javax.faces.PROJECT_STAGE विकास अपवाद पर सेट है चिह्नित बिंदु पर फेंक दिया जाता है (< == [यहां]):

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) 

यह (j_id2 automaticaly उत्पन्न होता है compositeRoot की आईडी) compositeRoot घटक में सेट माता पिता के साथ कुछ समस्या है । इसके अलावा इस कोड का परीक्षण पर्याप्त रूप से पर्याप्त नहीं है, इसलिए मुझे यकीन नहीं है कि मैं इस पर भरोसा कर सकता हूं।

मुझे लगता है कि समग्र घटक प्रोग्रामेटिकल में हेरफेर करने में सक्षम होना बहुत महत्वपूर्ण है। अन्यथा समग्र घटक आधा बेकार हैं।

बहुत बहुत धन्यवाद।

+0

कुछ करने के बाद इसलिए, यदि आप JSF 2.2 का उपयोग कर रहे, दृष्टिकोण इस प्रकार से किया जाना चाहिए परीक्षण मैंने यह भी पाया कि मैं अन्य समग्र घटक में किसी भी घटक (बच्चे के रूप में जोड़ें) को प्रोग्रामेटिक रूप से घोंसला नहीं कर सकता :( –

+1

ठीक है तो मैंने फाइनल को हल किया। यहां आप प्रोग्रामेटिक रूप से समग्र घटक बनाने के लिए डेमो हो डाउनलोड कर सकते हैं। http://confluence.highsource।संगठन/प्रदर्शन/हिफ़ेस 20/गतिशील + चेहरे + - + नमूना + प्रदर्शन + गतिशील + या + प्रोग्रामैटिक + यूआई + निर्माण + + जेएसएफ + 2.0 + और + फेसलेट –

+0

के साथ मैंने अब लिंक की कोशिश की और यह काम करता है। यह जटिल जटिल है क्योंकि यह समग्र घटकों के प्रोग्रामिक निर्माण और जेएसएफ पृष्ठों के गतिशील निर्माण के बारे में पूरी परियोजना है। –

उत्तर

7

चूंकि दोनों समाधान मेरे लिए काम नहीं करते थे, इसलिए मैं जेएसएफ कार्यान्वयन में खोदता हूं, यह पता लगाने के लिए कि स्थिर रूप से सम्मिलित कंपोजिट्स को घटक पेड़ में कैसे जोड़ा और संभाला जाता है। यह काम कर कोड मैं अंत में साथ समाप्त हो गया है:

public UIComponent addWidget(UIComponent parent, String widget) { 
    UIComponent cc = null; 
    UIComponent facetComponent = null; 
    FacesContext ctx = FacesContext.getCurrentInstance(); 
    Resource resource = ctx.getApplication().getResourceHandler().createResource(widget + ".xhtml", "widgets"); 
    FaceletFactory faceletFactory = (FaceletFactory) RequestStateManager.get(ctx, RequestStateManager.FACELET_FACTORY); 

    // create the facelet component 
    cc = ctx.getApplication().createComponent(ctx, resource); 

    // create the component to be populated by the facelet 
    facetComponent = ctx.getApplication().createComponent(UIPanel.COMPONENT_TYPE); 
    facetComponent.setRendererType("javax.faces.Group"); 

    // set the facelet's parent 
    cc.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, facetComponent); 

    // populate the facetComponent 
    try { 
     Facelet facelet = faceletFactory.getFacelet(resource.getURL()); 
     facelet.apply(ctx, facetComponent); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

    // finally add the facetComponent to the given parent 
    parent.getChildren().add(cc); 

    return cc; 
} 
+0

यह विफल रहता है जब ' 'पर निर्भर है। – BalusC

14

मैं विस्तार से ठोस समस्या व्याख्या नहीं कर सकते, लेकिन मैं केवल का निरीक्षण करने और पुष्टि करते हैं कि दृष्टिकोण के रूप में सवाल में दिखाया गया अनाड़ी और तंग के लिए युग्मित है सकते हैं Mojarra। com.sun.faces.* विशिष्ट निर्भरताओं को मोजररा की आवश्यकता है। यह दृष्टिकोण मानक API विधियों का उपयोग नहीं कर रहा है और इसके अतिरिक्त, MyFaces जैसे अन्य जेएसएफ कार्यान्वयन में काम नहीं करेगा।

यहां मानक API-प्रदत्त विधियों का उपयोग करने का एक बहुत ही सरल दृष्टिकोण है। मुख्य बिंदु यह है कि आपको दिए गए माता-पिता में समग्र घटक संसाधन शामिल करने के लिए FaceletContext#includeFacelet() का उपयोग करना चाहिए।

public static void includeCompositeComponent(UIComponent parent, String libraryName, String resourceName, String id) { 
    // Prepare. 
    FacesContext context = FacesContext.getCurrentInstance(); 
    Application application = context.getApplication(); 
    FaceletContext faceletContext = (FaceletContext) context.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY); 

    // This basically creates <ui:component> based on <composite:interface>. 
    Resource resource = application.getResourceHandler().createResource(resourceName, libraryName); 
    UIComponent composite = application.createComponent(context, resource); 
    composite.setId(id); // Mandatory for the case composite is part of UIForm! Otherwise JSF can't find inputs. 

    // This basically creates <composite:implementation>. 
    UIComponent implementation = application.createComponent(UIPanel.COMPONENT_TYPE); 
    implementation.setRendererType("javax.faces.Group"); 
    composite.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, implementation); 

    // Now include the composite component file in the given parent. 
    parent.getChildren().add(composite); 
    parent.pushComponentToEL(context, composite); // This makes #{cc} available. 
    try { 
     faceletContext.includeFacelet(implementation, resource.getURL()); 
    } catch (IOException e) { 
     throw new FacesException(e); 
    } finally { 
     parent.popComponentFromEL(context); 
    } 
} 

कल्पना कीजिए कि आप यूआरआई xmlns:my="http://java.sun.com/jsf/composite/mycomponents" से <my:testComposite id="someId"> शामिल करना चाहते हैं, तो इसका इस्तेमाल इस प्रकार है:

includeCompositeComponent(parent, "mycomponents", "testComposite.xhtml", "someId"); 

यह भी Components#includeCompositeComponent() (V1.5 के बाद से) के रूप में JSF उपयोगिता पुस्तकालय OmniFaces में जोड़ा गया है।


अद्यतन JSF 2.2 के बाद से, ViewDeclarationLanguage वर्ग एक नया createComponent() विधि taglib यूआरआई और टैग नाम जो भी इस उद्देश्य के लिए इस्तेमाल किया जा सकता लेने मिला है।

public static void includeCompositeComponent(UIComponent parent, String taglibURI, String tagName, String id) { 
    FacesContext context = FacesContext.getCurrentInstance(); 
    UIComponent composite = context.getApplication().getViewHandler() 
     .getViewDeclarationLanguage(context, context.getViewRoot().getViewId()) 
     .createComponent(context, taglibURI, tagName, null); 
    composite.setId(id); 
    parent.getChildren().add(composite); 
} 

कल्पना कीजिए कि आप यूआरआई xmlns:my="http://xmlns.jcp.org/jsf/composite/mycomponents" से <my:testComposite id="someId"> शामिल करना चाहते हैं, तो इसका इस्तेमाल इस प्रकार है::

includeCompositeComponent(parent, "http://xmlns.jcp.org/jsf/composite/mycomponents", "testComposite", "someId"); 
+0

हैलो। मुझे इस मुद्दे का भी सामना करना पड़ रहा है; क्या फेसलेट गतिशील निर्माण उदाहरण ठीक है जेएसएफ 2.0 के लिए ठीक है? क्योंकि मैं इस पंक्ति में * * .getAttributes() में एनपीई का सामना कर रहा हूं। (FaceletContext.FACELET_CONTEXT_KEY) प्राप्त करें; ' – user390525