Base source for JPA Bean Validation example

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@951071 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jeremy Bauer 2010-06-03 17:07:17 +00:00
parent 632639bb62
commit 6bdb269a8b
14 changed files with 1028 additions and 0 deletions

View File

@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!--
Please keep the project tag on one line to avoid confusing
the release plugin.
-->
<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>
<parent>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa-parent</artifactId>
<version>2.1.0-SNAPSHOT</version>
</parent>
<groupId>org.apache.openjpa.openjpa-examples</groupId>
<artifactId>image-gallery</artifactId>
<packaging>jar</packaging>
<name>Apache OpenJPA :: Examples - image-gallery</name>
<url>http://openjpa.apache.org/samples.html</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<openjpa.Log>DefaultLevel=WARN</openjpa.Log>
<checkstyle.config.location>../../openjpa-project/checkstyle.xml</checkstyle.config.location>
<test.jvm.maxpermsize>256m</test.jvm.maxpermsize>
<test.jvm.maxheapsize>1024m</test.jvm.maxheapsize>
<test.jvm.arguments>-Xmx${test.jvm.maxheapsize} -XX:MaxPermSize=${test.jvm.maxpermsize}</test.jvm.arguments>
<surefire.jvm.args>${test.jvm.arguments}</surefire.jvm.args>
</properties>
<dependencies>
<!-- When using OpenJPA 2.0.0 with bval, commons-lang must be in the dependency -->
<!-- tree before openjpa-all-2.0.0 since openjpa-all bundles commons-lang 2.1 -->
<!-- and bval requires version 2.4 -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.8.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-validation_1.0_spec</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.apache.bval</groupId>
<artifactId>org.apache.bval.bundle</artifactId>
<version>0.1-incubating-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa-all</artifactId>
<version>${pom.version}</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.5.3.0_1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<!-- Disable the annotation processor for now due to a JDK 6 bug -->
<compilerArgument>-proc:none</compilerArgument>
</configuration>
</plugin>
<plugin>
<!-- The jar plugin builds a jar containing the image gallery classes -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3</version>
<configuration>
<archive>
<manifest>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<!-- The surefire plugin is used to run the jUnit tests -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.3</version>
<configuration>
<argLine>${surefire.jvm.args}</argLine>
<useFile>false</useFile>
<trimStackTrace>false</trimStackTrace>
<useSystemClassLoader>true</useSystemClassLoader>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<!-- Use the openjpa maven plugin to enhance the domain model classes -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>openjpa-maven-plugin</artifactId>
<version>1.1</version>
<configuration>
<includes>org/apache/openjpa/examples/gallery/model/*.class</includes>
<addDefaultConstructor>true</addDefaultConstructor>
<enforcePropertyRestrictions>true</enforcePropertyRestrictions>
<persistenceXmlFile>src/test/resources/META-INF/persistence.xml</persistenceXmlFile>
</configuration>
<executions>
<execution>
<id>enhancer</id>
<phase>process-classes</phase>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.apache.openjpa</groupId>
<artifactId>openjpa-all</artifactId>
<version>${pom.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,24 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.example.gallery;
public enum ImageType {
JPEG,
GIF
}

View File

@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.example.gallery.constraint;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import javax.validation.Constraint;
import javax.validation.Payload;
import org.apache.openjpa.example.gallery.ImageType;
/**
* Type-level annotation used to specify an image constraint. Uses
* ImageValidator to perform the validation.
*/
@Documented
@Constraint(validatedBy = ImageValidator.class)
@Target({ TYPE })
@Retention(RUNTIME)
public @interface ImageConstraint {
String message() default "Image data is not a supported format.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
ImageType[] value() default { ImageType.GIF, ImageType.JPEG };
}

View File

@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.example.gallery.constraint;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import javax.validation.Constraint;
import javax.validation.Payload;
import org.apache.openjpa.example.gallery.ImageType;
/**
* Attribute-level annotation used to specify an image content constraint. Uses
* ImageContentValidator to perform the validation.
*/
@Documented
@Constraint(validatedBy = ImageContentValidator.class)
@Target({ METHOD, FIELD })
@Retention(RUNTIME)
public @interface ImageContent {
String message() default "Image data is not a supported format.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
ImageType[] value() default { ImageType.GIF, ImageType.JPEG };
}

