Динамическая форма JSF 2 и проверка бинов JSR 303 - PullRequest
2 голосов
/ 08 июля 2011

Я генерирую динамическую форму, начиная с аннотированного компонента. Этот же bean-компонент аннотирован для проверки с использованием Hibernate Validator. Форма правильно отображается, но когда форма отправлена, шаг проверки не выполняется. Если я напишу ту же форму с тегом jsf, валидация будет работать правильно.

Есть идеи?

Страница формы:

<body>

    <ui:composition template="/template/basetheme_one_col.xhtml">
        <ui:define name="title">#{__g4cController.entityClassName}</ui:define>

        <ui:define name="main_area">

            <h2>#{__g4cController.entityClassName}</h2>
            <br />
            <div id="briciole_pane">
                <h:form id="briciole_pane_form"  styleClass="form">
                    <h:commandLink action="home" value="Home" />
                    <h:outputText value=" / " />
                    Modifica #{__g4cController.entityClassName}
                </h:form>
            </div>
            <br />


            <h:form id="edit_record"  styleClass="myForm">
                <rich:calendar rendered="false" />
                <h4>Modifica #{__g4cController.entityClassName}</h4>

                <h:messages errorClass="error_msg" layout="list" globalOnly="false" />
                <br />

               <h:panelGrid binding="#{__g4cController.dynamicForm}" />


               <div class="box_bottoni">
                    <div class="box_bottone_azzurro">
                        <h:commandLink action="#{__g4cController.edit}" value="Salva Modifiche">
                            <f:param name="cruddao.objectKey" value="#{g4c:getXmlFromObject(__g4cController.entity.id)}" />
                        </h:commandLink>
                    </div>
                    <h:commandLink action="#{__g4cController.listSetup}" styleClass="link_annulla_rosso"
                                   value="Annulla e torna a lista #{__g4cController.entityClassName}" immediate="true" />
                    <div class="clear"></div>
                </div>


           </h:form>

        </ui:define>
    </ui:composition>
</body>

Код, который генерирует форму, начиная с EntityBean

    public UIComponent getDynamicForm() {
    FacesContext ctx = FacesContext.getCurrentInstance();
    Application app = ctx.getApplication();
    HtmlPanelGrid panel = (HtmlPanelGrid) app.createComponent(HtmlPanelGrid.COMPONENT_TYPE);
    panel.setColumns(2);

    Class currentClass = super.entityClass;
    while(!currentClass.equals(Object.class)) {
        Field fields[] = currentClass.getDeclaredFields();
        for(Field field: fields) {
            Annotation id = field.getAnnotation(Id.class);
            Annotation embeddedId = field.getAnnotation(EmbeddedId.class);
            OneToMany oneToMany = field.getAnnotation(OneToMany.class);
            ManyToMany manyToMany = field.getAnnotation(ManyToMany.class);
            Transient transientTag = field.getAnnotation(Transient.class);
            Temporal temporal = field.getAnnotation(Temporal.class);



            if(id == null && embeddedId == null && oneToMany == null && manyToMany == null && transientTag == null) {
                int modifiers=field.getModifiers();
                if(!Modifier.isStatic(modifiers)) {
                    HtmlOutputLabel label = (HtmlOutputLabel) app.createComponent(HtmlOutputLabel.COMPONENT_TYPE);

                    String name = field.getName();
                    Class clazz = field.getType();

                    panel.getChildren().add(label);
                    label.setFor(name);
                    label.setValue(StringUtil.capitalize(name)+":");

                    String expression = "#{__g4cController.entity."+name+"}";
                    ValueExpression valueExpression = app.getExpressionFactory()
                            .createValueExpression(ctx.getELContext(),
                                    expression,
                                    clazz);

                    ManyToOne manyToOne = field.getAnnotation(ManyToOne.class);
                    if(manyToOne != null) {
                        HtmlSelectOneMenu input = (HtmlSelectOneMenu) app.createComponent(HtmlSelectOneMenu.COMPONENT_TYPE);
                        input.setId(name);
                        input.setValueExpression("value", valueExpression);
                        input.setLabel(name);

                        UISelectItems items = (UISelectItems) app.createComponent(UISelectItems.COMPONENT_TYPE);
                        input.getChildren().add(items);
                        String manyToOneClassName = field.getType().getSimpleName().toLowerCase();
                        String itemsExpression = "#{"+manyToOneClassName+".entityListSelectOne}";
                        ValueExpression itemsValueExpression = app.getExpressionFactory()
                                .createValueExpression(ctx.getELContext(),
                                        itemsExpression,
                                    SelectItem[].class);
                        items.setValueExpression("value", itemsValueExpression);
                        panel.getChildren().add(input);
                    } else {
                        if(temporal != null) {
                            if(temporal.value().equals(TemporalType.DATE)) {
                                UICalendar input = (UICalendar) app.createComponent(UICalendar.COMPONENT_TYPE);
                                input.setId(name);
                                input.setValueExpression("value", valueExpression);
                                input.setDatePattern("dd/MM/yyyy");
                                //input.setConverter(new DateConverter());
                                panel.getChildren().add(input);
                            }
                        } else {
                            HtmlInputText input = (HtmlInputText) app.createComponent(HtmlInputText.COMPONENT_TYPE);
                            input.setId(name);
                            input.setValueExpression("value", valueExpression);
                            input.setLabel(name);
                            input.setSize(50);
                            input.setMaxlength(255);
                            panel.getChildren().add(input);
                        }

                    }
                }
            }
        }
        currentClass = currentClass.getSuperclass();
    }
    return panel;
}

Пример Entity Bean:

@Entity

открытый класс Istituto реализует Serializable, IBaseEntity { приватный статический финал long serialVersionUID = 1L;

@Id
@SequenceGenerator(name="IstitutoGenerator", sequenceName="ISTITUTO_SEQ", allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="IstitutoGenerator")
@Column(name="ID_ISTITUTO")
private int idIstituto;

@NotNull
private String nome;

@NotNull
private String indirizzo;

@NotNull
private String comune;

@NotNull
@Pattern(regexp="[0-9][0-9][0-9][0-9][0-9]", message="Il CAP deve essere composto da 5 numeri")
private String cap;

@OneToMany(mappedBy="istituto")
private Set<Classe> classes;

public Istituto() {
}

public int getIdIstituto() {
    return this.idIstituto;
}

public void setIdIstituto(int idIstituto) {
    this.idIstituto = idIstituto;
}

public String getCap() {
    return this.cap;
}

public void setCap(String cap) {
    this.cap = cap;
}

public String getComune() {
    return this.comune;
}

public void setComune(String comune) {
    this.comune = comune;
}

public String getIndirizzo() {
    return this.indirizzo;
}

public void setIndirizzo(String indirizzo) {
    this.indirizzo = indirizzo;
}

public String getNome() {
    return this.nome;
}

public void setNome(String nome) {
    this.nome = nome;
}

public Set<Classe> getClasses() {
    return this.classes;
}

public void setClasses(Set<Classe> classes) {
    this.classes = classes;
}

@Override
public Integer getId() {
    return this.getIdIstituto();
}

@Override
public int hashCode() {
    int hash = 0;
    hash += this.getIdIstituto();
    return hash;
}

@Override
public boolean equals(Object object) {
    if (!(object instanceof Istituto)) {
        return false;
    }
    Istituto other = (Istituto) object;
    if  (this.getIdIstituto() != other.getIdIstituto()) {
        return false;
    }

    return true;
}

@Override
public String toString() {
    return this.getNome();
}

} * * тысяча двадцать-один

1 Ответ

4 голосов
/ 14 августа 2011

Вы должны добавить экземпляр javax.faces.validator.BeanValidator к своим компонентам ввода:

input.addValidator(new BeanValidator());

Причина в том, что валидаторы по умолчанию (BeanValidator зарегистрирован как единица) добавляются во время выполнения тега: http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-635.

...