Wednesday, January 21, 2015

Create Your Own Java Bean Validator with a Custom Element

Abstract
The purpose of this article is to demonstrate how to do two things.  The first is how to create your own Java bean validator as specified by JSR 349: Bean Validation 1.1.  The second is adding your own custom element to this validator so as to effect or define the validator's behavior.

System Requirements
This example was developed and run using the following system setup. If yours is different, it may work but no guarantees.
  • JDK 1.7.0_11
  • Eclipse Luna
  • Maven 3.2.1 (Embedded with Eclipse)
Maven Dependencies
The following dependencies are needed in your pom.xml to work with bean validation:

javax.validation
validation-api
1.1.0.Final


org.hibernate
hibernate-validator
5.1.2.Final


com.fasterxml
classmate
1.1.0

What is Bean Validation
JSR 349: Bean Validation 1.1 is the Java standard allowing you to develop reusable constraints and validators to ensure your application's data meets its business requirements. This may sound complicated, but it's actually very simple. Suppose your application is required to get a user's email address before successfully registering them for a new account. Traditionally, a developer would need to manually code this business requirement. Using JSR 349, the same business requirement can be satisfied using a reusable @NotNull constraint from the bean validation framework. Listing 1 demonstrates this.

Listing 1: Validate user's email address is not null
public class User {
@NotNull
protected String email;
// class continues...
}

As you can see from listing 1 the @NotNull constraint and the JSR 349 Bean Validation framework are responsible for validating the email address.  Additionally, the @NotNull constraint has no specific ties to email address meaning it can be reused to validate a users first name, last name, date of birth, or whatever data your business requirements say the user must provide.

The bean validation framework is very powerful in that it's also extensible. @NotNull is a very common constraint and as such is provided by the framework. However your application will no doubt have very specific business requirements which the built-in constraints cannot handle. Let's look at an example of such a requirement and how we can build our own constraints and validators to handle it.

Specific Business Requirement
Suppose your application needs to interact with the computer's file system. The user must select a directory but in order to guarantee your application does not inadvertently modify any existing files, it's required that the directory the user selects must be completely empty. This is a good example of data validation that is very specific to your application and which the bean validation framework does not handle out of the box. Remember though the bean validation framework is extensible. It's possible to create a constraint and validator to satisfy this business requirement.  Let's first look at creating the constraint.

Constraint
A bean validation constraint is a simple annotation. Listing 2 shows a @DirectoryIsEmpty validation constraint annotation we'll use to satisfy our application's business requirement.

Listing 2: DirectoryIsEmpty bean validation constraint
package org.ferris.validation.constraints;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;
import org.ferris.validation.validator.DirectoryIsEmptyValidator;

@Target({ 
   ElementType.TYPE, ElementType.ANNOTATION_TYPE
 , ElementType.METHOD, ElementType.FIELD
 , ElementType.PARAMETER, ElementType.CONSTRUCTOR })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = { DirectoryIsEmptyValidator.class })
@Documented
public @interface DirectoryIsEmpty {
    String message() default "{org.ferris.validation.constraints.DirectoryIsEmpty.message}";

    Class[] groups() default { };

    Class[] payload() default { };
    
    String[] excludes() default {};
}

Let's take a look at this constraint in detail.

#12 The @Target annotation defines what elements the @DirectoryIsEmpty can be put on.  In general, the annotation can either be put at the class-level, property-level, or parameter-level.  At the class-level, the validation occurs on the class as a whole. This is a way to validated properties which go together, like password and verifiedPassword properties need to be the same. At the property-level, the annotation can either go on the property or on the getter method for the property. At the parameter-level, the annotation goes on a constructor parameter or a method parameter. Typically the @Valid annotation is used at this level so the bean validation framework can validate properties before executing the constructor or method.

#17 The @Constraint annotation tells the bean validation framework which class is responsible for validating this constraint.  Here it defines the DirectoryIsEmptyValidator.class.

#19 @interface DirectoryIsEmpty is the standard way to define an annotation.

