January 30, 2010

Maven Reporting with Cobertura, Dashboard, Change Report, FindBugs and PMD

I have been using maven coberture plugin before but it has one unimplemented function, aggregate cobertura report from multiple module. This can be solved by sonar and dashboard maven plugin, but Sonar requires that is run on a server, i.e. that you have a continuous integration server, but in some cases you have not got there and still is building your application locally than you can use the maven Dashboard plugin.


The parent pom.xml

<?xml version="1.0" encoding="UTF-8" ?>
<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/maven-v4_0_0.xsd">

 <modelVersion>4.0.0</modelVersion>
 <groupId>se.msc.examples</groupId>
 <artifactId>reporting-parent</artifactId>
 <version>0.1-SNAPSHOT</version>
 <packaging>pom</packaging>
 <url>http://www.msc.se/examples</url>
    <organization>
        <name>Msc.se</name>
    </organization>
    <developers>
     <developer>
      <name>Magnus K Karlsson</name>
      <email>magnus.k.karlsson@msc.se</email>
     </developer>
    </developers>
    
 <modules>
  <module>reporting-demo</module>
  <module>reporting-core</module>
 </modules>
 
 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>3.8.2</version>
   <scope>test</scope>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.0.2</version>
    <configuration>
     <source>1.5</source>
     <target>1.5</target>
     <encoding>UTF-8</encoding>
    </configuration>
   </plugin>
  </plugins>
 </build>

 <reporting>
  <plugins>
   <!-- Generate 'Changes Report' from src/changes/changes.xml -->
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-changes-plugin</artifactId>
    <version>2.3</version>
    <reportSets>
     <reportSet>
      <reports>
       <report>changes-report</report>
      </reports>
     </reportSet>
    </reportSets>
   </plugin>

   <!-- JXR - Source code as HTML --> 
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jxr-plugin</artifactId>
    <version>2.1</version>
    <configuration>
     <!-- Enable aggregation for multimodule projects. -->
     <aggregate>true</aggregate>
     <inputEncoding>utf-8</inputEncoding>
     <outputEncoding>utf-8</outputEncoding>
    </configuration>
   </plugin>

   <!-- JavaDoc - API-documentation -->
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-javadoc-plugin</artifactId>
    <version>2.6.1</version> 
    <configuration>
     <!-- Enable aggregation for multimodule projects. -->
     <aggregate>true</aggregate>
                    <show>public</show>
                    <charset>utf-8</charset>
                    <docencoding>utf-8</docencoding>
                    <encoding>utf-8</encoding>     
    </configuration>
   </plugin>

   <!-- Surefire - JUnit testing-->
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-report-plugin</artifactId>
    <version>2.5</version>
    <configuration>
     <!-- Required to properly link JXR -->
     <xrefLocation>${project.reporting.outputDirectory}/../xref-test</xrefLocation>
    </configuration>
   </plugin>

   <!-- JDepend - Package dependencies -->
   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>jdepend-maven-plugin</artifactId>
    <version>2.0-beta-2</version>
   </plugin>

   <!-- Cobertura - Test code coverage report. -->
   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>cobertura-maven-plugin</artifactId>
    <version>2.3</version>
   </plugin>
   
   <!-- PMD - Generate PMD and CPD reports using the PMD code analysis tool. -->
            <plugin>
             <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-pmd-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                 <linkXref>true</linkXref>
                 <!-- Required to properly link JXR -->
     <xrefLocation>${project.reporting.outputDirectory}/../xref-test</xrefLocation>
                 <sourceEncoding>utf-8</sourceEncoding>
                    <aggregate>true</aggregate>
                    <targetJdk>1.5</targetJdk>
                </configuration>
            </plugin>
            
   <!-- FindBugs - Finds potential bugs in your source code -->
   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>findbugs-maven-plugin</artifactId>
    <version>2.3</version>
    <configuration>
     <xmlOutput>true</xmlOutput>
     <effort>Max</effort>
    </configuration>
   </plugin>

   <!-- JavaNCSS - Source code metrics -->
   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>javancss-maven-plugin</artifactId>
    <version>2.0</version>
   </plugin>

   <!-- TagList - Creates a list with TODO:s etc -->
   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>taglist-maven-plugin</artifactId>
    <version>2.4</version>
                <configuration>
                    <aggregate>true</aggregate>
                    <tags>
                        <tag>TODO</tag>
                        <tag>FIXME</tag>
                        <tag>@todo</tag>
                    </tags>
                </configuration>    
   </plugin>

   <!-- The dashboard plugin should be specified as the last report. -->
   <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>dashboard-maven-plugin</artifactId>
    <version>1.0.0-beta-1</version>
   </plugin>

  </plugins>
 </reporting>

