I have a Java EE 7 web application (JSF 2.2) and JPA with EclipseLink 2.5.2, running on a GlassFish 4.1 (build 13) with Hibernate Validator 5.0.0.Final.
My purpose is to use bean validation for the enitity classes but don't want to use the provided annotations. I want to define the constrains for bean validation in XML. I have done this throw a file located in META-INF/validation.xml:
<?xml version="1.0" encoding="UTF-8"?>
<validation-config xmlns ="http://jboss.org/xml/ns/javax/validation/configuration"
xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://jboss.org/xml/ns/javax/validation/configuration validation-configuration-1.1.xsd">
<constraint-mapping>
META-INF/validation/EntityTest-constraints.xml
</constraint-mapping>
</validation-config>
And the Constraint-File:
<?xml version="1.0" encoding="UTF-8"?>
<constraint-mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.1.xsd"
xmlns="http://jboss.org/xml/ns/javax/validation/mapping" version="1.1">
<bean class="testprojektjee7.business.test.EntityTest">
<field name="label">
<constraint annotation="javax.validation.constraints.Size">
<message>3 bis 10 Zeichen!</message>
<element name="min">3</element>
<element name="max">10</element>
</constraint>
</field>
</bean>
</constraint-mappings>
And this is the Entity-Class:
@Entity
public class EntityTest implements Serializable {
@Id
@GeneratedValue(strategy = javax.persistence.GenerationType.IDENTITY)
private long id;
private String label;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
}
Everything is working fine if I use JSF to bind an input field to the label-field of the entity. In this case I get validation errors when the label is too short or too long. So the XML-Way is working with JSF.
But when I create an entity instance out of an Stateless EJB (@Stateless) and going to persist this instance throw the EntityManager I get no automatic bean validation errors. Otherwise it works when I am going to annotate the label-Attribut with the @Size annotation. So I don't know what I am doing wrong with the bean validation throw xml files because with JSF everything is working fine and the GlassFish server also logs that he found the validation.xml file and is going to parse it:
HV000007: META-INF/validation.xml found. Parsing XML based configuration.
Persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="TestprojektJEE7_PU" transaction-type="JTA">
<jta-data-source>jdbc/testprojektjee7</jta-data-source>
<class>testprojektjee7.business.test.EntityTest</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
</properties>
</persistence-unit>
</persistence>
Addition 1
To clarify the problem I just have done the other way and had defined an annoation at the field in the entity class. In this case I get the expected exception throw prePersist callback. Here is the stacktrace:
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.
at org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener.validateOnCallbackEvent(BeanValidationListener.java:90)
at org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener.prePersist(BeanValidationListener.java:62)
at org.eclipse.persistence.descriptors.DescriptorEventManager.notifyListener(DescriptorEventManager.java:748)
at org.eclipse.persistence.descriptors.DescriptorEventManager.notifyEJB30Listeners(DescriptorEventManager.java:691)
at org.eclipse.persistence.descriptors.DescriptorEventManager.executeEvent(DescriptorEventManager.java:229)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectClone(UnitOfWorkImpl.java:4316)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNotRegisteredNewObjectForPersist(UnitOfWorkImpl.java:4293)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.registerNotRegisteredNewObjectForPersist(RepeatableWriteUnitOfWork.java:518)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4235)
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:496)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.persist(EntityManagerWrapper.java:287)
I think the BeanValidationListener from org.eclipse.* only validates constraints which are present as annotations and is not looking at the constraints defined in xml files.
Addition 2
The method org.eclipse.persistence.internal.jpa.metadata.listeners.BeanValidationListener.validateOnCallbackEvent(...) gets an instance of org.hibernate.validator.internal.engine.ValidatorImpl.java. This validator implementation is ignoring the constraints defined by xml.
BUT if I get an validator instace from the EJB-Container throw @Resource annotation it validates correctly (also xml) and the instance is from the same ValidatorImpl too. I don't figured out the difference.