View File

@ -0,0 +1,72 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.example.gallery.constraint;
import java.util.Arrays;
import java.util.List;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.apache.openjpa.example.gallery.ImageType;
/**
* Simple check that file format is of a supported type
*/
public class ImageContentValidator implements ConstraintValidator<ImageContent, byte[]> {
private List<ImageType> allowedTypes = null;
/**
* Configure the constraint validator based on the image
* types it should support.
* @param constraint the constraint definition
*/
public void initialize(ImageContent constraint) {
allowedTypes = Arrays.asList(constraint.value());
}
/**
* Validate a specified value.
*/
public boolean isValid(byte[] value, ConstraintValidatorContext context) {
if (value == null) {
return false;
}
// Verify the GIF header is either GIF87 or GIF89
if (allowedTypes.contains(ImageType.GIF)) {
String gifHeader = new String(value, 0, 6);
if (value.length >= 6 &&
(gifHeader.equalsIgnoreCase("GIF87a") ||
gifHeader.equalsIgnoreCase("GIF89a"))) {
return true;
}
}
// Verify the JPEG begins with SOI & ends with EOI
if (allowedTypes.contains(ImageType.JPEG)) {
if (value.length >= 4 &&
value[0] == 0xff && value[1] == 0xd8 &&
value[value.length - 2] == 0xff &&
value[value.length -1] == 0xd9) {
return true;
}
}
// Unknown file format
return false;
}
}

View File

@ -0,0 +1,26 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.example.gallery.constraint;
/**
* Simple interface used to specify validation group: ImageGroup
*/
public interface ImageGroup {
}

View File

@ -0,0 +1,90 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.example.gallery.constraint;
import java.util.Arrays;
import java.util.List;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.apache.openjpa.example.gallery.ImageType;
import org.apache.openjpa.example.gallery.model.Image;
/**
* Simple validator used to verify that image data is of a supported type
*/
public class ImageValidator implements ConstraintValidator<ImageConstraint, Image> {
private List<ImageType> allowedTypes = null;
/**
* Configure the constraint validator based on the image
* types it should support.
* @param constraint the constraint definition
*/
public void initialize(ImageConstraint constraint) {
allowedTypes = Arrays.asList(constraint.value());
}
/**
* Validate a specified value.
*/
public boolean isValid(Image value, ConstraintValidatorContext context) {
// JSR-303 best practice. Promotes the use of @NotNull to perform
// null checking.
if (value == null) {
return true;
}
// All these values will be pre-validated with @NotNull constraints
// so they are safe to use
byte[] data = value.getData();
String fileName = value.getFileName();
ImageType type = value.getType();
// Verify the GIF type is correct5, has the correct extension and
// the data header is either GIF87 or GIF89
if (allowedTypes.contains(ImageType.GIF) &&
type == ImageType.GIF &&
fileName.endsWith(".gif")) {
if (data != null && data.length >= 6) {
String gifHeader = new String(data, 0, 6);
if (gifHeader.equalsIgnoreCase("GIF87a") ||
gifHeader.equalsIgnoreCase("GIF89a")) {
return true;
}
}
}
// Verify the JPEG type is correct, has the correct extension and
// the data begins with SOI & ends with EOI markers
if (allowedTypes.contains(ImageType.JPEG) &&
value.getType() == ImageType.JPEG &&
(fileName.endsWith(".jpg") ||
fileName.endsWith(".jpeg"))) {
if (data.length >= 4 &&
data[0] == 0xff && data[1] == 0xd8 &&
data[data.length - 2] == 0xff &&
data[data.length - 1] == 0xd9) {
return true;
}
}
// Unknown file format
return false;
}
}

View File

@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.example.gallery.constraint;
import javax.validation.GroupSequence;
import javax.validation.groups.Default;
/**
* Sequenced validation group definition. When this validation group is
* used constraints within the Default group will validate first. If
* successful, constraints within the ImageGroup will validate next.
*/
@GroupSequence({Default.class, ImageGroup.class})
public interface SequencedImageGroup {
}

View File