</project>



The jar module pom.xml

<?xml version="1.0" encoding="UTF-8" ?>
<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/maven-v4_0_0.xsd">

 <parent>
  <groupid>se.msc.examples</groupId>
  <artifactid>reporting-parent</artifactId>
  <version>0.1-SNAPSHOT</version>
 </parent>
 <modelversion>4.0.0</modelVersion>
 <artifactid>reporting-demo</artifactId>
 <packaging>jar</packaging>
 <name>Demo Reporting</name>

 <reporting>
  <!-- Needed in order to generate the dashboard report properly. -->
  <outputdirectory>
            ${basedir}/../target/site/${project.artifactId}
        </outputDirectory>
 </reporting>

</project>

December 14, 2009

How to handle XML Schema Version?

Use the Schema verison attribute.
Pros:
  • Simple
Cons:
  • No XML Schema enforcement when stepping version and version number is concealed for user.
Recommendation:
  • Do no use.

Change the Schema location and keep the namespace.
Pros:
  • Good för maintaining backward compability. No depending XML files needs to be altered, simply upgrade implementing jar.
Cons:
  • Cannot tell from the XML file which implementing jar version is used.
Recommendation:
  • Use this technique to handle minor version upgrade.

Example:
http://camel.apache.org/schema/spring/camel-spring-1.6.X.xsd, in version 1.6.0-1.6.3 is the same targetNamespace used.

Change the Schema location and the namespace.
Pros:
  • Forces the user to upgrade the client code, when stepping version. Hard versioning control, no chanse to make misstake.
Cons:
  • No seamless upgrade. Upgrade will cost.
Recommendation:
  • Use this when stepping major version.

For you using JAXB, is it a good reminder that the namspace versionnumber is direclty reflected in the package name. So when uppgrading and if the depending generated code has changed namespace, i.e. package name will the depending code not compile. This can be a advantage since it will directly be apparent where in your code you have the dependencies.

XML Schema Design Pattern - Handling Versioning and Reuse

In my last project I have been working with service orientated integration and ESB, in such an architecture the domain model is represented with a canonical model of a XML schema. There several way you can design your schema which I will describe bellow, but what is more imported is the implication it has on:
  • Level of possibility to reuse your canonical model in different service.
  • Level of possibility to handle different version of same service.
  • Level of possibility to split your canonical data model into bit of pieces and process them in parallel.
Before laying out the different patterns I will explain different definition that I will use when evaluating the different patterns

Definition:
Root element – the first element a XML must contain. If a schema contains several root element it is possible to slice the XML document into several new XML document.

Global element – the elements that directly comes after the root element, possibly elements are 'element', 'complexType' and 'simpleType'.

Local element – nested element inside global element.

Russian Doll Example

Pros:
  • One root element, good for encapsulation.
  • All elements are local and encapsulated.
Cons:
  • No reuse of elements.
  • Easier to get started with.

Example Book-RussianDoll-v1.0.0.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="http://ns.msc.se/examples/book-russiandoll/v1_0_0"
     xmlns:russ="http://ns.msc.se/examples/book-russiandoll/v1_0_0" 
     elementFormDefault="qualified">
 
 <xs:element name="book">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="Title" type="xs:string" />
    <xs:choice>
     <xs:element name="AuthorList" minOccurs="0" maxOccurs="unbounded">
      <xs:complexType>
       <xs:sequence>
        <xs:element name="Author">
         <xs:complexType>
          <xs:sequence>
           <xs:element name="givenName" type="xs:string" />
          </xs:sequence>
         </xs:complexType> 
        </xs:element>
       </xs:sequence>
      </xs:complexType>
     </xs:element>
    </xs:choice>
   </xs:sequence>
  </xs:complexType>
 </xs:element> 
 
</xs:schema>

Salami Slide
Pros
  • Many root elements, the XML file can be sliced into numerous ways.
  • All elements are global, which allows reuse in other Schemas.

Cons
  • Does not encapsulate and hide the schema.
  • Usage of namespaces are almost a most, which makes usage more complex.

