Aug 132010
 

One more error: In a comment to my Eclipse / GlassFish / Java EE 6 tutorial, FMora said:

One detail – if you annotate a constraint with @NotNull and then insert a null value via SoapUI, one gets a NPE instead of a constraint violation.

Oh dear, that’s so true and it is a typical case of untested code. Have you ever seen untested code that did not break? I haven’t :)

The problem was in the ValidationInterceptor in that line, where I took the invalid value and called “toString()” on it.

The tutorial is already updated, and from now on the tutorial begins with a version number. The current version is version 1.2, last updated August 13, 2010 – 17:06. The ZIP file with the sources was updated as well.

For your convenience, here is the updated ValidationInterceptor:

package com.manessinger.cookbook.util;
 
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.groups.Default;
 
import com.manessinger.cookbook.exception.ConstraintProperty;
import com.manessinger.cookbook.exception.ValidationException;
import com.manessinger.cookbook.exception.ViolationDetail;
 
@Interceptor
public class ValidationInterceptor {
 
    // the factory is expensive but thread-safe
    private static ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
 
    @AroundInvoke
    public Object intercept(InvocationContext ctx) throws Exception {
        Validator v = factory.getValidator();
        // for all parameters
        for (Object p : ctx.getParameters()) {
            // validate parameter
            Set<ConstraintViolation<Object>> violations = v.validate(p, Default.class);
            if (!violations.isEmpty()) {
                // validation failed, gather details and throw an exception
                List<ViolationDetail> details = new ArrayList<ViolationDetail>();
                for (ConstraintViolation<Object> violation : violations) {
                    ViolationDetail d = new ViolationDetail();
                    // path to violated constraint
                    d.setAttributedItem(violation.getPropertyPath().toString());
                    // what type of constraint, e.g. "Min" or "Pattern"
                    d.setConstraintName(
                        violation.getConstraintDescriptor()
                            .getAnnotation().annotationType().getSimpleName()
                    );
                    // construct list of constraint properties
                    Map<String, Object> violationAttributes 
                        = violation.getConstraintDescriptor().getAttributes();
                    List<ConstraintProperty> properties = new ArrayList<ConstraintProperty>();
                    for (String propertyName : violationAttributes.keySet()) {
                        if (propertyName.matches("^(message|payload|groups|flags)$")) {
                            // skip unwanted property
                            continue;
                        }
                        ConstraintProperty a = new ConstraintProperty();
                        a.setName(propertyName);
                        a.setValue(violationAttributes.get(propertyName).toString());
                        properties.add(a);
                    }
                    d.setConstraintProperties(properties);
                    // the value that violated the constraint
                    Object invalidValue = violation.getInvalidValue();
                    d.setInvalidItemValue((invalidValue != null ? 
                                           invalidValue.toString() : "null"));
 
                    details.add(d);
                }
                throw new ValidationException(details);
            }
        }
        return ctx.proceed();
    }
}
Apr 062010
 

Version 1.4, last updated May 23, 2011 – 11:10

The content of this tutorial is still relevant, but you may also consider my new open source Azzyzt JEE Tools, a set of Eclipse plugins that greatly simplify the process of creating a Java Enterprise application using the patterns outlined in this tutorial. See the Azzyzt JEE Tools home page and especially the tutorial “Using Azzyzt JEE Tools“.

In “4 – Equipment” I have committed myself to using Eclipse and the Java Enterprise Edition as my tools, while in “5 – Patterns And Languages” I’ve declared my high-level goals for implementing a next step of design pattern-based tools. Now, for a deeper understanding of design patterns, you first have to use them. This post in the form of a tutorial shows some very basic project setups using Eclipse and GlassFish.

I am no expert in this field, some important things may be missing, so just take the following as a set of things that work for me.

As I am not immune to learning, and as I am going the use these things a lot, it is inevitable that my understanding of certain aspects will change. I suppose that means, I will have to make changes to this post whenever it happens. If I ever do so, I will post a short notice.

Applicability

This is a tutorial about using Eclipse and the GlassFish v3 Java application server to implement Java EE 6 applications. I will show how to use different Eclipse project types for different purposes, will show how to do manual tests and how to implement automatic unit tests. We will not create a complete application, but more a vertical slice through an application. The idea is to just touch all relevant areas, not to finish a project.

The tutorial assumes the existence of a relational database, and it concentrates on the Java application used as a backend. Using JSF or another server-based GUI framework is definitely out of scope.

Where’s the beef?

At an equivalent of approximately 80 printed pages, the full tutorial is much too long for a regular blog post. It would break the size limit of feeds syndicated via Google’s Feedburner server. In fact it did. I had no choice but to move the text to a separate page. On the other hand, that’s quite OK, I want my tutorials (this won’t be the last) to be available as pages from a tutorial menu anyway.

Unfortunately I noticed the feed problems only after I had already published the URL of this post a few times. Thus, if you arrive here from a link, please go on to the actual page containing the full Eclipse / GlassFish / Java EE 6 tutorial. Sorry for the inconvenience.