注釈付きBeanから動的フォームを生成します。同じBeanには、Hibernate Validatorを使用して検証のための注釈が付けられます。 フォームは正しくレンダリングされますが、フォームが送信されると検証ステップは実行されません。同じフォームをjsfタグで記述すると、検証が正しく機能します。JSF 2動的フォームとBeanの検証JSR 303
フォームページ:
: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エンティティBeanの例から始まるフォームを生成
<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>
コード
@Entity
パブリッククラスIstitutoは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();
}
}