Example Book-SalamiSlice-v1.0.0.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="http://ns.msc.se/examples/book-salamislice/v1_0_0"
     xmlns:salv1_0_0="http://ns.msc.se/examples/book-salamislice/v1_0_0" 
     elementFormDefault="qualified">

 <xs:element name="book">
  <xs:complexType>
   <xs:sequence>
    <xs:element ref="salv1_0_0:Title" />
    <xs:element ref="salv1_0_0:AuthorList" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>

 <xs:element name="Title" type="xs:string" />

 <xs:element name="AuthorList">
  <xs:complexType>
   <xs:sequence>
    <xs:element ref="salv1_0_0:Author" minOccurs="0" maxOccurs="unbounded" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>

 <xs:element name="Author">
  <xs:complexType>
   <xs:sequence>
    <xs:element ref="salv1_0_0:GivenName" />
    <xs:element ref="salv1_0_0:Surname" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>
 
 <xs:element name="GivenName" type="xs:string" />
 
 <xs:element name="Surname" type="xs:string" />
 
</xs:schema>

When generating code via JAXB, wee can see that several classes are annotated with the @XmlRootElement. This says that we have several possible root element.

In the next example we show how to handle version and extending previous schema version.

Example Book-SalamiSlice-v1.0.1.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="http://ns.msc.se/examples/book-salamislice/v1_0_1"
     xmlns:salv1_0_0="http://ns.msc.se/examples/book-salamislice/v1_0_0"
     xmlns:salv1_0_1="http://ns.msc.se/examples/book-salamislice/v1_0_1" 
     elementFormDefault="qualified">
 
 <xs:import namespace="http://ns.msc.se/examples/book-salamislice/v1_0_0" schemaLocation="Book-SalamiSlice-v1.0.0.xsd" />

 <xs:element name="book">
  <xs:complexType>
   <xs:sequence>
    <xs:element ref="salv1_0_1:Title" />
    <xs:element ref="salv1_0_1:Category" />
    <xs:element ref="salv1_0_0:AuthorList" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>
 
 <xs:element name="Title">
  <xs:simpleType>
   <xs:restriction base="xs:string">
    <xs:minLength value="3" />
   </xs:restriction>
  </xs:simpleType>
 </xs:element>
 
 <xs:element name="Category" type="xs:string" />
 
</xs:schema>

Venetian Blind

Pros:
  • Only one root element, good for encapsulation.
  • All element are global, which allows reuse in other Schemas.
Cons:
  • Usage of namespaces are almost a most, which makes usage more complex.

Example Book-VenetianBlind-v1.0.0.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="http://ns.msc.se/examples/book-venetianblind/v1_0_0"
     xmlns:ven="http://ns.msc.se/examples/book-venetianblind/v1_0_0" 
     elementFormDefault="qualified">

 <xs:element name="Book">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="Title" type="ven:TitleType" />
    <xs:element name="AuthorList" type="ven:AuthorListType" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>
 
 <xs:simpleType name="TitleType">
  <xs:restriction base="xs:string">
  </xs:restriction>
 </xs:simpleType>

 <xs:complexType name="AuthorListType">
  <xs:sequence>
   <xs:element name="Author" type="ven:AuthorType" minOccurs="0" maxOccurs="unbounded" />
  </xs:sequence>
 </xs:complexType>
 
 <xs:complexType name="AuthorType">
  <xs:sequence>
   <xs:element name="GivenName" type="ven:GivenNameType" />
   <xs:element name="Surname" type="ven:SurnameType" />
  </xs:sequence>
 </xs:complexType>
 
 <xs:simpleType name="GivenNameType">
  <xs:restriction base="xs:string">
  </xs:restriction>
 </xs:simpleType>

 <xs:simpleType name="SurnameType">
  <xs:restriction base="xs:string">
  </xs:restriction>
 </xs:simpleType>
 
</xs:schema>

Example Book-VenetianBlind-v1.0.1.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
     targetNamespace="http://ns.msc.se/examples/book-venetianblind/v1_0_1"
     xmlns:ven1_0_0="http://ns.msc.se/examples/book-venetianblind/v1_0_0"
     xmlns:ven1_0_1="http://ns.msc.se/examples/book-venetianblind/v1_0_1" 
     elementFormDefault="qualified">

 <xs:import namespace="http://ns.msc.se/examples/book-venetianblind/v1_0_0" schemaLocation="Book-VenetianBlind-v1.0.0.xsd" />

 <xs:element name="Book">
  <xs:complexType>
   <xs:sequence>
    <xs:element name="Title" type="ven1_0_1:TitleType" nillable="true" />
    <xs:element name="Category" type="ven1_0_1:CategoryType" nillable="true" />
    <xs:element name="AuthorList" type="ven1_0_0:AuthorListType" />
   </xs:sequence>
  </xs:complexType>
 </xs:element>
 
 <xs:simpleType name="TitleType">
  <xs:restriction base="xs:string">
  </xs:restriction>
 </xs:simpleType>

 <xs:simpleType name="CategoryType">
  <xs:restriction base="xs:string">
   <xs:enumeration value="SPORT" />
   <xs:enumeration value="COOKING" />
   <xs:enumeration value="PROGRAMMING" />
  </xs:restriction>
 </xs:simpleType>
 