#20 The message element is required on bean validation constraint annotations. This element is used by the framework to determine what error message should be displayed if validation fails. You can hard code a plain text message, or, as is seen here, enter a resource bundle key as "{key_value}". By convention, the key value is the fully-qualified-class-name + ".message". The bean validation framework will look in the class path for a ValidationMessages.properties file.  This file is located at the root of the class path.

#22 The groups element is required on bean validation constraint annotations. This is used to group validation constraints together. For example, a field may have four validation constraints divided into three different groups. The @GroupSequence annotation can be used to define the sequence of the validation constraints.  This is helpful if a constraint validation needs to happen in a certain order.

#24 The payload element is required on bean validation constraint annotations, however it is not directly used by the bean validation framework itself. If a payload is present and a constraint violation occurs, the bean validation framework will put the payload into the ConstraintViolation#ConstraintDescriptor object for later use. If a payload is not present, the bean validation framework puts nothing into the object. A payload is a way to pass additional information about the constraint violation to the UI layer (or to any code) responsible for handling the violation. For example, a severity can be assigned to the payload to change the alerting level handling the violation.

#26 The excludes element is custom to this annotation. Just like any annotation, you are able to create your own custom elements in order to pass additional information to the validator to customize the validation. In this example, the excludes element is a String[] and it is used to define the names of directories which are excluded from the constraint validation. For example, suppose you have @DirectoryIsEmpty(excludes={"foo", "bar"}). At validation, the directory will NOT be checked if the name of the directory is either "foo" or "bar".

A constraint annotation is only the first part to creating your own bean validator. As seen on line #17, a class to do the validation is needed. In this example it is DirectoryIsEmptyValidator.class.  Let's take a look at this class next.

Validator
A validator class is the next piece you need to creating your own bean validation after creating the validation constraint annotation.  The annotation is used on whatever class, property, or parameter you want to validate. The validator class is responsible for doing the actual validation. Given our @DirectoryIsEmpty validation constraint annotation, listing 3 shows its validator

Listing 3: DirectoryIsEmptyValidator validator
package org.ferris.validation.validator;

import java.io.File;
import java.util.Arrays;
import java.util.List;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.ferris.validation.constraints.DirectoryIsEmpty;

public class DirectoryIsEmptyValidator 
implements ConstraintValidator< DirectoryIsEmpty, File > {

 private List< String > excludes;
 
 @Override
 public void initialize(DirectoryIsEmpty arg0) {
  String [] strarr = arg0.excludes();
  if (strarr == null) {
   strarr = new String[]{};
  }
  excludes = Arrays.asList(strarr);
 }

 @Override
 public boolean isValid(File file, ConstraintValidatorContext context)
 {
  if (excludes.contains(file.getName())) {
   return true;
  }
  File [] files = file.listFiles();
  if (files != null && files.length > 0) {
   return false;
  } else {
   return true;
  }
 }
}

Let's take a look at this validator in more detail.

#11 Here we see the class implements the ConstraintValidator interface with the specific generics being DirectoryIsEmpty, and FileDirectoryIsEmpty obviously refers to the @DirectoryIsEmpty validation constraint annotation. File defines the @DirectoryIsEmpty annotation must be put on a class that extends File or on a File property or parameter. This of course make sense because our business requirement states the directory picked by the user must be empty if it is to be valid. Directories in Java are represented by the File object.

#13 This property will be used to hold a list of directory names excluded from the validator.

#16 The initialize method is part of the ConstraintValidator interface and can be overridden to do custom initialization of the validator.

#17 Here the excludes() method is called to get the String[] holding the names of the directories to exclude from validation. The excludes element may or may not be defined so the validator must handle both cases.  If the excludes element is defined and the excludes() method call returns a String[] of directory names to be excluded from validation, then the validator must ensure it does not validate those directories. If the excludes element is not defined and the excludes() method call returns nothing, then the validator should not exclude any directory from validation.

#25 The isValid method is part of the ConstraintValidator interface. This is where the magic happens. Code this method to perform any validation you need. Return true if valid, false otherwise.

#27 The code checks the excludes property to see if the list contains the name of the directory being validated. If the list does contain the name, then return true (#28) because that directory should be excluded from validation which means it is automatically valid.

