I am trying to get JPA validation to work, however it seems that the validation annotations are ignored. I found this example of JPA validation on SO: JPA Entity Validation, but it does not work for me. The @NotNull
and @Size
annotations seem to be ignored.
As in the answer mentioned above I use only two classes:
Customer.java:
package com.validation.test;
import javax.persistence.*;
import javax.validation.constraints.*;
@Entity
@Table(name = "T_CUSTOMER")
public class Customer {
@Id
@NotNull
@SequenceGenerator(name = "customerIdSeq", sequenceName = "T_CUSTOMER_ID_SEQ", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "customerIdSeq")
private Long id;
@NotNull
@Size(min = 3, max = 80)
private String name;
public Customer() {};
public Customer(String name) {
this.name = name;
}
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;
}
}
CustomerTest.java:
package com.validation.test.test;
import static org.junit.Assert.*;
import javax.persistence.*;
import javax.validation.*;
import javax.validation.constraints.Size;
import org.junit.*;
import com.validation.test.Customer;
public class CustomerTest {
private static EntityManagerFactory emf;
private EntityManager em;
@BeforeClass
public static void createEntityManagerFactory() {
emf = Persistence.createEntityManagerFactory("testPU");
}
@AfterClass
public static void closeEntityManagerFactory() {
emf.close();
}
@Before
public void beginTransaction() {
em = emf.createEntityManager();
em.getTransaction().begin();
}
@After
public void rollbackTransaction() {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
if (em.isOpen()) {
em.close();
}
}
@Test
public void nameTooShort() {
try {
Customer customer = new Customer("bo");
em.persist(customer);
em.flush();
fail("Expected ConstraintViolationException wasn't thrown.");
} catch (ConstraintViolationException e) {
assertEquals(1, e.getConstraintViolations().size());
ConstraintViolation<?> violation = e.getConstraintViolations().iterator().next();
assertEquals("name", violation.getPropertyPath().toString());
assertEquals(Size.class, violation.getConstraintDescriptor().getAnnotation().annotationType());
}
}
}
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.validation.test</groupId>
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<repositories>
<repository>
<id>maven2-repository.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2/</url>
<layout>default</layout>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc5</artifactId>
<version>11.2.0.2.0</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.3.Final</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>wwd-bs</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="testPU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.validation.test.Customer</class>
<properties>
<property name="eclipselink.logging.level" value="FINE" />
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver" />
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:orcl" />
<property name="javax.persistence.jdbc.user" value="user" />
<property name="javax.persistence.jdbc.password" value="password" />
<property name="eclipselink.logging.level" value="INFO" />
</properties>
</persistence-unit>
</persistence>
The test fails at the fail(...)
so the exception is never thrown.
How can I make (any) validation work with JPA? I cannot use Hibernate or Spring.
Thank you for your help
EDIT: added hibernate-validator to pom.xml (with no effect)
Data validation is a common task that occurs in all layers of an application, including persistence. The Java™ Persistence API (JPA) 2.0 provides support for the Bean Validation API so that data validation can be done at run time.
The @Valid annotation ensures the validation of the whole object. Importantly, it performs the validation of the whole object graph. However, this creates issues for scenarios needing only partial validation. On the other hand, we can use @Validated for group validation, including the above partial validation.
@Email annotation is part of javax. validation. constraints package. Using Just @Email annotation like below @Data.
Add this to your pom.xmls.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
<exclusions>
<exclusion>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
And set validation property to AUTO this must to be enable in persistence.xml
<property name="javax.persistence.validation.mode" value="AUTO" />
Or do it progrmatically.
final Set<ConstraintViolation<Object>> errors = validator.validate(object, classes);
Do you have a runtime implementation of the validator on your classpath? Typically people seem to use hibernate validator. (e.g. indeed by adding hibernate-validator to your pom.xml)
edit: Your version of EclipseLink also looks quite old, it should be a JPA2 implementation. If it is a JPA1 implementation, you should register your own event listener, which will be a bit more work. You can find some hints in the eclipse docs (scroll down to JPA section), but it looks like you'll have to slightly edit the standard validators to make it work. This blog might be helpful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With