I am using
- Myfaces 2.1.12 (with Primefaces 3.5)
- Bean Validation Hibernate Validator 4.3.0.Final
- Lombok 1.12.2
- Omnifaces 1.6.2
- PrettyFaces 3.3.3
- Weld 2.1.0.CR1
to validate a bean (relevant extract below)
@Entity
@Data
public class Controle implements Serializable {
private static final String FOREIGN_KEY_ID = "CON_ID";
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Size(max = 256, message = "trop long.")
@Column(nme = "LIB", length = 256)
@NotNull
private String libelle;
@ManyToMany
@JoinTable(
name = "THEME_CONTROLE",
joinColumns = @JoinColumn(name = FOREIGN_KEY_ID),
inverseJoinColumns = @JoinColumn(name = "THECLE")
)
@NotNull(message = "vous devez définir au moins un thème")
@Size(min = 1, message = "vous devez définir au moins un thème")
private List<Theme> themes;
(...)
}
The relevant facelet extract is below
<h:form id="controle">
(...)
<p:messages />
<p:panel>
(...)
<h:panelGrid columns="2" columnClasses="label,">
<p:outputLabel for="libelle" value="Libellé" />
<p:inputText id="libelle" value="#{controle.controle.libelle}" size="60" />
(...)
<p:outputLabel for="themes" value="Thèmes" />
<p:selectManyButton id="themes" value="#{controle.controle.themes}"
collectionType="java.util.ArrayList"
converter="omnifaces.SelectItemsConverter">
<f:selectItems value="#{controle.themes}" var="t" itemLabel="#{t.libelle}" itemValue="#{t}" />
</p:selectManyButton>
(...)
</h:panelGrid>
(...)
<f:facet name="footer">
(...)
<p:commandButton id="saveSubmit" value="#{controle.saveLabel}"
action="#{controle.save}" icon="ui-icon-disk"
styleClass="ui-priority-primary" update=":controle" />
</f:facet>
</p:panel>
(...)
</h:form>
The backing-bean is below
@Named(value = "controle")
@ViewScoped
@Data
@Slf4j
@URLMappings(mappings = {
@URLMapping(id = "controle_create", pattern = ControleController.URL_MAPPING_CONTROLE_CREATE, viewId = ControleController.VIEW_ID),
@URLMapping(id = "controle", pattern = ControleController.URL_MAPPING_CONTROLE, viewId = ControleController.VIEW_ID)})
public class ControleController implements Serializable {
(...)
@URLAction
public void load() {
FacesContext.getCurrentInstance().getMessages();
if (controle == null) {
if (id != null) {
controle = controleService.findById(id);
} else {
controle = new Controle();
controle.setAnneeCreation(LocalDate.now().getYear());
}
themes = themeService.getAllThemes();
}
(...)
public String save() {
String destination;
if (controle.getId() == null) {
destination = "pretty:controle_create";
} else {
destination = "pretty:programme";
}
controleService.save(controle);
return destination;
}
(...)
}
In case you are wondering about the collectionType, you can look at “could not initialize proxy - no session” with an open session available
My problem lies with how (or maybe when) validation constraints are validated. More specifically, the @NotNull
constraint on the String libelle
attribute is working as expected (message is displayed along potential others, saving doesn't occur, ...)
However, it is not the same with the @Size
constraint on the List<Theme>
themes attribute. With no theme selected (size is 0) and all else validates, nothing seems to happen when I click on save. If I inspect the HTTP response (ajax), I find the validation exception
<?xml version="1.0" encoding="utf-8"?>
<partial-response>
<error>
<error-name>org.apache.myfaces.view.facelets.el.ContextAwareELException</error-name>
<error-message><![CDATA[
javax.el.ELException: javax.validation.ConstraintViolationException: Validation failed for classes [fr.senat.model.dosleg.Controle] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{
interpolatedMessage='vous devez définir au moins un thème',
propertyPath=themes,
rootBeanClass=class fr.senat.model.dosleg.Controle,
messageTemplate='vous devez définir au moins un thème'
}
]]]></error-message>
</error>
</partial-response>
Furthermore, if both constraints are not validated, only the first one (libelle is null) is displayed.
This all leads me to think that the @Size
constraint on the Collection is only verified during persist phase and not the validation phase. But I don't understand why that would happen.
Thank you in advance for any lead or help with that problem.