#30 Use the File#listFiles method to get a list of all files and sub-directories. If there are files or sub-directories (#31) return false because the directory the user selected is not empty and fails the business requirement. Otherwise, return true (#34) because the directory the user selected is empty and this satisfies the business requirement.

You've learned how to create your own validation constraint annotation and its associated validator. You've also learned how easily the bean validation framework is extended and hopefully you recognize the great opportunities this gives you.

References
Bernard, Emmanuel. (2013, April). Bean Validation specification. beanvalidation.org. Retrieved January 21, 2015, from http://beanvalidation.org/1.1/spec/

JSR 349: Bean Validation 1.1. (n.d.). Java Community Process. Retrieved January 21, 2015, from https://jcp.org/en/jsr/detail?id=349

Enjoy!

Friday, January 9, 2015

Mocking System static void methods..config for Maven, JUnit, PowerMock, PowerMockito, and Mockito

Abstract
I previously wrote about Mocking return values of static methods..config for Maven, JUnit, PowerMock, EasyMock, and Mockito. The previous article focused on the need to mock a static method which returns a value. This article is also about mocking static methods, but static void methods - methods that return no value. Why would you need to mock such a method? Well my unit test needs to verify that a static void method was being called.  Specifically I wanted to Mockito.times(1) verify my application was calling the following System static void method on the Thread class: 

Thread.setDefaultUncaughtExceptionHandler(eh); 
My application's proper error handling depends on setting a default exception handler so it makes sense to have a unit test for it. Performing a Mockito.times(1) verify testing for this System static void method call however, has a number of challenges, including:
  1. It's a static method
  2. It's a static void method meaning it does not return a value
  3. It's a JVM System class
The purpose of this article is to show a simple JUnit code example to verify a call to a JVM System static void method such as Thread.setDefaultUncaughtExceptionHandler(eh).

System Requirements
This example was developed and run using the following system setup. If yours is different, it may work but no guarantees.
  • JDK 1.7.0_11
  • Eclipse Luna
  • Maven 3.2.1 (Embedded with Eclipse)
The rest of the software dependencies can be found in this article.

Maven POM dependencies
Listing 1 shows the Maven POM dependencies needed to run the unit test listed below.  From my research, these are the only dependencies you need.  

WARNING: If you do have JUnit or Mockito as direct dependencies, most likely you'll get at version mismatch and the unit tests will fail to run. They are pulled in as transitive dependencies of what's in Listing 1. 
Listing 1: Maven POM dependencies
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>1.5.6</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-easymock</artifactId>
    <version>1.5.6</version>
    <scope>test</scope>
</dependency>       
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito</artifactId>
    <version>1.5.6</version>
    <scope>test</scope>
</dependency>        
<dependency>
    <groupId>org.easymock</groupId>
    <artifactId>easymock</artifactId>
    <version>3.2</version>
    <scope>test</scope>
</dependency>

Class Using a System static void method
Listing 2 shows a wrapper class which wraps the call to the System static void method Thread.setDefaultUncaughtExceptionHandler(eh). The reason for the wrapper class is described in the Mockito documentation which states such a wrapper class is required "If you need to mock classes loaded by the java system/bootstrap classloader (those defined in the java.lang or java.net etc)." I called my wrapper class ThreadTools.

Listing 2: Java ThreadTools wrapper class
/**
 * @author Michael Remijan mjremijan@yahoo.com @mjremijan
 */
public class ThreadTools {
  public void setUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
    Thread.setDefaultUncaughtExceptionHandler(handler);
  }
} 

As you can see, ThreadTools is very simple. It doesn't add any overhead to your application to use this wrapper class and it is essential for the unit test to work properly. Now that we have a class to test, let's next take a look at what the unit test looks like.

Verifying a static void method in a unit test 
The goal of the unit test is to verify the System static void method Thread.setDefaultUncaughtExceptionHandler(eh)is actually called. In the Mockito world, verifing that a method has been called with certain parameter values is usually accomplished with code that looks like:

Mockito.verify(mockedObject, Mockito.times(1)).someMethod("param");

