I try to use JSF in combination with Bean Validation. Basically, everything works well, the validation works as expected, I get the correct message, but there is an exception on my Glassfish console:
Warnung: EJB5184:A system exception occurred during an invocation on EJB MyEntityFacade, method: public void com.mycompany.testbv.AbstractFacade.create(java.lang.Object)
Warnung: javax.ejb.EJBException
at com.sun.ejb.containers.EJBContainerTransactionManager.processSystemException(EJBContainerTransactionManager.java:748)
....
....
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
at java.lang.Thread.run(Thread.java:744)
Caused by: javax.validation.ConstraintViolationException: Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'prePersist'. Please refer to embedded ConstraintViolations for details.
This exception occurs if I use custom constraints as well as predefined constraints.
Here is my sample code.
Sample Entity:
@Entity
@ValidEntity
public class MyEntity implements Serializable {
private static final long serialVersionUID = 3104398374500914142L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Size(min = 2)
private String name;
public MyEntity(String name) {
this.name = name;
}
public MyEntity() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Custom constraint:
@Constraint(validatedBy = MyValidator.class)
@Target({FIELD, METHOD, TYPE})
@Retention(RUNTIME)
public @interface ValidEntity {
String message() default "fail";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Custom validator:
public class MyValidator implements ConstraintValidator<ValidEntity, MyEntity>{
@Override
public void initialize(ValidEntity a) {
}
@Override
public boolean isValid(MyEntity t, ConstraintValidatorContext cvc) {
return false;
}
}
Sample Controller:
@Named
@SessionScoped
public class MyController implements Serializable {
private static final long serialVersionUID = -6739023629679382999L;
@Inject
MyEntityFacade myEntityFacade;
String text;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public void saveNewEntity() {
try {
myEntityFacade.create(new MyEntity(text));
} catch (Exception e) {
Throwable t = e;
while (t != null) {
if (t instanceof ConstraintViolationException) {
FacesContext context = FacesContext.getCurrentInstance();
Set<ConstraintViolation<?>> constraintViolations = ((ConstraintViolationException) t).getConstraintViolations();
for (ConstraintViolation<?> constraintViolation : constraintViolations) {
FacesMessage facesMessage = new FacesMessage(constraintViolation.getMessage());
facesMessage.setSeverity(FacesMessage.SEVERITY_ERROR);
context.addMessage(null, facesMessage);
}
}
t = t.getCause();
}
}
}
}
Sample jsf page:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head></h:head>
<h:body>
<h:form>
<h:messages id="messages" />
<h:inputText value="#{myController.text}" />
<h:commandButton value="Save" action="#{myController.saveNewEntity()}" />
</h:form>
</h:body>
</html>
The MyEntityFacade only calls persist from entity manager.
As mentioned before, the application is running fine and the correct messages are shwon, but I want to avoid this exception in the Glassfish console.
Setting the validation mode in persistence.xml to NONE as discussed here is no option, because I want a validation.
I use JSF in version 2.2, the implementation is Mojarra. The version of Bean Validation is 1.1, the implementation is Hibernate Validator. Application Server is Glassfish 4.0.