Spring Bean Validation Example (JSR-303) in Kotlin

Many developers need a solution to validating forms. Spring MVC supports bean validation (JSR-303) which is an easy to use annotation driven framework that is used to validate objects. Spring utilizes bean validation throughout the entire application framework, allowing developers to annotation one or more objects and ensure they are valid from the controller all the way to the data access layer.

Since Kotlin is compatible with Java libraries, this post demonstrates how to use bean validation along with Spring MVC to validate a user registration form. Here is a screen shot of the form we are going to validate.
WelcomeScreen copy

Step 1—Define a Form Object

We will use a POJO that carries data from the view to the server. Kotlin makes this really easy because it provides data classes.

data class User(@get: NotBlank (message = "{first_name.required}")
                    var firstName : String = "",

                @get: NotBlank (message = "{last_name.required}")
                    var lastName : String = "",

                @get: NotBlank (message="{email.required}")
                @get: Email (message = "{email.invalid}")
                    var email : String = "",

                @get: NotBlank (message="{phone.required}")
                    var phone : String = "",

                @get: NotBlank (message="{address.required}")
                    var address : String = "",

                @get: NotBlank (message="{city.required}")
                    var city : String = "",

                @get: NotBlank (message="{state.required}")
                @get: Size(min=2, max=2, message = "{state.size}")
                    var state : String = "",

                @get: NotBlank (message="{zip.required}")
                    var zip : String = "")

You will notice a couple of things in the class. The first is the @get [annotation] annotation. Kotlin generates getter/setter methods in the Java bytecode. When we use the @get annotation followed by the annotation, Kotlin will place the target annotation on the getter method. So for example, @get: NotBlank is telling the Kotlin compiler to place the @NotBlank annotation on the generated getter method.

Next you will notice the message argument that is passed to the NotBlank annotation. In the first example, we have message = “{first_name.required}”. The message parameter takes a String that is displayed to the user when validation fails. If we use expression language, Spring boot will look for a ValidationMessages.properties file that contains the actual message. This is useful when making localized applications because you can have a different ValidationMessages file per language.

In this example, we are using three different Hibernate Validator annotations.

  • NotBlank—Valid if a String is not blank. Fails is the String is blank or null.
  • Email—Valid if the string field contains a valid email address
  • Size—Valid if the string has at least min number of characters and less than max characters

Step 2—ValidationMessages.properties

If you choose to use a ValidationMessages.properties file, Spring Boot will look for the actual message inside of a ValidationMessages.properties file in the applications classpath. I find this to be the preferred approach because it allows develoeprs to easily localize an application if needed. Here is the properties file we are using in this example.

first_name.required="First name is required"
last_name.required="Last name is required"
email.required="Please enter your email address"
email.invalid="Please provide a valid email address"
phone.required="Please enter a phone number"
address.required="Please enter your address"
city.required="Please enter a city"
state.required="Please enter a state"
state.size="Please use 2 letter state code"
zip.required="Enter a zip code"

The keys of the file are the same as when is passed to the message parameter of each bean validator annotation. The value is what is ultimately displayed to the user.

Step 3-Controller

Spring MVC uses a controller class. Here is the code for our controller in this example.

@Controller
@RequestMapping("/")
@Scope(WebApplicationContext.SCOPE_REQUEST)
class ValidatorController(@Autowired val registrationService: RegistrationService) {

    @RequestMapping(method = arrayOf(RequestMethod.GET))
    fun doGet(model : Model) : String {
        model.addAttribute("user", User())
        return "index"
    }

    @RequestMapping(method = arrayOf(RequestMethod.POST))
    fun doPost(@Valid user : User,  //The @Valid annotation tells Spring to Validate this object
               errors : Errors)  //Spring injects this class into this method. It will hold any
                                //errors that are found on the object
            : String {
        val result : String
        when {
            //Test for errors
            errors.hasErrors() -> result = "index"
            else -> {
                //Otherwise proceed to the next page
                registrationService.user = user
                result = "redirect:/congrats"
            }
        }
        return result
    }
}

The first method is doGet which is mapped to an HTTP Get request. Nothing fancy here for those readers who are famailier with Spring MVC (This post explains Spring MVC for users who are not famalier with Spring MVC). All we do here is create a new instance of the User class and pass it to the view.

The doPost is the method that we care about for this post. This method has two parameters. The first one is a User argument that is annotated with @Valid. The other one is an Errors object. These two argument work in tandem to validate a Spring MVC form.

