mirror of https://github.com/apache/openjpa.git
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:
parent
632639bb62
commit
6bdb269a8b
|
@ -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>
|
|
@ -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
|
||||
}
|
|
@ -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 };
|
||||
}
|
|
@ -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 };
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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' });
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
Loading…
Reference in New Issue