</xs:schema>

Conclusion
When starting of thinking of Schema one come to the conclusion that schema design is much like tradition OO design, where one must always consider if a properties and method should be hidden or exposed to other classes. The same yields for Schemas and in the real world one would scarcely use just one design pattern, but rather combine them.

November 2, 2009

Problem Running Eclipse in Ubuntu 9.10 Karmic Koala

After upgrading to Ubuntu 9.10, Eclipse started to behave strangely. Button seams to be non-responsive, so I googled for a solution and came up with this link.

http://www.norio.be/blog/2009/10/problems-eclipse-buttons-ubuntu-910

November 1, 2009

Writing to Syslog with Log4J and Testing It on Ubuntu 9.04 Jaunty

The preferred way to log in Linux is to write to the Syslog. For you that comes from the Windows world, Syslog is the equivalent for the Windows NT Event Log. Before you can ran the example below you need to enable Syslog Facility LOCAL1 on Ubuntu. The Facility can be looked as a filter and if you are running multiple programs on the same server, you might want to consider to let each program write to different Facility LOCAL[0-7].

To enable Facility LOCAL1 on Ubuntu 9.04 you first need to edit /etc/syslog.conf
$ sudo gedit /etc/syslog.conf

and add the following line
local1.*   /var/log/local1.log

But we are not done yet, since Log4J org.apache.log4j.net.SyslogAppender is using the underlying writer class org.apache.log4j.helpers.SyslogWriter that is using the java.net.DatagramPacket which is writing to the syslog remotely, we need to enable remote access to Syslog. We do that by changing:
$ sudo gedit /etc/default/syslogd

And changing the following:
SYSLOGD="-r"

Now we are done and we need to restarts the system log daemon, to make our changes take affect:
$ sudo /etc/init.d/sysklogd restart

Finally we add the following configuration to our log4j.properties.
# configure the root logger
log4j.rootLogger=INFO, STDOUT, DAILY, SYSLOG_LOCAL1

# configure Syslog facility LOCAL1 appender
log4j.appender.SYSLOG_LOCAL1=org.apache.log4j.net.SyslogAppender
log4j.appender.SYSLOG_LOCAL1.threshold=WARN
log4j.appender.SYSLOG_LOCAL1.syslogHost=localhost
log4j.appender.SYSLOG_LOCAL1.facility=LOCAL1
log4j.appender.SYSLOG_LOCAL1.facilityPrinting=false
log4j.appender.SYSLOG_LOCAL1.layout=org.apache.log4j.PatternLayout
log4j.appender.SYSLOG_LOCAL1.layout.conversionPattern=[%p] %c:%L - %m%n

Maven2 Reference Literature

For some time the best book on Maven2 was “Better Builds with Maven” which can be downloaded from http://www.maestrodev.com/better-build-maven, but now there is finally a more updated book, “Maven: The Definitive Guide“. Which is available from

http://www.sonatype.com/books/maven-book/reference/public-book.html

The Promising Standardized JSR 303 Bean Validation and Example of Usage

For too long have the Java world lived without a standardized bean validation specification and soon will the final approval hopefully be approved (2 Nov 2009). What does this imply?
  1. Better Domain Driven Design, by putting the shallow domain validation in the POJO where it belongs.
  2. Hopefully we can finally get rid of Value Objects Pattern which is a dark heritage from the EJB 2.1 age and instead use domain POJO beans through out our architecture. There is of course exception to this rule, e.g. in service layer where the exposed model is totally different than the domain model or in a UI layer with heavy usage of line charts, there an OO model does not fit into a point orientation representation.
What is still to be proven is how the specification will fit into other framework, such as JPA, Apache Wicket or Spring Remoting. But one can rest ashore if one is using the standard validation model, the odds increase dramatically. And presumably will big framework such as Spring Framework and Apache Wicket adjust there framework to the standard.

Here follows a simple example of the usage of Bean Validation.

pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>
<groupId>se.msc.examples</groupId>
<artifactId>validation-domain</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Validation :: Domain</name>
<url>http://www.msc.se/examples/validation</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<repositories>
<repository>
<id>repository.jboss.org</id>
<url>http://repository.jboss.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>

<dependencies>
<!-- common logging library -->
<!-- version is depended on hibernate-annotations v3.4.0.GA -->
<!--
http://repo1.maven.org/maven2/org/hibernate/hibernate-annotations/3.4.0.GA/hibernate-annotations-3.4.0.GA.pom
-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.4.2</version>
</dependency>
<!-- sun bean validation api -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<!-- hibernate bean validation impl -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.0.0.GA</version>
</dependency>
<!-- test support -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<defaultGoal>install</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>

</project>

package se.msc.examples.validation.domain;

import java.io.Serializable;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private Long personId;
private String firstName;
@NotNull
@Size(min=1)
private String surname;
@NotNull
@Pattern(regexp=".+@.+\\.[a-z]+")
private String mail;

public Long getPersonId() {
return personId;
}

protected void setPersonId(Long personId) {
this.personId = personId;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getSurname() {
return surname;
}

public void setSurname(String surname) {
this.surname = surname;
}

public String getMail() {
return mail;
}

public void setMail(String mail) {
this.mail = mail;
}

}

package se.msc.examples.validation.domain;

import static org.junit.Assert.*;

import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class PersonTest {
  private Validator validator;
  private Person person;

  @BeforeClass
  	public static void oneTimeSetUp() throws Exception {  
  }

  @AfterClass
  	public static void oneTimeTearDown() throws Exception {
  }

  @Before
  public void setUp() throws Exception {
    validator = Validation.buildDefaultValidatorFactory().getValidator();
    person = new Person();
    person.setFirstName("Magnus K");
    person.setSurname("Karlsson");
    person.setMail("magnus.k.karlsson@domain.se");  
  }

  @After
  public void tearDown() throws Exception {
  }

  private <T> void debugPrint(Set<ConstraintViolation<T>> violations) {
    for (ConstraintViolation<T> violation : violations) {
      String propertyPath = violation.getPropertyPath().toString();
      String message = violation.getMessage();
      System.out.println("invalid value for: '" + propertyPath + "': " + message);
    }  
  }

  @Test
  public void testValidate_OK() throws Exception {
    Set<ConstraintViolation<Person>> violations = validator.validate(person);
    assertTrue(violations.size() == 0);
    debugPrint(violations);
  }

  @Test
  public void testValidate_FAIL_MAIL() throws Exception {
    person.setMail("magnus.k.karlsson@domain");
    Set<ConstraintViolation<Person>> violations = validator.validate(person);
    assertTrue(violations.size() == 1);
    debugPrint(violations);
  }

  @Test
  public void testValidate_FAIL_SURNAME() throws Exception {
    person.setSurname(null);
    Set<ConstraintViolation<Person>> violations1 = validator.validate(person);
    assertTrue(violations1.size() == 1);
    debugPrint(violations1);

    person.setSurname("");
    Set<ConstraintViolation<Person>> violations2 = validator.validate(person);
    assertTrue(violations2.size() == 1);
    debugPrint(violations2);  
  }

}

The resource bundle message ValidationMessages.properties
javax.validation.constraints.Null.message=must be null
javax.validation.constraints.NotNull.message=must not be null
javax.validation.constraints.AssertTrue.message=must be true
javax.validation.constraints.AssertFalse.message=must be false
javax.validation.constraints.Min.message=must be greater than or equal to {value}
javax.validation.constraints.Max.message=must be less than or equal to {value}
javax.validation.constraints.Size.message=size must be between {min} and {max}
javax.validation.constraints.Digits.message=numeric value out of bounds (<{integer} digits>.<{fraction} digits> expected)
javax.validation.constraints.Past.message=must be a past date
javax.validation.constraints.Future.message=must be a future date
javax.validation.constraints.Pattern.message=must match the following regular expression: {regexp}


References:
JSR 303: Bean Validation
http://jcp.org/en/jsr/detail?id=303

Article comparing JSR 303 Reference Implementation And Spring 2.5 Validation
http://blog.jteam.nl/2009/08/04/bean-validation-integrating-jsr-303-with-spring/

JSR 303 Reference Material
http://people.redhat.com/~ebernard/validation/

JSR 303 Specification Leads Emmanuel Bernard Blog
http://in.relation.to/Bloggers/Emmanuel