The above statement is used to verify that someMethod was called on the mockedObject only times(1) with exactly the "param" value passed to the method. We want to do something similary, only with a JVM System static void method, which makes it a little bit harder.
  
Listing 3 shows the Java source code for a very simple unit test which does exactly this. For this unit test you are going to be using a combination of PowerMockRunner, PowerMockito, and Mockito. Let's step through this unit test line by line.

NOTE: You'll be using PowerMockRunner, PowerMockito, and Mockito all at the same time, for sanity's sake, avoid using static imports! Static imports are a great convenience, but when mixing so many different technologies it get very hard to keep straight which methods are coming from which classes.

Listing 3: Java ThreadToolsTest class
import java.lang.Thread.UncaughtExceptionHandler;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(ThreadTools.class) 
public class ThreadToolsTest {
  @Test
  public void testSetDefaultUncaughtExceptionHandleIsCalled() throws Exception {
    // Prepare
    PowerMockito.mockStatic(Thread.class);

    // Mock
    UncaughtExceptionHandler handler
      = Mockito.mock(UncaughtExceptionHandler.class);
    
    // Test
    new ThreadTools().setUncaughtExceptionHandler(handler);
    
    // Verify
    PowerMockito.verifyStatic(Mockito.times(1));
    Thread.setDefaultUncaughtExceptionHandler(handler);
  }
}

Let's take a look at this code in a bit more detail.

#9 @RunWith
We need to run the test with the PowerMockRunner, not the normal JUnit runner.

#10 @PrepareForTest
We need to prepare the wrapper class that uses the System static void method. This is important and easy to get confused. Do not prepare the System class, which in this example is Thread.class. You must prepare the wrapper class which is ThreadTools.class. To make the test easy, we created a wrapper class specifically for calling Thread.setDefaultUncaughtExceptionHandler(eh). In general, the class you must @PrepareForTest must be whatever class is making the System static void method call.

#12 PowerMockito.mockStatic(Thread.class)
Use PowerMockito to prepare the Thread.class for mocking.  Unlike normal mocking, this does not return a mock object, it just prepares Thread.class for mocking in the PowerMockito framework.

#18 Mockito.mock(UncaughtExceptionHandler.class)
This is a normal mock of the UncaughtExceptionHandler interface. Ultimately this mock should be passed to Thread.setUncaughtExceptionHander(eh) and  the goal of the unit test is to verify this has happened.

#22 new ThreadTools().setUncaughtExceptionHandler(handler)
This will now perform the test.  An instance of our wrapper class ThreadTools is created and its setUncaughtExceptionHandler(eh) method is called.  This in turn will call a "mocked" Thread.class.  After this test is performed, we should be able to verify the "mocked" Thread.class did get called.  We'll see this in the next lines.

#25 PowerMockito.verifyStatic(Mockito.times(1));
This tells the PowerMockito framework that it needs to verify that the class it statically mocked on line #15 (Thread.class) had a static void method called only 1 time.  But which method?  Look at the next like of code.

#26 Thread.setDefaultUncaughtExceptionHandler(handler);
The previously like, line #25 told PowerMockito to verify the static void method was called only 1 time. This line tells PowerMockito which method, which is setDefaultUncaughtExceptionHandler(eh).  Not only that, but it also tells PowerMockito that the parameter passed that to method should have been the handler object which is the mock of UncaughtExceptionHandler we create on line #18.

Conclusion
Mocking statics is not trivial, and mocking System static void method is even more tricky.  But PowerMockRunner, PowerMockito, and Mockito are powerful tools which make it possible. Put it all together with Maven and you have a good system to verifying your code base.

References
Using PowerMock with Mockito. (n.d.). code.google.com. Retrieved January 2015, from https://code.google.com/p/powermock/wiki/MockitoUsage13

Mocking system classes. (n.d.). code.google.com. Retrieved January 2015, from https://code.google.com/p/powermock/wiki/MockSystem

Class Mockito. (n.d.). docs.mockito.googlecode.com. Retrieved January 2015, from http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#1

fatmind. (2014 May 4). powermock example. github.com. Retrieved January 2015, from https://gist.github.com/fatmind/4110984
Enjoy!