Получить список с cc.attrs и ValueExpression в CompositeComponent JSF

Я должен создать составной компонент и вставить его в родительский компонент. Я попытался найти ответ на свою проблему в stackOverflow и нашел это:

Добавить программно составной компонент в компонент поддержки

Итак, я создаю составной компонент:

    <html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:p="http://xmlns.jcp.org/jsf/passthrough"
    xmlns:composite="http://java.sun.com/jsf/composite"
    xmlns:ic="http://java.sun.com/jsf/composite/inputComponent">

<composite:interface>
    <composite:attribute name="idPanel" required="true" />
    <composite:attribute name="typeBSPanel" default="default" />
    <composite:attribute name="idPanelHeading" required="true" />
    <composite:attribute name="idPanelBody" required="true" />
    <composite:attribute name="listInputText" required="true"
        shortDescription="Questo componente è un Panel con un numero variabile di InputText di tipo Text, Number e DropDown. Questa lista deve contenere degli oggetti con le seguenti proprietà: label, value e placeholder."></composite:attribute>
    <composite:attribute name="objectBindToPanel" required="true" />
</composite:interface>

<composite:implementation>
    <div class="panel-group" id="accordion">
        <div id="#{cc.attrs.idPanel}"
            class="panel panel-#{cc.attrs.typeBSPanel}">
            <div id="#{cc.attrs.idPanelHeading}" class="panel-heading">
                <button type="button" class="btn btn-#{cc.attrs.typeBSPanel}"
                    data-toggle="collapse" data-target="#collapseBodyPanel">
                    +/-</button>
            </div>
            <div id="collapseBodyPanel" class="panel-collapse collapse in">
                <div id="#{cc.attrs.idPanelBody}" class="panel-body">
                    <ui:repeat var="inputText" value="#{cc.attrs.listInputText}">
                        <ic:inputTextBS preAddon="#{inputText.label}"
                            requiredMessage="This field must not be empty"
                            placeholder="#{inputText.placeholder}"
                            value="#{cc.attrs.objectBindToPanel[inputText.value]}" required="true">
                        </ic:inputTextBS>
                    </ui:repeat>
                </div>
            </div>
        </div>
    </div>
</composite:implementation>

</html>

класс и метод динамического добавления составного компонента:

    public class CCUtility {

    public static void includeCompositeComponent(UIComponent parent, String libraryName, String resourceName, String id, Map<String, String> mapValueExpression) {
        // Prepare.
        FacesContext context = FacesContext.getCurrentInstance();
        Application application = context.getApplication();
        FaceletContext faceletContext = (FaceletContext) context.getAttributes().get("javax.faces.FACELET_CONTEXT");

        // 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.

        ExpressionFactory factory = application.getExpressionFactory(); 
        ELContext ctx = context.getELContext(); 
        for (Map.Entry<String, String> entry : mapValueExpression.entrySet()) { 
            ValueExpression expr = factory.createValueExpression(ctx, entry.getValue(), String.class); 
            composite.setValueExpression(entry.getKey(), expr); 
            //composite.getAttributes().put(entry.getKey(), entry.getValue());
            }

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


}

и я вызываю предыдущий метод в другом классе, который передает карту атрибутов, которые я хочу для составного компонента:

public void addPanelHostMachine(){
    this.dataCenterController.getDataCenter().getGroupsHost().add(indexGroupHostMachine, new GroupHost());
    Map<String, String> mapValueExpression = new HashMap<String, String>();
    mapValueExpression.put("idPanel", "panelHostMachine" + indexGroupHostMachine);
    mapValueExpression.put("idPanelHeading", "panelHostMachineHeading" + indexGroupHostMachine);
    mapValueExpression.put("idPanelBody", "panelHostMachineBody" + indexGroupHostMachine);
    mapValueExpression.put("typeBSPanel", "success");
    mapValueExpression.put("listInputText", "#{dataCenterController.dataCenter.groupsHost.get(" + indexGroupHostMachine + ").listOfInputText}");
    mapValueExpression.put("objectbindToPanel", "#{dataCenterController.dataCenter.groupsHost.get(" + indexGroupHostMachine + ")}");
    CCUtility.includeCompositeComponent(panelBodyDataCenter, "panelComponent", "panelComponent.xhtml", "ccPanelHostMachine" + indexGroupHostMachine, mapValueExpression);
    indexGroupHostMachine = indexGroupHostMachine + 1;
}

Теперь проблема в том, что когда я пытаюсь добавить CompositeComponent, я получаю эту ошибку:

Grave: Servlet.service() for servlet [Faces Servlet] in context with path [/IcaroKBMassiveEditor] threw exception [/resources/panelComponent/panelComponent.xhtml @34,79 preAddon="#{inputText.label}": Property 'label' not found on type java.lang.String] with root cause
javax.el.PropertyNotFoundException: Property 'label' not found on type java.lang.String

Я думаю, что это проблема с выражением EL и 'composite:attribute', но я не знаю, как это исправить. Может кто-нибудь помочь мне?


person Claudio Badii    schedule 06.03.2014    source источник
comment
Вы решили это? Какой у вас #{cc.attrs.listInputText} тип?   -  person Xtreme Biker    schedule 08.03.2014
comment
Да, я сделал. Я использовал решение, которое объясняется в ссылке, размещенной в моем сообщении.   -  person Claudio Badii    schedule 10.03.2014
comment
Поскольку вы здесь впервые, просто обратите внимание, что вы тоже можете ответить на свой вопрос. На самом деле, это путь. Если вы опубликуете вопрос и позже найдете решение, опубликуйте ответ самостоятельно (в части ответа, под вопросом). В противном случае вопрос останется нерешенным и предпочтительнее его удалить, чем оставить без решения.   -  person Xtreme Biker    schedule 10.03.2014
comment
Извините, теперь все в порядке? Я отредактировал свой вопрос с ответом, я не знал, что должен ответить на свой вопрос новым сообщением.   -  person Claudio Badii    schedule 10.03.2014
comment
Это хорошо, приятель ;-) Теперь вам нужно только пометить его как принятый ответ (нажмите на галочку ✓), когда переполнение стека позволит вам.   -  person Xtreme Biker    schedule 10.03.2014
comment
Спасибо. На следующем! :-)   -  person Claudio Badii    schedule 10.03.2014


Ответы (1)


Я нашел решение в этом сообщении: DataTable внутри составного компонента.

Вместо:

for (Map.Entry<String, String> entry : mapValueExpression.entrySet()) { 
 ValueExpression expr = factory.createValueExpression(ctx, entry.getValue(),String.class); 
  composite.setValueExpression(entry.getKey(), expr); 
        }

Я использовал:

for (Map.Entry<String, String> entry : mapValueExpression.entrySet()) { 
 ValueExpression expr = factory.createValueExpression(ctx, entry.getValue(),Object.class); 
  composite.setValueExpression(entry.getKey(), expr); 
        }

Я заменил String.Class на Object.class в вызове функции factory.createValueExpression

person Claudio Badii    schedule 10.03.2014