@ -0,0 +1,81 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.example.gallery.model;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.ManyToMany;
import javax.validation.constraints.NotNull;
/**
* Album entity. Contains references to zero or more images and zero or more
* image creators/authors.
*/
@Entity
public class Album {
@Id
@GeneratedValue
private long id;
@NotNull
private String name;
@OneToMany
private List<Image> images;
@ManyToMany
private List<Creator> creator;
public void setId(long id) {
this.id = id;
}
public long getId() {
return id;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setImages(List<Image> images) {
this.images = images;
}
public List<Image> getImages() {
return images;
}
public void setCreator(List<Creator> creator) {
this.creator = creator;
}
public List<Creator> getCreator() {
return creator;
}
}

View File

@ -0,0 +1,94 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.example.gallery.model;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.validation.constraints.NotNull;
/**
* Creator entity. Contains a reference to one or more images authored by
* an instance of the creator.
*/
@Entity
public class Creator {
@Id
@GeneratedValue
private long id;
@NotNull(message="Photographer's first name must be specified.")
private String firstName;
@NotNull(message="Photographer's last name must be specified.")
private String lastName;
@OneToMany
@OrderBy("fileName")
private List<Image> images;
@ManyToMany
private List<Album> albums;
public void setId(long id) {
this.id = id;
}
public long getId() {
return id;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getFirstName() {
return firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getLastName() {
return lastName;
}
public void setImages(List<Image> images) {
this.images = images;
}
public List<Image> getImages() {
return images;
}
public List<Album> getAlbums() {
return albums;
}
public void setAlbums(List<Album> albums) {
this.albums = albums;
}
}

View File

@ -0,0 +1,105 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.openjpa.example.gallery.model;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import org.apache.openjpa.example.gallery.ImageType;
import org.apache.openjpa.example.gallery.constraint.ImageConstraint;
import org.apache.openjpa.example.gallery.constraint.ImageGroup;
/**
* Image entity which makes use of several BV constraints.
*/
@Entity
@ImageConstraint(groups=ImageGroup.class)
public class Image {
private long id;
private ImageType type;
private String fileName;
private byte[] data;
private Location location;
private Creator creator;
@Id
@GeneratedValue
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@NotNull(message="Image type must be specified.")
@Enumerated(EnumType.STRING)
public ImageType getType() {
return type;
}
public void setType(ImageType type) {
this.type = type;
}
@NotNull(message="Image file name must not be null.")
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
@NotNull(message="Image data must not be null.")
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
}
@Valid
@Embedded
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
@ManyToOne
public Creator getCreator() {
return creator;
}
public void setCreator(Creator creator) {
this.creator = creator;
}
}

View File

@ -0,0 +1,72 @@
package org.apache.openjpa.example.gallery.model;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
/**
* Location embeddable with several BV constraints applied.
*/
@Embeddable
public class Location {
@NotNull(message="City must be specified.")
private String city;
private String street;
private String state;
@NotNull(message="Country must be specified.")
@Size(message="Country must be 50 characters or less.", max=50)
@Column(length=50)
private String country;
@Size(message="Zip code must be 10 characters or less.", max=10)
@Pattern(message="Zip code must be 5 digits or use the 5+4 format.",
regexp="^\\d{5}(([\\-]|[\\+])\\d{4})?$")
@Column(length=10)
private String zipCode;
public void setCity(String city) {
this.city = city;
}
public String getCity() {
return city;
}
public void setStreet(String street) {
this.street = street;
}
public String getStreet() {
return street;
}
public void setState(String state) {
this.state = state;
}
public String getState() {
return state;
}
public void setCountry(String country) {
this.country = country;
}
public String getCountry() {
return country;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public String getZipCode() {
return zipCode;
}
}

View File

@ -0,0 +1,122 @@
package org.apache.openjpa.example.gallery;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import org.apache.openjpa.example.gallery.model.Image;
import org.apache.openjpa.example.gallery.model.Location;
public class TestJPAValidation extends junit.framework.TestCase {
/**
* Shows usage of BV constraints with JPA at pre-update, pre-remove,
* and pre-persist lifecycle events.
*/
public void testValidation() {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("BeanValidation");
EntityManager em = emf.createEntityManager();
// Create a valid location
Location loc = new Location();
loc.setCity("Rochester");
loc.setState("MN");
loc.setZipCode("55901");
loc.setCountry("USA");
// Create an Image with non-matching type and file extension
Image img = new Image();
img.setType(ImageType.JPEG);
img.setFileName("Winter_01.gif");
loadImage(img);
img.setLocation(loc);
// *** PERSIST ***
try {
em.getTransaction().begin();
System.out.println("Persisting an entity with non-matching extension and type");
em.persist(img);
fail();
} catch (ConstraintViolationException cve) {
// Transaction was marked for rollback, roll it back and
// start a new TX
em.getTransaction().rollback();
handleConstraintViolation(cve);
em.getTransaction().begin();
System.out.println("Fixing the file type and re-attempting the persist.");
img.setType(ImageType.GIF);
em.persist(img);
em.getTransaction().commit();
System.out.println("Persist was successful");
}
// *** UPDATE ***
try {
em.getTransaction().begin();
// Modify the file name to a non-matching file name
// and commit to trigger an update
System.out.println("Modifying file name to use an extension that does not");
System.out.println("match the file type. This will cause a CVE.");
img.setFileName("Winter_01.jpg");
em.getTransaction().commit();
fail();
} catch (ConstraintViolationException cve) {
// Handle the exception. The commit failed so the transaction
// was already rolled back.
System.out.println("Update failed as expected");
handleConstraintViolation(cve);
}
// The update failure caused img to be detached. It must be merged back
// into the persistence context.
img = em.merge(img);
// *** REMOVE ***
em.getTransaction().begin();
try {
// Remove the type and commit to trigger removal
System.out.println("Setting the type to an invalid type. This will cause a");
System.out.println("validation exception upon removal");
img.setType(null);
em.remove(img);
em.getTransaction().commit();
fail();
} catch (ConstraintViolationException cve) {
// Rollback the active transaction and handle the exception
em.getTransaction().rollback();
System.out.println("Remove failed as expected");
handleConstraintViolation(cve);
}
em.close();
emf.close();
System.out.println("Done");
}
// Handles constraint violations by printing out violation information
private static void handleConstraintViolation(ConstraintViolationException cve) {
Set<ConstraintViolation<?>> cvs = cve.getConstraintViolations();
for (ConstraintViolation<?> cv : cvs) {
System.out.println("------------------------------------------------");
System.out.println("Violation: " + cv.getMessage());
System.out.println("Entity: " + cv.getRootBeanClass().getSimpleName());
// The violation occurred on a leaf bean (embeddable)
if (cv.getLeafBean() != null && cv.getRootBean() != cv.getLeafBean()) {
System.out.println("Embeddable: " + cv.getLeafBean().getClass().getSimpleName());
}
System.out.println("Attribute: " + cv.getPropertyPath());
System.out.println("Invalid value: " + cv.getInvalidValue());
System.out.println("------------------------------------------------");
}
}
// Mock image loading utility... simply loads the GIF89a header to satisfy the
// constraint validator.
private static void loadImage(Image img) {
img.setData(new byte[] { 'G', 'I', 'F', '8', '9', 'a' });
}
}

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0" >
<persistence-unit name="BeanValidation">
<description>Example persistence unit for Bean Validation</description>
<class>org.apache.openjpa.example.gallery.model.Album</class>
<class>org.apache.openjpa.example.gallery.model.Creator</class>
<class>org.apache.openjpa.example.gallery.model.Image</class>
<class>org.apache.openjpa.example.gallery.model.Location</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<validation-mode>CALLBACK</validation-mode>
<properties>
<property name="openjpa.ConnectionDriverName"
value="org.apache.derby.jdbc.EmbeddedDriver" />
<property name="openjpa.ConnectionURL"
value="jdbc:derby:database/ImageDB;create=true" />
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
<property name="openjpa.DynamicEnhancementAgent" value="false"/>
<property name="javax.persistence.validation.group.pre-persist"
value="org.apache.openjpa.example.gallery.constraint.SequencedImageGroup"/>
<property name="javax.persistence.validation.group.pre-update"
value="org.apache.openjpa.example.gallery.constraint.SequencedImageGroup"/>
<property name="javax.persistence.validation.group.pre-remove"
value="javax.validation.groups.Default"/>
</properties>
</persistence-unit>
</persistence>