The User object is bound to the web form. Each field in the form is mapped to a property on the User class. When the form is submitted, Spring MVC carries this object from the View to the Controller. However, if the parameter has the @Valid annotation, then the User object make a stop and is examaned by a class that impelements javax.validation.Validator. Should the validation report any errors, they are gathered together in the Errors object that is injected into this method.

The errors.hasErrors() method returns true if the user entered invalid input into the form. We can return the name of the page that was submitted and report the errors back to the user if that is the case. Here is what it looks like.
Invalid copy

On the other hand, we can redirect the user to the next page if everything is ok (errors.hasErrors() == false).
Congrats copy

Step 4—The View

Of course, we need to setup our web page properly in order to actually see the errors. Since I am a big fan of Twitter’s Bootstrap, I use their form validation framework to make a nice front-end display to the errors message.

Here is a code snippet of a field on the form.
field
We use a teneray expression to check each field if it has errors th:class="${#fields.hasErrors('firstName') ?'form-group has-error' : 'form-group'}". If the field has an error, we use bootstraps has-error css class to get the red outline. Otherwise, we don’t add that class and just use form-group. In case you are wondering, the fields object is the same Errors object that we were using in our server code. This is just another rendition of the same object.

The next thing to do is print out each error. This can be done very easily by using the th:each tag and assigning each message to the err variable: th:each="err: ${#fields.errors('firstName')}" class="help-block" th:text="${err}". When executed, this code will look up the message (found in ValidationMessages.properties) for each error and write is out to a span tag.

When run, each field that has an error will have its textbox outlined and the error message printed below the text box.

Getting the Code

You can get the complete code for this project at my github page.

Result

Here is the final result

Advertisement

Kotlin Koans—Part 18

This portion of the Kotlin Koans tutorial deals with sorting a collection functionally. As usual with Kotlin, this wasn’t a very difficult problem. As a matter of fact, it’s only one line of code.

fun Shop.getCustomersSortedByNumberOfOrders(): List {
    return customers.sortedBy { it.orders.size }
}

We basically just call the sortedBy method and place the property we want to sort by inside of the curly braces { }. In this case, I wanted to sort by the number of orders my hypothetical customer placed, so I used it.orders.size.

Just for kicks, I decided to try this in Java 8 to see the difference.

public static List getCustomersSortedByNumberOfOrders(Shop shop){
    return shop.getCustomers()
            .stream()
            .sorted(Comparator.comparingInt(customer -> customer.getOrders().size()))
            .collect(Collectors.toList());
}

Once again, we can do the same thing in Java that we can do in Kotlin at the expense of more verbosity. Also, I think in this case, the Java approach is more difficult to learn and more prone to errors since we are chaining a bunch of functions together to achieve the same result that we can do in one line of Kotlin code.

You can click here to see Part 17

Kotlin Koans—Part 17

This part of Kotlin Koans continues to build on the features Kotlin offers on collection. Most of these methods will look familiar to people who have worked with Java 8 streams.

In this portion of the tutorial, I had to work with the maxBy method. It’s a nice little shortcut method to find an item based on a property. There is also a companion minBy.

fun Shop.getCustomerWithMaximumNumberOfOrders(): Customer? {
    // Return a customer whose order count is the highest among all customers
    return customers.maxBy { it.orders.size }
}

fun Customer.getMostExpensiveOrderedProduct(): Product? {
    // Return the most expensive product which has been ordered
    return orderedProducts.maxBy { it.price }
}

I was curious about what it would take to solve this problem in Java. Here is what I came up with.

public static Optional getCustomerWithMaximumNumberOfOrders(Shop shop){
    return shop.getCustomers().stream().max(Comparator.comparingInt(lhs -> lhs.getOrders().size()));
}

I can’t say it was too brutal, but I think maxBy is much easier to read and understand as opposed to stream().max(Comparator.comparingInt(lhs -> lhs.getOrders().size()))

You can click here to see Part 16

Kotlin Koans—Part 16

This portion of the Kotlin Koans tutorial continued with collection operations. Again, many of these operations are available in JDK8, but are missing in Android Java and previous versions of JDK. I got a few different demonstrations about what you can do with Kotlin here.

Operator Overloading

