openjpa-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mik...@apache.org
Subject svn commit: r1409057 [4/25] - in /openjpa/site: branches/ trunk/ trunk/cgi-bin/ trunk/content/ trunk/content/images/ trunk/lib/ trunk/resources/ trunk/templates/
Date Wed, 14 Nov 2012 01:50:14 GMT
Added: openjpa/site/trunk/content/bean-validation-primer.mdtext
URL: http://svn.apache.org/viewvc/openjpa/site/trunk/content/bean-validation-primer.mdtext?rev=1409057&view=auto
==============================================================================
--- openjpa/site/trunk/content/bean-validation-primer.mdtext (added)
+++ openjpa/site/trunk/content/bean-validation-primer.mdtext Wed Nov 14 01:49:37 2012
@@ -0,0 +1,1117 @@
+Title: Bean Validation Primer
+<a name="BeanValidationPrimer-OpenJPABeanValidationPrimer"></a>
+## OpenJPA Bean Validation Primer
+
+A new feature defined by the JPA 2.0 specification is the ability to
+seamlessly integrate with a [JSR-303](http://jcp.org/en/jsr/detail?id=303)
+ bean validation provider.   With minimal effort, [OpenJPA 2.0|http://openjpa.apache.org/openjpa-200.html]
+ can be coupled with a [JSR-303|http://jcp.org/en/jsr/detail?id=303]
+ validation provider to provide runtime data validation.  By combining
+these two technologies, you get a standardized persistence solution with
+the added ability to perform standardized java bean validation.
+
+<a name="BeanValidationPrimer-WhatisBeanValidation?"></a>
+### What is Bean Validation?
+
+Most applications, especially those that gather input from a user, contain
+a significant amount of code to perform data validation.  It is typically
+custom code, fragmented and littered throughout the application.  Worse,
+there may be duplicate validation code at the presentation (Web) , business
+(EJB), and persistence layers.	The task of keeping duplicate code in synch
+can be especially problematic.	A slight modification in the code at one
+layer can lead to an unforseen breakage in another.
+
+The Bean Validation API was designed to provide a standardized method for
+validating data within Java beans.  As an added feature, it seemlessly
+integrates with several JEE6 technologies including [JPA 2.0](http://jcp.org/en/jsr/detail?id=317)
+, [JCA 1.6|http://jcp.org/en/jsr/summary?id=322]
+, and [JSF 2.0|http://jcp.org/en/jsr/detail?id=314]
+.  Additionally, JEE6 complaint servers are required to support bean
+validation and must include a validation provider.  While a JEE6
+environment provides some simplified packaging and configuration benefits,
+bean validation works equally well in a JSE environment.  For simplicity,
+this primer will use a JSE environment, but the example code could be used
+within a JEE6 environment with very few modifications.
+
+While the [JSR-303 specification](http://jcp.org/en/jsr/detail?id=303)
+ is very feature rich and extensible, there are three core concepts that
+will be of most interest to the majority of users:  constraints, constraint
+violation handling, and the validator itself.  If you are running in an
+integrated environment like JPA, you will rarely have to concern yourself
+with the validator; simplifying things even further.
+
+<a name="BeanValidationPrimer-ValidationConstraints"></a>
+### Validation Constraints
+
+Constraints are a fundamental component of bean validation.  Constraints
+can be placed on Java beans and/or fields and properties (collectively
+labeled attributes in JPA terminology) to constrain the data within the
+bean.  A constraint can either be defined using annotations or XML.  The
+bean validation specification defines a small set of constraints that must
+be included with every validation provider.  This small set covers most
+types of simple validation in addition to a powerful regular expression
+based validator.  If the built-in constraints don't fit the bill, you can
+very easily build your own custom validators and matching constraints. 
+Let's start by looking at some simple constraints and then move to creating
+some custom constraints.
+
+<a name="BeanValidationPrimer-ConstraininganEntity"></a>
+### Constraining an Entity
+
+For the purposes of an example, let's start building the JPA domain model
+for a digital image storage system. For the sake of simplicity, we'll start
+with a simple entity "Image".  An [Image](http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/model/Image.java)
+ has an ID, image type, file name, and image data.  Our system has a
+requirement that the image type must be specified and the image file name
+must include a valid JPEG or GIF extension.  The code below shows the
+annotated Image entity with some built-in bean validation constraints
+applied.
+
+  
+  
+<DIV class="code panel" style="border-style: solid;border-width: 1px;"><DIV class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><B>Image.java|borderStyle=solid</B></DIV><DIV class="codeContent panelContent">
+    package org.apache.openjpa.example.gallery.model;
+    
+    import javax.persistence.Entity;
+    import javax.persistence.EnumType;
+    import javax.persistence.Enumerated;
+    import javax.persistence.GeneratedValue;
+    import javax.persistence.Id;
+    import javax.validation.constraints.NotNull;
+    import javax.validation.constraints.Pattern;
+    
+    @Entity
+    public class Image {
+    
+        private long id;
+        private ImageType type;
+        private String fileName;
+        private byte[]
+ data;
+    
+        @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;
+        }
+    
+        @Pattern(regexp = ".*\\.jpg|.*\\.jpeg|.*\\.gif",
+    	message="Only images of type JPEG or GIF are supported.")
+        public String getFileName() {
+    	return fileName;
+        }
+    
+        public void setFileName(String fileName) {
+    	this.fileName = fileName;
+        }
+    
+        public byte[]
+ getData() {
+    	return data;
+        }
+    
+        public void setData(byte[]
+ data) {
+    	this.data = data;
+        }
+    }
+
+
+  
+  
+The [Image](http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/model/Image.java)
+ class uses two built in constraints @NotNull and @Pattern. The @NotNull
+constraint ensures that an [ImageType|http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/ImageType.java]
+ is specified and @Pattern constraint uses regular expression pattern
+matching to ensure the image file name is suffixed with a supported image
+format.  Each constraint has corresponding validation logic that gets
+executed at runtime when the Image entity is validated.  If either
+constraint is not met, the JPA provider will throw a
+ConstraintViolationException with the defined message.	The [JSR-303 specification|http://jcp.org/en/jsr/detail?id=303]
+ also makes provisions for the use of a variable within the message
+attribute.  The variable references a keyed message in a resource bundle. 
+That allows for environment specific messages and localization of messages.
+ See the [JSR-303 specification|http://jcp.org/en/jsr/detail?id=303]
+, section 4.1.3 for additional details regarding the customization and
+localization of messages.
+
+<a name="BeanValidationPrimer-CustomConstraintsandValidators"></a>
+### Custom Constraints and Validators
+
+If the built-in constraints do not meet your needs, you can create your own
+custom validators and constraints.  In our previous example, the Image
+entity used the @Pattern constraint to validate the file name of the image.
+ However, it did no constraint checking on the actual image data itself.  A
+pattern-based constraint could potentially be used, but this is rather
+inflexible and will get messy.	A custom constraint and validator provides
+a more robust and flexible solution.  First, let's create a custom method
+level constraint annotation named [ImageContent](http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/constraint/ImageContent.java)
+.
+
+  
+  
+<DIV class="code panel" style="border-style: solid;border-width: 1px;"><DIV class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><B>ImageContent.java|borderStyle=solid</B></DIV><DIV class="codeContent panelContent">
+    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.model.ImageType;
+    
+    @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 };
+    }
+
+  
+  
+
+Now, let's create the validator class, [ImageContentValidator](http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/constraint/ImageContentValidator.java)
+.  The logic within this validator gets executed by validation provider
+when the constraint is validated.  Notice, the validator class is bound to
+the constraint annotation via the validatedBy attribute on the @Constraint
+annotation.
+
+  
+  
+<DIV class="code panel" style="border-style: solid;border-width: 1px;"><DIV class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><B>ImageContentValidator.java|borderStyle=solid</B></DIV><DIV class="codeContent panelContent">
+    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.model.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;
+        }
+    }
+
+  
+  
+
+Finally, let's apply the new constraint to the getData() method on our
+Image class.
+
+  
+  
+
+        @ImageContent
+        public byte[]
+ getData() {
+    	return data;
+        }
+
+  
+  
+
+When validation of the "data" attribute occurs, the isValid() method in our [ImageContentValidator](http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/constraint/ImageContentValidator.java)
+ will fire.  This method contains logic for performing simple validation of
+ the format of the binary image data.  A potentially overlooked feature in
+the [ImageContentValidator|http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/constraint/ImageContentValidator.java]
+ is that it can also validate for a specific image type.  By definition, it
+accepts for JPEG or GIF formats, but it can also validate for a specific
+format.  For example, by changing the annotation to:
+
+  
+  
+
+        @ImageContent(ImageType.JPEG)
+        public byte[]
+ getData() {
+    	return data;
+        }
+
+  
+  
+
+instructs the validator to only permit image data with valid JPEG content.
+
+<a name="BeanValidationPrimer-Type-levelConstraints"></a>
+### Type-level Constraints
+
+The examples thus far have shown the use of validation constraints on
+individual attributes.	That is sufficient in many cases, but validation
+logic often needs to consider combinations of attributes when validating an
+entity.  For example, the constraints applied to the Image entity validate
+that an image type is set (not null), the extension on the image file name
+are of a supported type, and the data format is correct for the indicated
+type. But, for example, it will not collectively validate that a file named
+"img0.gif" is of type GIF and the format of the data is for a valid GIF
+image.	There are several options to provide collective validation.  One
+option is to create subclasses of Image, JPEGImage and GIFImage, with
+constraints geared for each of these types.  Another, less invasive and
+simpler option is a type-level constraint.  Let's modify our Image class to
+use a custom type-level constraint.  Here is the updated Image entity with
+the new type-level constraint.
+
+  
+  
+<DIV class="code panel" style="border-style: solid;border-width: 1px;"><DIV class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><B>Image.java|borderStyle=solid</B></DIV><DIV class="codeContent panelContent">
+    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.constraint.ImageConstraint;
+    import org.apache.openjpa.example.gallery.constraint.SequencedImageGroup;
+    
+    @Entity
+    @ImageConstraint(groups=ImageGroup.class)
+    public class Image {
+    
+        private long id;
+        private ImageType type;
+        private String fileName;
+        private byte[]
+ data;
+    
+        @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;
+        }
+    }
+
+  
+  
+
+Notice that the @Pattern and @ImageContent were replaced by @NotNull
+constraints.  The new class level constraint will perform the duties
+previously performed by @Pattern and @ImageContent.  The @NotNull
+constraints have been added as a first level check.  If these constraints
+succeed, the type level validator @ImageConstraint will fire, providing
+complex validation.  Sequenced validation is provided using validation
+groups and group sequences.  These concepts will be explained shortly.
+
+Here is the code for the new [ImageConstraint](http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/constraint/ImageConstraint.java)
+ annotation:
+
+  
+  
+<DIV class="code panel" style="border-style: solid;border-width: 1px;"><DIV class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><B>ImageConstraint.java|borderStyle=solid</B></DIV><DIV class="codeContent panelContent">
+    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.model.ImageType;
+    
+    @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 };
+    }
+
+  
+  
+
+Unlike the [ImageContent](http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/constraint/ImageContent.java)
+ constraint, [ImageConstraint|http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/constraint/ImageConstraint.java]
+ is targeted for a TYPE.  This allows this annotation to be applied at a
+type level (class or interface).  This constraint has a new validator
+class, [ImageValidator|http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/constraint/ImageValidator.java]
+.
+
+  
+  
+<DIV class="code panel" style="border-style: solid;border-width: 1px;"><DIV class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><B>ImageValidator.java|borderStyle=solid</B></DIV><DIV class="codeContent panelContent">
+    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.model.Image;
+    import org.apache.openjpa.example.gallery.model.ImageType;
+    
+    /**
+     * Simple check that an Image is consistent in type, name, and format.
+     */
+    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)
+{
+    	if (value == null) {
+    	    return true;
+    	}
+    
+    	// All these fields will be pre-validated with @NotNull constraints
+    	// so they are safe to use without null checks.
+            byte[]
+ data = value.getData();
+    	String fileName = value.getFileName();
+    	ImageType type = value.getType();
+    
+    	// Verify the GIF type is correct, 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;
+        }
+    }
+
+  
+  
+
+One thing that must be considered in a JPA environment is the load state of
+the attributes of an entity when doing type-level validation.  Simply
+accessing attributes can have some side effects.  If the attribute is
+marked LAZY fetch it may get loaded in order to perform validation.  If the
+attribute is not loaded and cannot be loaded (for several reasons, most
+likely due to detachment) you'll be validating	inconsistent data.  The JPA
+2.0 specification provides a utility interface to help in these situations.
+ It can be obtained statically so squirreling away a copy of the JPA entity
+manager is not necessary.  Here is an example of how PersistenceUtil could
+be used in the ImageValidator.
+
+  
+  
+
+            byte[]
+ data = value.getData();
+    	PersistenceUtil putil = Persistence.getPersistenceUtil();
+    	if (!putil.isLoaded(value, "data")) {
+    	    // don't validate the data
+    	}
+
+  
+  
+
+<a name="BeanValidationPrimer-TheCompleteDomainModel"></a>
+### The Complete Domain Model
+
+Now that some of the basics of bean validation are covered, let's finish up
+the domain model for our simple application and then get into JPA specifics
+through an example.
+
+!ig_domain_model.gif!
+
+The persistent types [Album](http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/model/Album.java)
+, [Creator|http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/model/Creator.java]
+, and [Location|http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/model/Location.java]
+ are new to the domain model.  An Album entity contains a reference to
+collection of its Image entities.  The Creator entity contains a reference
+to the Album album entities the image Creator contributed to and a
+reference to the Image entities they've created.  This provides full
+navigational capabilities to and from each of the entities in the domain. 
+An embeddable, Location, has been added to Image to allow location
+information to be stored along with the Image.
+
+The Album and Creator entities have a few built-in constraints and are
+pretty run of the mill.  The embeddable [Location](http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/model/Location.java)
+ is a bit more interesting in that it demonstrates the use of the @Valid
+annotation to validate embedded objects.  In order to embed location into
+an image a new field and corresponding persistent properties were added to
+the Image class:
+
+  
+  
+
+        private Location location;
+    
+        @Valid
+        @Embedded
+        public Location getLocation() {
+    	return location;
+        }
+    
+        public void setLocation(Location location) {
+    	this.location = location;
+        }
+
+  
+  
+
+Notice the use of the @Valid annotation.  This provides chained validation
+of embeddables within a JPA environment.  Thus, when Image is validated,
+any constraints on the Location it references are also validated.  If
+@Valid was not specified, Location would not get validated.  In a JPA
+environment, chained validation via @Valid is only available for
+embeddables.  Referenced entities and collections of entities are validated
+separately in order to prevent circular validation.
+
+<a name="BeanValidationPrimer-ValidationGroups"></a>
+### Validation Groups
+
+Bean validation uses validation groups to determine what and when
+validation occurs.  There are no special interfaces to implement or
+annotations to apply in order to create a validation group.  A validation
+group is denoted simply by a class definition. However, it is strongly
+recommended that simple interfaces are used.  This is a best practice since
+it makes validation groups more usable in multiple environments.  Whereas,
+if a class or entity definition were used as a validation group, it may
+pollute the object model of another application by bringing in domain
+classes and logic that do not make sense for the application. By default,
+if a validation group or multiple groups is not specified on an individual
+constraint, it will be validated using the
+*javax.validation.groups.Default* group.  Creating a custom group is as
+simple as creating a new interface definition.
+
+  
+  
+<DIV class="code panel" style="border-style: solid;border-width: 1px;"><DIV class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><B>ImageGroup.java|borderStyle=solid</B></DIV><DIV class="codeContent panelContent">
+    package org.apache.openjpa.example.gallery.constraint;
+    
+    public interface ImageGroup {
+    
+    }
+
+  
+  
+
+This new [ImageGroup](http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/constraint/ImageGroup.java)
+ validation group can now be applied to a constraint.
+
+  
+  
+
+        @ImageContent(groups={Default.class,ImageGroup.class})
+        public byte[]
+ getData() {
+    	return data;
+        }
+
+  
+  
+
+This @ImageContent constraint in this example will validate when either or
+both the Default and/or [ImageGroup](http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/main/java/org/apache/openjpa/example/gallery/constraint/ImageGroup.java)
+ group is/are validated.
+
+By default there is no order applied or short circuiting behavior when
+validation occurs.  Validation ordering and short circuiting is an
+extremely useful function that can be achieved by defining a group
+sequence.  A group sequence is defined via the @GroupSequence annotation
+with an ordered array of validation groups.  When the group sequence is
+validated, the constraints supplied in its grouping are validated in the
+order they are specified.  In addition, if a constraint within a group
+fails, the groups that follow will not be validated.  This allows
+lightweight validation such as @NotNull or @Size constraints to validate
+before heavyweight constraints.  The Image class uses a group sequence to
+validate its lightweight @NotNull constraints (which use the Default
+validation group) before validating its heavyweight constraint
+@ImageValidator (which validates when the ImageGroup) is validated. 
+Sequenced validation can be accomplished by defining a new validation
+group.
+
+  
+  
+<DIV class="code panel" style="border-style: solid;border-width: 1px;"><DIV class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><B>SequencedImageGroup.java|borderStyle=solid</B></DIV><DIV class="codeContent panelContent">
+    package org.apache.openjpa.example.gallery.constraint;
+    
+    import javax.validation.GroupSequence;
+    import javax.validation.groups.Default;
+    
+    @GroupSequence({Default.class, ImageGroup.class})
+    public interface SequencedImageGroup {
+    
+    }
+
+  
+  
+
+This group is then specified during validation.  How to specify which
+groups will be validated in a JPA environment is explained in the sections
+to follow.
+
+<a name="BeanValidationPrimer-JPAIntegration"></a>
+### JPA Integration
+
+The JPA 2.0 specification makes integration with JSR-303 very simple.  In a
+JSE environment all you need to do is provide the JSR-303 API and a JSR-303
+bean validation provider on your runtime classpath and bean validation is
+enabled by default.  OpenJPA adds one additional caveat.  With OpenJPA you
+must also be using a version 2.0 persistence.xml file.	A version 1.0
+persistence.xml provides no means to configure bean validation.  Requiring
+a version 2.0 persistence.xml prevents a pure JPA 1.0 application from
+incurring the validation startup and runtime costs.  This is important
+given that there is no standard means for a 1.0-based application to
+disable validation.  Besides adding the necessary bean validation jars to
+your classpath, enabling validation in an existing 1.0 application may be
+as simple as modifying the root element of your persistence.xml to:
+
+  
+  
+
+    <?xml version="1.0" encoding="UTF-8"?>
+    <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>
+
+  
+  
+
+{info:title="Note"}While the JPA 2.0 specification is backward compatible
+with JPA 1.0, there are some OpenJPA specific extensions that are not.	By
+switching to a 2.0 persistence.xml, in some cases you may need to specify
+compatibility flags in order to get OpenJPA 1.0 behavior.  See the [migration considerations](http://openjpa.apache.org/builds/latest/docs/manual/migration_considerations.html)
+ section of the [OpenJPA 2.x manual|http://openjpa.apache.org/builds/latest/docs/manual/main.html]
+ for additional information.
+{info}
+
+<a name="BeanValidationPrimer-ValidationModes"></a>
+##### Validation Modes
+
+Bean validation provides three modes of operation within the JPA
+environment: _auto_, _callback_, and _none_.  As you may have guessed,
+_none_ disables bean validation for a particular persistence unit.  The
+_auto_ mode, which is the default, enables bean validation if a validation
+provider is available within the classpath.  When _callback_ mode is
+specified, a bean validation provider must be available for use by the JPA
+provider.  If not, the JPA provider will throw an exception upon
+instantiation of a new JPA entity manager factory.  While _auto_ mode
+simplifies deployment, it can lead to problems if validation is
+unexpectedly not taking place due to a configuration problem.  It is a good
+practice to use either _none_ or _callback_ mode explicitly in order to get
+consistent behavior.  In addition, if _none_ is specified, OpenJPA will do
+optimization at startup and will not attempt to perform unexpected
+validation.  Explicitly disabling validation is especially important in a
+JEE6 environment where the container is mandated to provide a validation
+provider.  Thus, unless specified, a JPA 2.0 app running in a container
+will have validation enabled.  This will add additional processing during
+lifecycle events. We'll get to lifecycle events shortly.
+
+There are two means to configure validation modes in JPA 2.0.  Perhaps the
+simplest is to add a validation-mode element to your persistence.xml with
+the desired validation mode.
+
+  
+  
+
+        <persistence-unit name="auto-validation">
+    	...
+    	<!-- Validation modes: AUTO, CALLBACK, NONE -->
+    	<validation-mode>AUTO</validation-mode>
+    	...
+        </persistence-unit>
+
+  
+  
+
+In addition, the validation mode can be configured programmatically by
+specifying the *javax.persistence.validation.mode* property with value
+_auto_, _callback_, or _none_ when creating a new JPA entity manager
+factory.
+
+  
+  
+
+    	Map<String, String> props = new HashMap<String,String>();
+    	props.put("javax.persistence.validation.mode", "callback");
+    	EntityManagerFactory emf = 
+    	    Persistence.createEntityManagerFactory("validation", props);
+    
+
+  
+  
+
+<a name="BeanValidationPrimer-ValidationinJPA"></a>
+##### Validation in JPA
+
+We've covered the basics of constraints and validation configuration, now
+on to actually doing some validation within JPA.  Bean validation within
+JPA occurs during JPA's lifecycle event processing.  If enabled, validation
+will occur at the final stage of the PrePersist, PreUpdate, and PreRemove
+lifecycle events.  Validation will occur only after all user defined
+lifecycle events, since some of those events may modify the entity that is
+being validated.   By default, JPA enables validation for the Default
+validation group for PrePersist and PreUpdate lifecycle events.  If you
+need to validate other Validation groups or enable validation for the
+PreRemove event you can specify the validation groups to validate for each
+lifecycle event in the [persistence.xml](http://svn.apache.org/repos/asf/openjpa/trunk/openjpa-examples/image-gallery/src/test/resources/META-INF/persistence.xml)
+.
+
+  
+  
+
+        <persistence-unit name="non-default-validation-groups">
+    	<class>my.Entity</class>
+    	<validation-mode>CALLBACK</validation-mode>
+    	<properties>
+    	    <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>
+
+  
+  
+
+Now that we've gone through validation basics and JPA configuration
+options, the validation part is a piece of cake.  In general, you simply
+need to handle validation exceptions that may result from various JPA
+operations.  Here are some simple examples for the persist, update, and
+remove operations.  We'll get to more in-depth exception handling in a
+moment.
+
+  
+  
+
+    	EntityManagerFactory emf = 
+    	    Persistence.createEntityManagerFactory("BeanValidation");
+    	EntityManager em = emf.createEntityManager();
+    
+    	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();
+    	    // Persist the entity with non-matching extension and type
+    	    em.persist(img);
+    	} catch (ConstraintViolationException cve) {
+    	    // Transaction was marked for rollback, roll it back and
+    	    // start a new one
+    	    em.getTransaction().rollback();
+    	    em.getTransaction().begin();
+    	    // Fix the file type and re-try the persist.
+    	    img.setType(ImageType.GIF);
+    	    em.persist(img);
+    	    em.getTransaction().commit();
+    	}
+    
+    	// *** UPDATE ***
+    	try {
+    	    em.getTransaction().begin();
+    	    // Modify the file name to a non-matching file name 
+    	    // and commit to trigger an update
+    	    img.setFileName("Winter_01.jpg");
+    	    em.getTransaction().commit();
+    	}  catch (ConstraintViolationException cve) {
+    	    // Handle the exception.  The commit failed so the transaction
+    	    // was already rolled back.
+    	    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
+    	    img.setType(ImageType.GIF);
+    	    em.remove(img);
+    	}  catch (ConstraintViolationException cve) {
+    	    // Rollback the active transaction and handle the exception
+    	    em.getTransaction().rollback();
+    	    handleConstraintViolation(cve);
+    	}
+    	em.close();
+    	emf.close();
+
+  
+  
+
+<a name="BeanValidationPrimer-ExceptionHandling"></a>
+##### Exception Handling
+
+If one or more constraints fail to validate during a lifecycle event, a
+ConstraintViolationException is thrown by the JPA provider.  The
+ConstraintViolationException thrown by the JPA provider includes the set of
+ConstraintViolations that occurred.  Individual constraint violations
+contain information regarding the constraint, including a message, the root
+bean (JPA entity), the leaf bean (useful when validating JPA embeddables),
+the attribute which failed to validate, and the value that caused the
+failure.  Here is a sample exception handling routine:
+
+  
+  
+
+        private 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());
+          }
+        }
+
+  
+  
+
+Constraint violation processing is not quite as straight forward when using
+type-level level validators with type-level constraints as using attribute
+level constraints. When type-level constraints are used it can be more
+difficult to determine	which attribute or combination of attributes failed
+to validate.  In addition, the entire object is returned as the invalid
+value instead of an individual attribute.  In cases where specific failure
+information is required, either use an attribute level constraint or a
+custom constraint violation may be provided as described in section 2.4 of
+the [JSR-303 specification](http://jcp.org/en/jsr/detail?id=303)
+.
+
+<a name="BeanValidationPrimer-OpenJPAandApacheBeanValidationLibraries"></a>
+### OpenJPA and Apache Bean Validation Libraries
+
+If you are not using a maven build environment, the use of bean validation
+in a JPA environment requires a 2.0 level JPA provider and a bean
+validation provider libraries.	Apache OpenJPA 2.0 includes a test suite
+which exercises the Apache Bean Validation provider and this has proven to
+be a very stable environment.  Here are the libraries you'll need.
+
+* Apache OpenJPA 2.0 provides an "all" library which makes it very simple
+to get OpenJPA 2.0 and all its dependencies in a single jar.  Download and
+extract the [OpenJPA 2.0 binary package](http://www.apache.org/dyn/closer.cgi/openjpa/2.0.0/apache-openjpa-2.0.0-binary.zip)
+ and reference the openjpa-all-2.0.0.jar on your build and runtime
+classpath.
+
+* Apache Bean Validation does not yet have a canned binary package, but it
+does publish nightly snapshots of the core valiation library and JSR-303
+extensions.  Until a binary package is available from the [Apache Bean Validation site](http://projects.apache.org/projects/bean_validation__incubating_.html)
+. You can obtain the core library, JSR-303 packages, and Geronimo JSR-303
+spec API directly from the maven repository.
+** [Apache Bean Validation Core](https://repository.apache.org/content/groups/public/org/apache/bval/bval-core/0.1-incubating/bval-core-0.1-incubating.jar)
+** [Apache Bean Validation JSR-303](https://repository.apache.org/content/groups/public/org/apache/bval/bval-jsr303/0.1-incubating/bval-jsr303-0.1-incubating.jar)
+** [Apache Geronimo Bean Validation Spec API](https://repository.apache.org/content/groups/public/org/apache/geronimo/specs/geronimo-validation_1.0_spec/1.1/geronimo-validation_1.0_spec-1.1.jar )
+** [Apache Commons Bean Utils](http://commons.apache.org/beanutils/download_beanutils.cgi)
+ - Extract the distribution and include commons-beanutils-1.8.3.jar on your
+runtime classpath.
+** [Apache Commons Lang](http://archive.apache.org/dist/commons/lang/binaries/commons-lang-2.4-bin.zip)
+ - Extract the distribution and *include commons-lang-2.4.jar in your
+classpath before openjpa-all-2.0.0.jar*.
+
+<a name="BeanValidationPrimer-MavenConfiguration"></a>
+### Maven Configuration
+
+If you are a maven user, dependency management is much simpler.  Here are
+the dependencies you'll need in order to use OpenJPA 2.0 and the current
+(as of this writing) snapshot of Apache Bean Validation.
+
+  
+  
+
+      <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>2.0.0</version>
+        </dependency>
+      </dependencies>
+
+  
+  
+
+<a name="BeanValidationPrimer-GettingtheSampleApplication"></a>
+### Getting the Sample Application
+
+The code for the example provided in this primer is currently available
+from the OpenJPA subversion repository.  Obtaining, building and running
+the example requires [Subversion](http://subversion.apache.org)
+, [Maven|http://maven.apache.org/download.html]
+ version 2.2.1 or later and JDK version 1.6.  Be sure to set your JAVA_HOME
+environment variable to the location of the 1.6 JDK.  To get and run the
+sample you must first get the source for OpenJPA via:
+
+*svn co* http://svn.apache.org/repos/asf/openjpa/trunk
+
+Next, from the trunk directory, run a quick build to generate the OpenJPA
+provider jars.
+
+*_mvn -Dtest install -DfailIfNoTests=false -Dmaven.test.skip=true_*
+
+<a name="BeanValidationPrimer-RunningtheSampleApplication"></a>
+### Running the Sample Application
+
+Currently, the sample only runs a jUnit which shows how bean validation can
+be used within the context of JPA persist, update, and remove operations. 
+To build and run the sample using maven:
+
+1. Goto the *openjpa-parent/openjpa-examples/image-gallery* directory
+within the source tree you downloaded in the previous section.
+
+2. Run: *_mvn clean install_*
+
+This command builds the image-gallery sample, enhances the entity classes,
+and runs the jUnits.  Within the Maven output, you should see output
+similar to the following.
+
+  
+  
+{quote}
+Persisting an entity with non-matching extension and type
+------------------------------------------------
+Violation: Image data is not a supported format.
+Entity: Image
+Attribute:
+Invalid value: org.apache.openjpa.example.gallery.model.Image@8d5aad
+------------------------------------------------
+Fixing the file type and re-attempting the persist.
+Persist was successful
+Modifying file name to use an extension that does not
+match the file type.  This will cause a CVE.
+Update failed as expected
+------------------------------------------------
+Violation: Image data is not a supported format.
+Entity: Image
+Attribute:
+Invalid value: org.apache.openjpa.example.gallery.model.Image@8d5aad
+------------------------------------------------
+Setting the type to an invalid type.  This will cause a
+validation exception upon removal
+Remove failed as expected
+------------------------------------------------
+Violation: Image type must be specified.
+Entity: Image
+Attribute: type
+Invalid value: null
+------------------------------------------------
+Done
+{quote}
+  
+  
+
+<a name="BeanValidationPrimer-ImportingtheSampleintoEclipse"></a>
+### Importing the Sample into Eclipse
+
+If you'd like to import the sample into Eclipse, from the image-gallery
+directory run:
+
+*mvn eclipse:eclipse*
+
+This will generate the necessary Eclipse project files.  Next, direct
+Eclipse to import a project from this directory.  You'll need to set the
+M2_REPO path variable to point at the location of your local Maven
+repository in order to get the project to build.
+
+<a name="BeanValidationPrimer-References"></a>
+### References
+
+[JSR-317 - JPA 2.0 Specification](http://jcp.org/en/jsr/detail?id=317)
+[JSR-303 - Bean Validation Specification](http://jcp.org/en/jsr/detail?id=303)
+[OpenJPA 2.0 Release](http://openjpa.apache.org/openjpa-200.html)
+[Apache Bean Validation Home](http://projects.apache.org/projects/bean_validation__incubating_.html)

Added: openjpa/site/trunk/content/begin-using-openjpa---the-basics
URL: http://svn.apache.org/viewvc/openjpa/site/trunk/content/begin-using-openjpa---the-basics?rev=1409057&view=auto
==============================================================================
--- openjpa/site/trunk/content/begin-using-openjpa---the-basics (added)
+++ openjpa/site/trunk/content/begin-using-openjpa---the-basics Wed Nov 14 01:49:37 2012
@@ -0,0 +1,488 @@
+h1. Introduction
+
+OpenJPA is an open source implementation of the Java JPA (Java Persistence API) specification from Apache. JPA provides an agnostic Java-based API for storing and retrieving information to a backend database. It has a canonical query language named Java Persistence Query Language, or JPQL, that blends with the programming methods of Java and eliminates the need to tailor database queries for a particular database. However, JPA also supports native SQL which can be used for quick ports with a known backend database. This tutorial is designed to walk you through the steps of setting up a simple {color:black}web application{color} to use OpenJPA Geronimo and to transact the derby database that comes with Geronimo. The tutorial code uses a simple Java Server Page (JSP), backed up by some basic classes. It displays a table of inventory items and categories. In this tutorial, we will not dive into details regarding the JSP code. Its purpose is to be a window through which you can 
 examine OpenJPA. &nbsp;The intended audience for this tutorial is those with some knowledge and understanding of the Java programming language and who are just beginning with OpenJPA. To start, you must download the following requirements and install them on your computer. For the purposes of this tutorial, we are using Eclipse as the IDE and Microsoft Windows as the operating system of choice.&nbsp;
+
+h2. Prerequisites
+
+*Geronimo V2.2:* You can get it [here|http://www.apache.org/dyn/closer.cgi/geronimo/2.2/geronimo-tomcat6-javaee5-2.2-bin.zip]. Download this file and unzip it to a permanent location. There is no installer. The server will run from the command line.
+
+*Java (J2SE) V1.6:* This tutorial was developed and tested with Java V1.6. If you don't already have Java V1.6 you can get the IBM JDK [here|http://www.ibm.com/developerworks/java/jdk/] or the Sun JDK [here|https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=jdk-6u16-oth-JPR@CDS-CDS_Developer].
+
+*Eclipse V3.2 or later:* This version has annotation support included. Annotations play a large role in OpenJPA.&nbsp; [Download|http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/galileo/SR1/eclipse-jee-galileo-SR1-win32.zip]Eclipse 3.2 or later.
+
+*Apache OpenJPA library:* For the purpose of implementing this tutorial you can select
+OpenJPA v1.2 or greater. You can download [Apache OpenJPA|http://openjpa.apache.org/downloads.html] from the Apache site. Note that the Milestone (openjpa-all-2.0.0-M3.jar as of this writing) is an early release of OpenJPA 2.0 and may have some instabilities. No issues have been noted for the usage in this tutorial.
+
+*The tutorial code files*: [These files|^OpenJPAWebAppTutorial.zip|attached source files] are provided with this tutorial. You will add them to your Eclipse project.
+
+h1. Setup and Running the Sample
+
+Now, that you have all the prerequisites for this tutorial downloaded and installed, the following sections will walk you through the Eclipse project setup and the OpenJPA configuration. Make sure you read through and follow each part carefully. &nbsp;
+
+h2. Setting up Eclipse
+
+After installing Eclipse, create a new project in a dedicated workspace for the tutorial. Complete the following setup instructions: First, make sure your Eclipse environment is updated and has the Geronimo plugin. If you do not know how to do that, follow the instructions found at the [Geronimo website|http://geronimo.apache.org/geronimo-eclipse-plugin-installation-instructions.html].
+
+# Create a new Java project in Eclipse called, *"OpenJPATutorial"*.
+#* From the menu, select: *File->New->Enterprise Application Project*. (If *Enterprise Application Project* is not available as an option, select *Project* and then choose *Enterprise       Application Project* from the list. Then click on the *Next* button).
+When the New Project settings dialog appears, use the following settings:
+\\
+\\  !image001.jpg!\\
+\\
+# Under the *Target Runtime* section, select *Apache Geronimo v2.2*.
+#* If you do not already have Geronimo setup in Eclipse then you will have to do so now. Click on the *New...* button.
+#* If Apache Geronimo v2.2 does not appear in the list under *Apache*, click the *Download additional server adapters* link at the top right of the dialog. If the adapter does not appear in that list then follow the [directions from the Geronimo site|http://geronimo.apache.org/geronimo-eclipse-plugin-installation-instructions.html].
+\\
+\\  !image002.jpg!\\
+\\
+#* Select *Apache->Apache Geronimo v2.2*
+#* Click *Next*.
+\\
+\\  !image003.jpg!\\
+\\
+#* Set the JRE to *jre6* if it is not already set.
+#* Browse for the install directory of Geronimo v2.2 on your system.
+#* Click *Finish*. You should see the following:
+\\
+\\  !image001.jpg!\\
+\\
+# Now, click the *Next* button. You should see this:
+\\
+\\  !image004.jpg!\\
+\\
+#* Check the *Generate application.xml deployment descriptor* option.
+#* Click the *New Module...* button:
+\\
+\\  !image005.jpg!\\
+\\
+#* De-select *Create default modules*.
+#* Select       the *Web* option.
+#* Click *Next*.
+\\
+\\  !image006.jpg!\\
+\\
+#* Click *Finish*. You will see the following:
+\\
+\\  !image007.jpg!\\
+\\
+#* Click *Finish*.
+\\
+\\
+# Now, your Project Explorer should look like this (partially expanded):
+\\
+\\  !image008.jpg!\\
+\\
+#* If you double-click on the *Deployment Descriptor: OpenJPATutorial*, you should see the application.xml open:
+\\
+\\  !image009.jpg!\\
+\\
+# Now we will bring in the sample code. The easiest way to add the sample code is      to find the source provided with this tutorial and copy it to the src      folder under the *OpenJPATutorialWeb* folder in your project directory in Windows Explorer:
+\\
+\\  !image010.jpg!\\
+\\
+#* Now go back to Eclipse. Right-click on the *OpenJPATutorialWeb* folder in the Project Explorer view and select *Refresh,* or press the *F5* key on your keyboard. Now you will see this:
+\\
+\\  !image011.jpg!\\
+\\
+Notice that all the source files compile without error. That is because Geronimo comes with OpenJPA v1.1 built in.
+\\
+\\
+# {color:black}Now copy the index.jsp file from the tutorial into the Web Content directory under the Project directory in Windows Explorer:{color}\\
+\\  !image012.jpg!\\
+\\
+#* {color:black}Got to the Project Explorer and refresh the project. You should see this:{color}\\
+\\
+\\  !image013.jpg!\\
+\\
+
+h2. Running and Configuring Geronimo and Derby
+
+Geronimo has no installer and runs from the command line. Here are some quick instructions to get you started.
+# In Windows, open a command prompt and navigate to the Geronimo *bin* directory.
+# Type the command:
+{code}
+start-server
+{code}
+\\
+\\  !image014.jpg!\\
+\\
+Press the *Enter* key.
+\\
+\\  !image015.jpg!\\
+\\
+# Open a web browser and go to the address:
+\\
+\\
+[http://localhost:8080/console|http://localhost:8080/console]\\
+\\
+\\  !image016.jpg!\\
+\\
+\\
+The default password is _manager_.
+\\
+\\
+# You will come to the Welcome page. On the left menu, at the bottom, find the      section for the Embedded DB. This is the Derby database control page.
+\\
+\\
+\\  !image017.jpg!\\
+\\
+# {color:black}Click on the link for the{color} {color:black}{*}DB Manager{*}{color}{color:black}.{color}
+# You will see two sections: *DB Viewer* and *Run SQL*.
+# In the Run SQL section, in the text field labeled Create DB, type in *StoreSystem*. This is the name of the database that the OpenJPA sample is configured to transact.
+\\
+\\
+\\  !image018.jpg!\\
+\\
+# {color:black}Click on the{color} {color:black}{*}Create{*}{color} {color:black}button. You should now see the{color} {color:black}{*}StoreSystem{*}{color} {color:black}database appear in the{color}{color:black}{*}DB Viewer{*}{color} {color:black}section{color}.
+\\
+\\
+\\  !image019.jpg!\\
+\\
+# {color:black}We are now ready to deploy and run the sample code.{color}
+
+\\
+
+h2. Running and Deploying the Sample Code in Geronimo
+
+The sample code provided with this tutorial is working code. It is a simple inventory database program that shows items and categories. But even this simple example requires the ability to add, edit and delete entries. It requires the ability to sort and filter database queries and it requires the identification of the relationship of the items to the categories. In this example, the relationship is *one to many*. Knowing that relationship is important to how the code is written. Before we analyze the code and OpenJPA, we will first deploy the sample and see it work. To deploy the sample code follow these instructions:
+# In Eclipse, in the Project Explorer, right click on the OpenJPATutorial project and select: *Export->EAR file*.
+\\
+\\
+\\  !image020.jpg!\\
+\\
+# In the      Ear Export dialog, find a convenient place to put the exported EAR file.
+# Check      the *Overwrite existing file* check box.
+\\
+\\
+\\  !image021.jpg!\\
+\\
+# Click *Finish*.
+# Go out to Windows Explorer and copy the file *TutorialDeploymentPlan.xml* to the location of the exported ear. This is the deployment plan that Geronimo requires to deploy the application.
+\\
+\\
+\\  !image022.jpg!\\
+\\
+# Open the Geronimo console in a web browser and log in.
+# In the Console Navigation menu on the left, under the *Applications* section, click on the *Deploy New* item.
+# Browse to the location of the exported EAR file and the deployment plan XML file.
+\\
+\\
+\\  !image023.jpg!\\
+\\
+# Click on the *Install* button. You should see this.
+\\
+\\
+\\  !image024.jpg!\\
+\\
+# In the Console Navigation menu on the left, under the *Applications* section, click on the *Web App WARs* item.
+#* Notice that the OpenJPATutorial application is now listed and that there is a clickable link under the URL heading:
+\\
+\\
+\\  !image025.jpg!\\
+\\
+# Click on the link *OpenJPATutorial* and now you should see this:
+\\
+\\
+\\  !image026.jpg!\\
+\\
+Each of the buttons will execute OpenJPA code. The lists are filled by running queries on the Derby database.
+## Add a some categories and items
+## Make sure you test each of the buttons and see the results.
+\\
+
+h1. Examining the Sample Code
+
+Now that everything is set up and you have seen it work, let's look more closely at the parts of the code that use OpenJPA. The JSP code is just a prop to explore OpenJPA and we will not examine it.The sample application source code is provided for this tutorial and you may run as-is with no customizations. However, you have the option of reproducing the code manually using the following explanations. Whichever method you choose, locate the code that corresponds to explanations as you follow along.
+* Java code: This tutorial comes with the following java source files:
+** index.jsp: This is the interface code only. It does call into other classes but it does not use any OpenJPA code directly.
+** InventoryEntityBroker.java:&nbsp;This class contains methods that encapsulate the OpenJPA handling code. It is provided as a way to separate OpenJPA functionality from the web interface.
+** InventoryItem.java: This is an OpenJPA Entity class file. This file is an example of a simple OpenJPA Entity with a relationship.
+** InventoryCategory.java: This is an OpenJPA Entity class file. This file is an example of a simple OpenJPA Entity with a relationship.
+* Persistence code: Each entity concept that would be a database table will be its own class. In this case, the tables are called "InventoryItem" and "InventoryCategory". Annotations in the Java file will associate the properties with the database columns. The annotation, {color:#646464}@Column{color}, maps the property name to the column name for synchronization with the database. If the table corresponding tables do not exist, OpenJPA can use these annotations to create the tables' schema dynamically based on the property type and length.
+
+{code:title=InventoryCategory.java|borderStyle=solid}
+package tutorial;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Version;
+
+@Entity
+public class InventoryCategory
+{
+   private int version;
+   private int id;
+
+   private String categoryName;
+   private String categoryDescription;
+
+   List<InventoryItem> items;
+
+   public InventoryCategory(){}
+
+   @Column(name = "categoryName")
+   public String getCategoryName()
+   {
+      return categoryName;
+   }
+
+   public void setCategoryName(String name)
+   {
+      this.categoryName = name;
+   }
+
+   @Column(name = "itemDescription")
+   public String getCategoryDescription()
+   {
+      return categoryDescription;
+   }
+
+   public void setCategoryDescription(String description)
+   {
+      this.categoryDescription = description;
+   }
+
+   @Version
+   @Column(name = "version_field")
+   // not required
+   public int getVersion()
+   {
+       return version;
+   }
+
+   public void setVersion(int version)
+   {
+      this.version = version;
+   }
+
+   @Id
+   @GeneratedValue(strategy = GenerationType.AUTO)
+   public int getId()
+   {
+      return id;
+   }
+
+   public void setId(int id)
+   {
+      this.id = id;
+   }
+
+   @OneToMany(targetEntity=tutorial.InventoryItem.class,
+      cascade=CascadeType.ALL,
+      mappedBy="category")
+   public List<InventoryItem> getItems()
+   {
+      return items;
+   }
+
+   public void setItems(List<InventoryItem> items)
+   {
+      this.items = items;
+   }
+
+   public void addItem(InventoryItem item)
+   {
+      this.items.add(item);
+   }
+}
+{code}
+\\
+{info:title=Note}
+In this example, the property annotations ( {color:#646464}@Column{color},{color:#646464}@Version{color}, and {color:#646464}@Id{color}) are placed on the getter methods. They can alternatively be placed on the property declarations. For more information on these annotations and to see what other annotations are in OpenJPA, see the [Apache OpenJPA 2.0 User's Guide: Chapter 5|http://openjpa.apache.org/builds/latest/docs/manual/jpa_overview_meta.html]
+* The annotated class and property declarations are all that are required.
+* The {color:#646464}*@Id{*}{color} annotation is needed as the unique identifier (primary key) for each record.
+* The {color:#646464}*@Version{*}{color} annotation is common practice. It ensures data integrity during merges and acts as an optimistic concurrency control.
+* Every property must have both a getter and a setter and the standard case convention must be observed.
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;°&nbsp; Correct: {color:#7f0055}{*}public{*}{color} {color:#7f0055}{*}void{*}{color} {color:black}setCategoryName(String name){color}
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;°&nbsp; Incorrect: {color:#7f0055}{*}public{*}{color} {color:#7f0055}{*}void{*}{color} {color:black}setcategoryname(String name){color}
+{info}
+\\
+* Persistence.xml: JPA requires the use of a XML file called the "persistence.xml" that describes how to access the data. The XML file must be created in the META-INF directory. The META-INF directory containing the persistence.xml must be located with the source files.
+\\
+\\
+\\  !image027.jpg!\\
+\\
+In the following example, the file only requires a few fields.
+\\
+\\
+{code:xml|title=META-INF/persistence.xml|borderStyle=solid}
+<persistence xmlns=http://java.sun.com/xml/ns/persistence
+    xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
+    version="1.0">
+    <persistence-unit name="InventorySystem" transaction-type="RESOURCE_LOCAL">
+        <class>tutorial.InventoryItem</class>
+        <class>tutorial.InventoryCategory</class>
+        <properties>
+            <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema"/>
+            <property name="openjpa.ConnectionURL" value="jdbc:derby://localhost:1527/StoreSystem"/>
+            <property name="openjpa.ConnectionDriverName" value="org.apache.derby.jdbc.ClientDriver"/>
+        </properties>
+    </persistence-unit>
+</persistence>
+{code}
+\\
+\\
+* The following elements are specific to this tutorial:
+** *persistence-unit*: the *name* is the table name to bind. In this case it is        'person'.
+** *class*: the java class that is bound to the table 'person'.
+** *property:* openjpa.jdbc.SynchronizeMappings: This tells OpenJPA to automatically create the table with the class definition if a table does not already exist.
+** *property:* openjpa.ConnectionURL: The URL of the database connection.
+** *property:* openjpa.ConnectionDriverName: the class name of the JDBC driver for Derby. This must be available via the classpath. In this tutorial, the driver is built into Geronimo so no extra actions are needed.
+* A complete explanation of the persistence.xml is in the [Apache OpenJPAV2.0 user's Guide: Chapter 6|http://openjpa.apache.org/builds/latest/docs/manual/jpa_overview_persistence.html]\\
+\\
+* Create the Entity Manager. In the provided code, the EntityManager is a property of the InventoryEntityBroker class. The Entity Manager controls the interaction with the database. You must use the Entity Manager to start or access transactions or to send queries.
+** The following code must be added before using any of the persistence APIs (If you are using the provided sample code, this is already included):
+{code:java}
+EntityManagerFactory factory = 	Persistence.createEntityManagerFactory("InventorySystem",
+      System.getProperties());
+
+EntityManager em = factory.createEntityManager();
+{code}
+** Note that the name, {color:#2a00ff}"InventorySystem"{color}, is the same one identified in the persistence.xml.
+** This code can be placed just before a query or transaction or they can be class properties.
+** Regardless of the scope, the EntityManager and the EntityManagerFactory should be closed when they are no longer needed:
+\\
+{code:java}
+...
+em.close();
+factory.close();
+...
+{code}
+** The EntityManagerFactory and EntityManager full descriptions are in the following OpenJPA documentation:
+*** EntityManagerFactory: [http://openjpa.apache.org/builds/latest/docs/manual/jpa_overview_emfactory.html|http://openjpa.apache.org/builds/latest/docs/manual/jpa_overview_emfactory.html]
+*** EntityManager: [http://openjpa.apache.org/builds/latest/docs/manual/jpa_overview_em.html|http://openjpa.apache.org/builds/latest/docs/manual/jpa_overview_em.html]
+
+* DB interface class. In this example, the InventoryEntityBroker class contains all the OpenJPA database interaction code. This is not required but it is a good idea for keeping the functionality componentized. For example, if you want to pull all of the records from the InventoryItem table, the code would look like this:
+\\
+{code:java|title=InventoryEntityBroker.java}
+...
+List<Person> getAllItems()
+{
+     Query q = em.createQuery("SELECT item FROM InventoryItem item");
+
+     return (List<InventoryItem>)q.getResultList();
+}
+...
+{code}
+{code:java|title=index.jsp}
+...
+List<InventoryItem> itemList = getAllItems();
+...
+{code}
+** All of the specific APIs are described in the OpenJPA [javadoc|http:/openjpa.apache.org/builds/latest/docs/javadoc/index.html]
+** Notice that the Query is not standard SQL. It is actually JPQL, which is a specialized form of query language specifically designed for JPA.
+**- In the JPQL statement, "{color:#2a00ff}SELECT item FROM InventoryItem item{color}", notice that InventoryItem has the same case as the class InventoryItem.
+**- JPQL uses java objects in the query and not the database table names. The statement identifies the variable for InventoryItem as "{color:#2a00ff}item{color}".
+**- JPQL provides an object oriented query language that is independent of the database being queried.&nbsp; So, regardless of which database being used, the JPQL does not change.&nbsp; The JPA runtime takes care of doing the translation from the object world to the desired relational database.
+**- For more information on JPQL, check out this [Java Persistence Querly Language reference.|http://java.sun.com/javaee/5/docs/tutorial/backup/update3/doc/QueryLanguage.html]\\
+\\
+* Also in the InventoryEntityBroker is code to add entries the database tables. Since you did not create a table for InventoryItem in the StoreSystem database in Derby, OpenJPA 2.0 will create the table the first time an _"add"_ is attempted.
+** Consider the following code:
+{code:java|title=InventoryEntityBroker}
+...
+void addItem(String name, String description, float price, int categoryID)
+{
+    InventoryItem item = new InventoryItem();
+    item.setName(name);
+    item.setDescription(description);
+    ...
+
+    em.persist(item);
+}
+...
+{code}
+You can then call the addItem() method in another part of the code. The EntityManager.persist() method will throw an exception if a transaction has not been started. The transaction must be committed by calling the Transaction.commit() method after all updates have been applied or else the changes will not be saved to the database:
+{code}
+...
+em.getTransaction().begin();
+
+addItem(...);
+
+em.getTransaction().commit();
+...
+{code}
+*** When this is executed the first time it will use the annotations to create the Person table, then OpenJPA 2.0 will populate it with the provided data.
+*** Note the use of the getTransaction() method to start an update and then to commit it. The concept is the same as in any database transaction processing.
+*** Also note that while the getAllItems() function requires a JPQL SELECT query, the update type actions have APIs.
+*** Take a look in the InventoryEntityBroker code at the addItem(), updateItem() and deleteItem() functions and note the simplicity of these operations.
+
+* An important aspect of relational databases is, of course, the relationships. The basic relationship types are: one to many, many to one, and many to many. OpenJPA provides annotations to identify the related fields.
+Open the source file, InventoryCategory.java in Eclipse and find the following code:
+{code:java|title=InventoryCategory.java}
+...
+@OneToMany(targetEntity=tutorial.InventoryItem.class,
+   cascade=CascadeType.ALL,
+   mappedBy="category")
+public List<InventoryItem> getItems()
+{
+    return items;
+}
+...
+{code}
+** The annotation {color:#646464}@OneToMany{color} identifies that:
+*** This object has a one-to-many relationship with targetEntity=tutorial.InventoryItem.class. Meaning that one InventoryCategory can have many InventoryItems associated with it.
+*** {color:black}The property of InventoryItem that specifies the InventoryCategory it is associated with is mappedBy="category". In other words, InventoryItem has a class property of type InventoryCategory named "category".{color}\\  {color:black}Now open the source file, InventoryItem.java and find the following code:{color}
+{code:java|title=InventoryItem.java}
+...
+@ManyToOne
+@JoinColumn(name="CAT_ID", nullable=false)
+public InventoryCategory getCategory()
+{
+    return category;
+}
+...
+{code}
+*** {color:black}The annotation @ManyToOne identifies that:{color}
+*** This object has a many-to-one relationship with the InventoryCategory object. Meaning that there many InventoryItems can reference the same InventoryCategory
+** The annotation {color:#646464}@JoinColumn{color} identifies that:
+*** The column in the database table that holds the InventoryCategory reference by the attribute: {color:black}name={color}{color:#2a00ff}"CAT_ID"{color}.
+\\
+{info:title=Remember}
+These annotations contribute to the creation of the tables and the relationships. It is important to put as much thought into how these objects relate to each other as you would if you were designing the database tables because you are designing the database tables.
+You can see more about the relationship annotations at the Apache OpenJPA site. The&nbsp; [documentation is here|http://openjpa.apache.org/builds/latest/docs/manual/jpa_overview_meta_field.html].
+{info}
+
+h1. Summary
+
+This was a very basic example of how to use OpenJPA with Geronimo and Derby. However, many applications that require database persistence do not use much more than the basic functionality demonstrated in this tutorial. The purpose of this was to be a primer. Aside from the setup of the server and database, we went through the creation of a persistence.xml file, the basics of the OpenJPA Entity, and EntityManager and some of the functionality.
+*{+}Exercises{+}*
+Using this sample code as a base, try to do some of the following:
+* Add additional fields to the InventoryItem Entity.
+* Create a Customer Entity and establish a one-to-many relationship with the InventoryItems as one customer having purchased many items.
+* Since several customers could have purchased the same items and an item could have been purchased by many customers, use the documentation to create a many-to-many relationship using @ManyToMany*.
+
+~\*To make these changes you may have to delete the existing database tables so that they can recreated with the new relationship fields.~
+
+\\
+
+h1. References
+
+* *Java J2SE 1.6*
+** [Download|https://cds.sun.com/is-bin/INTERSHOP.enfinity/WFS/CDS-CDS_Developer-Site/en_US/-/USD/ViewProductDetail-Start?ProductRef=jdk-6u16-oth-JPR@CDS-CDS_Developer]
+*&nbsp;*
+* *Apache Sources*
+** *Geronimo*
+**- [Geronimo Homepage|http://geronimo.apache.org/]
+**- [Geronimo V2.2 Server Documentation|http://cwiki.apache.org/GMOxDOC22/documentation.html]
+**- [Geronimo V2.2 Server download|http://www.apache.org/dyn/closer.cgi/geronimo/2.2/geronimo-tomcat6-javaee5-2.2-bin.zip]
+** *JPA*
+**- [Apache OpenJPA home page|http://openjpa.apache.org/]
+**- [Apache OpenJPA download|http://openjpa.apache.org/downloads.html]
+**- [Apache OpenJPA        documentation|http://openjpa.apache.org/documentation.html]&nbsp;&nbsp;
+
+* *Annotations*
+** [Documentation       for Java Annotations|http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html]
+* *JPQL*
+** [A       reference for JPQL|http://java.sun.com/javaee/5/docs/tutorial/backup/update3/doc/QueryLanguage.html]
+* *Blogs*
+** [Discussion       on The Server Side|http://www.theserverside.com/news/thread.tss?thread_id=58343]
+** [Websphere & OpenJPA blog on       blogspot|http://bit.ly/WASJPAblog]
+** [JPA Blog on developerWorks|http://bit.ly/JPATutApachedwBlog]
+* *Implementation Sites*
+** [IBM WebSphere Application Server V7 Java Persistence API (JPA) 2.0 Open Beta|http://bit.ly/BetaSiteApache]
\ No newline at end of file



Mime
View raw message