问题
I generate a dynamic form starting from annotated bean. The same bean is annotated for validation using Hibernate Validator. The form is correctly rendered but when the form is submitted the validation step it's not executed. If I write the same form with jsf tag the validation works properly.
Any idea?
The form page:
<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>
Code that generate the form starting from 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;
}
A Entity Bean example:
@Entity
public class Istituto implements Serializable, IBaseEntity { private static final 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:
You have to add an instance of javax.faces.validator.BeanValidator
to your input components:
input.addValidator(new BeanValidator());
The reason is that default validators (BeanValidator is registered as one) are added during tag execution: http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-635.
来源:https://stackoverflow.com/questions/6621045/jsf-2-dynamic-form-and-bean-validation-jsr-303