Kotlin supports operator overloading. I think this was a good move. C++ has operator overloading, but it was left out in Java. At the time, some people brought up that operator overloading was a source of bugs and it impacted code readability. I used to be one of those people, but frankly, I have been swayed back towards operator overloading. Operator overloading cuts down on verbosity in your code, and I can’t truthfully say I have seen additional bugs do to operator overloading.

Here is the first portion of Kotlin code

fun Customer.isFrom(city: City): Boolean {
    // Return true if the customer is from the given city
    return this.city == city
}

All

Kotlin collections have an all { } method that accepts a predicate. You can use it check if all items in a collection match the criteria specified in the predicate.

fun Shop.checkAllCustomersAreFrom(city: City): Boolean {
    // Return true if all customers are from the given city
    return customers.all { it.city == city }
}

Any

The any { } method is similar to all, but only one item in the collection has to match the predicate for it to return true.

 fun Shop.hasCustomerFrom(city: City): Boolean {
    // Return true if there is at least one customer from the given city
    return customers.any{ it.city == city }
}

Count

Kotlin collections have a count method also that returns the number of items that match the criteria provided in the predicate.

fun Shop.countCustomersFrom(city: City): Int {
    // Return the number of customers from the given city
    return customers.count { it.city == city }
}

Find Any

We also have a find any method which returns an item that matches the criteria in the predicate.

fun Shop.findAnyCustomerFrom(city: City): Customer? {
    // Return a customer who lives in the given city, or null if there is none
    return customers.find { it.city == city }
}

it

You may have noticed it popping up in all of these lambda expressions. As long as a SAM interface has only one parameter, developers can use a special it variable to refer to that parameter.

You can click here to see Part 15

Kotlin Koans—Part 15

Kotlin supports API that is similar to what is offered by Java 8 Streams. In this portion of the Kotlin Koans tutorial, I had to work with filtering and mapping. As an added bonus, I saw a good use case for Kotlin’s operator overloading capabilities and it’s collection transformation capabilities.

Here is the Kotlin code

fun Shop.getCitiesCustomersAreFrom(): Set {
    return customers.map { it.city }.toSet()
}

fun Shop.getCustomersFrom(city: City): List {
    return customers.filter { it.city == city }
}

The first function has us extracting all cities out the customers. In this example, customer has a city property. We can therefore us the map function to drill down to the city property on customer and gather than into a collection. Once we have our customers, we can use the toSet() method to transform the collection into a set.

The second function has us using a predicate to filter customers by city. Kotlin has operator overloading so we can use the == to compare object equality in Kotlin rather than reference equality in Kotlin.

Kotlin has to offer Android developers in this case. Java developers have much of these features as of JDK 8. One thing I noticed in particular was that you do not need to call stream() on collections in Kotlin. I don’t find this to be a huge surprise however. Much of the Java 8 functionality came in the form of the new Streams api, which they attached to the collection framework. Kotlin seems to have built such features directly into the collection classes.

You can click here to see Part 14

Kotlin Koans—Part 14

I have always had a huge complaint about Java’s collection classes. The complaint involves switching between types of collections. For example, let’s suppose you have an ArrayList and you want to switch it to a set. Here is how you would do it in Java.

public class CollectionConvert {
    public static void main(String [] args){
        List lst = Arrays.asList(1, 2, 3);
        Set set = new HashSet(lst);
    }
}

Ok so let’s be honest here. It’s not as if it’s really that difficult to convert a List to a Set in Java. All of the constructors of the Java collection class accept another collection so we can pass an existing collection into a new collection to handle switching between collection types.

But let’s face the fact. It can be better than this. We are using two lines of code that could be done with one piece of code instead. Here is how it’s done in Kotlin.

fun Shop.getSetOfCustomers(): Set {
    // Return a set containing all the customers of this shop
    return customers.toSet()
}

Kotlin extends Java’s collection classes with these sort of conversion method. It may not seems like a big deal until you want to do something like this.

val lst = arrayListOf(1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9)

//Filter out duplicates and maintain a list
val noDuplicates = lst.toSet().toList()
//continue working with list instead of set...

The Set interface lacks method such as get(index). Sometimes it’s helpful to remove all duplicates in a list prior before working on the list. Java 8 does a lot of help with this problem, but I still think Kotlin is more consice.

List lst = Arrays.asList(1, 1, 1, 2, 2, 2, 3, 3, 3);
List noDuplicates = lst.stream().distinct().collect(Collectors.toList());

You can click here to see Part 13

Kotlin Koan—Part 13

Kotlin has nice extensions on Collection classes. JDK has provided developers a way to sort collections for a long time now, but often times, it’s done with external classes such as Collections. This puts us in a odd position of using procedural programming when performing operations such as sorting a collection.

A more OOP approach would be to have a sort method directly on a Collection as opposed to passing a collection to an external class with a static method. Kotlin extends Java collections by using its extension feature to complement the collection classes found in JDK.

Here is an example that demonstrates how to sort an ArrayList in Java.

fun task12(): List {
    val lst =  arrayListOf(1, 5, 2)
    lst.sortDescending()
    return lst
}

If all fairness to Java, JDK 8 did address this issue. Here is the equivalent Java code that does the same thing.

public class CollectionSort {
    public List sortList(){
        List lst = Arrays.asList(1, 5, 2);
        lst.sort(Comparator.reverseOrder());
        return lst;
    }
}

I’m not going to complain too much about the Java 8 syntax, but I think sortDescending() and sortAcending() is more readable than Comparator.natualOrder() and Comparator.reverseOrder(). However, the Kotlin approach is much superior to JDK 7 and earlier.

You can read the previous post here.

Kotlin Koans—Part 12

The last part of the Kotlin Koans tutorial had me use Object Expressions to sort an ArrayList. I observed that this could have been done with a lambda expression and I was correct.

This portion of the tutorial discusses implementing an interface with one abstract method. Kotlin calls such interfaces a SAM interface (Single Abstract Method). Whenever a developer is working with a SAM interface, they are free to use a lambda expression rather than an Object Expression.

Here is the Kotlin code that uses a lambda expression

fun task11(): List {
    val arrayList = arrayListOf(1, 5, 2)
    Collections.sort(arrayList, { x, y -> y.compareTo(x) })
    return arrayList
}

I should point out that Java 8 supports lambda expressions now also. Java calls SAM interfaces Functional interfaces. You can even add a @Functional annotation to such interfaces in Java.

I don’t see any huge advantage to Kotlin lambdas over Java ones at this point. Of course, Android developers may appreciate Kotlin’s lambda support.

You can view part 11 here.

Kotlin Koans—Part 11

This portion of the Kotlin Koans tutorial focuses on Object Expressions. Practically speaking, Object Expressions serve the same role as anonymous innner classes in Java. They let us make modifications on a class in one particular case without having to create an entirely new class.

This portion of the tutorial has developers creating a dynamic Comparator class that sorts numbers in descending order.

fun task10(): List {
    val arrayList = arrayListOf(1, 5, 2)
    Collections.sort(arrayList, object: Comparator {
        override fun compare(o1: Int?, o2: Int?): Int {
            return o2?.compareTo(o1 ?: 0) ?: 0
        }
    })
    return arrayList
}

We could have used a lambda in this case, but that would miss the point of what the tutorial is trying to teach. In this code snippet, the second paramter of Collections.sort is an Object Expression that defines a custom Comparator class.

You’ll notice that the definition of compare is full of null safe expressions as indicated the by ? and ?: opeartors. As a side note, I really like how Kotlin has an arrayListOf() function that let’s you create an ArrayList. Sure it does the same thing as Arrays.asList, but again, it’s more concise.

You can view part 10 here

Kotlin Koans—Part 10

This part of the Kotlin Koans tutorial involved extension functions. This is a construct I have never seen in programming before, so it took me a little bit to get an idea of what it is and when to use this feature.

It seems as if the idea here is to add features to a class without have to use inheritence or some sort of delegate object. Here is the Kotlin code.

//This is the class we are adding to
data class RationalNumber(val numerator: Int, val denominator: Int)

//We are adding an r() method to Int which
//returns an instance of RationalNumber
fun Int.r(): RationalNumber = RationalNumber(toInt(), 1)

//We add an r() method to Pair which returns an
//instance of RationalNumber
fun Pair.r(): RationalNumber = RationalNumber(first, second)

The Kotlin documentation has a motivation section that explains the purpose behind extensions. They explain that in many cases in Java, we end up with FileUtils, StringUtils, *Utils classes. In the ideal world, we would want to add features to say the List class directly rather than having a ListUtils class with a bunch of static methods.

We get something like this in JDK8 with default methods that can get placed in an interface. However, that still requires us to extend and interface to add extra methods. Extensions let us work directly on the classes we are already using.

You can click here to see Part 9

%d bloggers like this: