Category: development

Project Euler problem 22 in Erlang

At work I’m in a reading group covering Bruce Tate’s Seven Languages in Seven Weeks. Each week we get together for an hour to discuss the current language. One person or duo is responsible for giving a presentation on the current language. This week was Erlang, and I was partly responsible for the presentation. After reading the chapter, I was trying to find a small program I could write in order to demonstrate some of the concepts discussed. I settled on problem 22 of Project Euler.

The problem is as follows:

Using names.txt (right click and ‘Save Link/Target As…’), a 46K text file containing over five-thousand first names, begin by sorting it into alphabetical order. Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list to obtain a name score.

For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, COLIN would obtain a score of 938 53 = 49714.

What is the total of all the name scores in the file?

This is the very first problem I tried to solve with Erlang. Fortunately, the documentation on the language is pretty good, and the standard libraries are nice too. When I started programming in 1993 in college, my first language was Pascal, but I haven’t done much in a functional language since then, and working in Java exclusively for my occupation since 2000 hasn’t really kept me in the functional frame of mind. Anyway, to the code.

-module(euler).
-export([prob22/0]).

% http://projecteuler.net/index.php?section=problems&id=22
% problem 22 in project euler.
% Load the names in names.txt, then sort them alphabetically
% Then working out the alphabetical value for each name, multiply this value 
% by its alphabetical position in the list to obtain a name score.
% Then find the total of all name scores in the file.
%
% I massaged input by putting all names on their own line and remove quote characters
% before running this program.

prob22() -> 
    UnsortedNameList = readlines("names.txt"),
    SortedNameList = lists:sort(UnsortedNameList),
    % convert the Names to the integers representing the characters.
    % but don't accept the \n at the end of each name.
    NumberNameList = lists:map(fun(Name) -> [X-64 || X <- Name, X>64] end, SortedNameList),
    % NumberNameList contains all the names adjusted so A=1, B=2, etc.
    addNameValues( NumberNameList, 1).

% add the name values in the list, as specified in the requirements of problem 22.
addNameValues( [], _ ) -> 0;
addNameValues( [Head|Tail], Index ) -> 
    HeadValue = lists:foldl(fun(X, Sum) -> X + Sum end, 0, Head),
    HeadValue*Index + addNameValues(Tail, Index+1).
    

% file reading blatantly borrowed from http://www.trapexit.org/Read_File_to_List
readlines(FileName) ->
    {ok, Device} = file:open(FileName, [read]),
    get_all_lines(Device, []).

get_all_lines(Device, Accum) ->
    case io:get_line(Device, "") of
        eof  -> file:close(Device), lists:reverse(Accum);
        Line -> get_all_lines(Device, [Line|Accum])
    end.

Not any big rocket science. Note that I modified the source file by putting each name on its own line and removing the quotes around each name, so maybe that’s cheating, but I only had a little while to work on this, so I didn’t want to spend the time really looking into getting around that.

In the book, each of the functions were quite terse with their variable names and most were a single line. I didn’t feel like that did the reader any favors, but just for fun I thought I would try to condense it a bit. Here’s what I came up with

-module(eulerSmall).
-export([prob22/0]).

prob22() -> add( lists:map(fun(N) -> [X-64 || X <- N, X>64] end, lists:sort(readlines("names.txt"))), 1).

% add the name values in the list, as specified in the requirements of problem 22.
add( [], _ ) -> 0;
add( [H|T], I ) -> I * lists:foldl(fun(X, Sum) -> X + Sum end, 0, H) + add(T, I+1).

% file reading blatantly borrowed from http://www.trapexit.org/Read_File_to_List
readlines(FileName) ->
    {ok, Device} = file:open(FileName, [read]),
    get_all_lines(Device, []).

get_all_lines(Device, Accum) ->
    case io:get_line(Device, "") of
        eof  -> file:close(Device), lists:reverse(Accum);
        Line -> get_all_lines(Device, [Line|Accum])
    end.

Notice that by combining all of the list manipulation together, the prob22() function now takes a single line. That’s kind of fun.

Mock Testing Spring MVC Controller

I’m in the midst of implementing a Spring MVC based web application. We have hudson for continuous integration builds that run all of our unit tests, but testing spring MVC controllers still just isn’t quite as easy as I would hope. There is some information on testing the controllers in the official spring documentation, but for someone like me that’s not a spring guru, or just starting out, it wasn’t enough to get me going. I recently was introduced to Mockito, so I spent a bit of time today trying to get a test for our controller using Mockito. It was simple and took no time at all.

I have yet to try it in a more complex controller method, but I think it’ll work just fine , especially when I get some utilities in place to initialize the mock objects that are commonly used by the controller. As it stands, here’s what I did to get it going. This tests the controller as a POJO, without using any spring configuration or capabilities.

Here is the controller I wish to test. Obviously I stripped out a bunch of code not needed for this demonstration.

@Controller
@RequestMapping( "/admin/survey" )
public class SurveyAdminController
{
    
    @Resource
    private SurveyService surveyService;
    
    @Resource
    private UnitService unitService;
    
    @Resource
    private OrganizationService orgService;
    
    /**
     * Show the table of existing questions to the user
     * @param model
     * @return
     */
    @RequestMapping( "questions" )
    public ModelAndView listQuestions()
    {
        ModelAndView mav = new ModelAndView( "/admin/questionList");
        List<SurveyQuestion> questions = surveyService.findAllQuestions();
        mav.addObject( "questions", questions );
        List<UnitFeature> features = unitService.getAllFeatures();
        mav.addObject( "features", features );
        List<Organization> organizations = orgService.getAll();
        mav.addObject( "organizations", organizations );
        return mav;
    }
}

For this simple test, it’s just going to validate that the view name is correct, and that the model that’s returned contains the correct information.


package com.bi.controller;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.servlet.ModelAndView;

import com.bi.data.OrganizationService;
import com.bi.data.SurveyService;
import com.bi.data.UnitService;
import com.bi.data.corp.Organization;
import com.bi.data.survey.SurveyQuestion;
import com.bi.data.unit.UnitFeature;
import com.bi.web.util.MessageUtil;

public class SurveyAdminControllerTest
{
    @Mock SurveyService surveyService;
    @Mock UnitService unitService;
    @Mock OrganizationService orgService;
    @Mock MessageUtil messageUtil;

    @Before
    public void setup()
    {
        // this must be called for the @Mock annotations above to be processed.
        MockitoAnnotations.initMocks( this );
    }
    
    @Test
    public void testListQuestions()
    {
        // setup our mock question list
        List<SurveyQuestion> questions = new ArrayList<SurveyQuestion>();
        questions.add( new SurveyQuestion( "asdf", null ));
        when( surveyService.findAllQuestions()).thenReturn( questions );

        // setup our mock feature list
        List<UnitFeature> features = new ArrayList<UnitFeature>();
        features.add( new UnitFeature( "TEST FEATURE" ));
        when( unitService.getAllFeatures()).thenReturn( features );

        // setup our mock organization list
        List<Organization> orgs = new ArrayList<Organization>();
        orgs.add( new Organization( "TEST ORGANIZATION" ));
        when( orgService.getAll()).thenReturn( orgs );

        // create an instance of the controller we want to test
        SurveyAdminController controller = new SurveyAdminController();

        // since we aren't using spring, these values won't be injected, so set them manually
        ReflectionTestUtils.setField( controller, "surveyService", surveyService );
        ReflectionTestUtils.setField( controller, "unitService", unitService );
        ReflectionTestUtils.setField( controller, "orgService", orgService );

        // call the method under test
        ModelAndView mav = controller.listQuestions();

        // review the results.
        assertEquals( questions, mav.getModel().get( "questions" ));
        assertEquals( features, mav.getModel().get( "features" ));
        assertEquals( orgs, mav.getModel().get( "organizations" ));
        assertEquals( "/admin/questionList", mav.getViewName());
    }
}

The comments should be pretty self explanatory in the test class. The awesomeness of Mockito is how you setup the mocks. A line like this:

        when( unitService.getAllFeatures()).thenReturn( features );

reads very nicely and sets up the return value for my service object, which keeps me from needing a database or anything setup in order to test my controller method. Mockito ftw.

Ajax Post to Spring MVC Controller

I wanted to submit an html form to my Spring MVC Controller, but I wanted to do it with ajax. I had previously submitted a single value and returned a JSON object for use in jquery, but I had yet to do it with an entire form. I’m a java guy, so there may be better ways to do the html stuff, but this is how I did it and thought I would share some of what I learned along the way.

First, here’s my form.

    <div id='newAnswerDialog'>
        <form id='newAnswerForm' name='newAnswerForm' action='/admin/survey/answer/new' onsubmit='return false;' method='post'>
            <label for='severity'><spring:message code='input.answer.severity' text='Severity' /></label>
            <select id='answerSeverity' name='answerSeverity'>
                <option value='MINIMAL'>MINIMAL</option>
                <option value='MINOR'>MINOR</option>
                <option value='MODERATE'>MODERATE</option>
                <option value='SEVERE'>SEVERE</option>
                <option value='URGENT'>URGENT</option>
            </select><br/>
            <label for='answerText'><spring:message code='input.answer.text' text='Answer Text' /></label>
            <input type='text' id='answerText' name='answerText'/><br/>
            <label for='requiresReason'><spring:message code='input.answer.requiresReason' text='Requires Reason?' /></label>
            <input type='checkbox' id='requiresReason' name='requiresReason' onclick='toggleReasonControls(this)'/><br/>
            <label for='answerReasons'><spring:message code='input.question.reasons' text='Reasons' /></label>
            <select class='newReason' id='answerReasons' name='answerReasons' multiple='multiple'>
                <c:forEach items='${reasons}' var='reason'>
                    <option value='${reason.key}'>${reason.text}</option>
                </c:forEach>
            </select><br/>
            <input type='button' onclick='createNewAnswer()' value='<spring:message code='submit' />'/><input type='button' onclick='cancelNewAnswer()' value='<spring:message code='cancel' />' />
        </form>
    </div>

It’s JSP using the JSTL and the Spring tag libraries, but it’s all basically html. You can see that I have some javascript in the requriesReason checkbox that is called when it is clicked. The javascript function just enables everything with a css class of newReason based on the state of the requiresReason checkbox. This will come into play later.

When the user clicks the button labeled submit, it calls the javascript function called “createNewAnswer()” which looks like this


        function createNewAnswer()
        {
            $.post( '<c:url value='/admin/survey/answer/new' />'
                    , $('#newAnswerForm').serialize()
                    , function( data )
                    {
                        // add the option to the list of answers, and select it.
                        var options = $('#'+data.severity.toLowerCase()+'Answer').attr( 'options' );
                        options[options.length] = new Option( data.text, data.key, true, true );
                        $('#newAnswerDialog').dialog( 'close' );
                    }
                    , 'json' );
        }

This uses the jquery post function to submit the values to the server and read the response.

The first parameter is the URL to submit to. I’m using the JSTL c:url tag so that the web application context is added to the url. Your controller method must be configured to accept POST requests since we are submitting via POST, not GET. I’ll show the controller implementation later on.

The second parameter is the data you want to submit to the Controller. This is where I found it a bit tricky. Getting the form is simple with jquery. Getting the data is also simple using jquery’s serialize() method. The trick is in the fine print in the serialize method. You can find the documentation here. At the time of this writing, it says:

Note: Only “successful controls” are serialized to the string. No submit button value is serialized since the form was not submitted using a button. For a form element’s value to be included in the serialized string, the element must have a name attribute. Data from file select elements is not serialized.

It then links to this page that has an explanation of what a “successful control” is. The gist of it is that the control cannot be disabled. The control must have a name. Checkboxes that are not checked may not be submitted. At least, those are the parts that affected me when trying to get this to work.

So, knowing that, it affects how I create the controller method to handle the post. Here’s the implementation:

    @RequestMapping( value='answer/new', method=RequestMethod.POST)
    public ResponseEntity<String> newAnswer( @RequestParam(value='answerSeverity', required=true ) String severity
            , @RequestParam( value='answerText', required=true ) String text
            , @RequestParam( value='requiresReason', required=false, defaultValue='false' ) boolean requiresReason
            , @RequestParam( value='answerReasons', required=false ) List<Long> reasonKeys
            )
    {
        Severity sev = Severity.valueOf( severity );
        SurveyAnswer answer = new SurveyAnswer( text, sev );
        answer.setRequiresReason( requiresReason );
        if ( requiresReason )
        {
            // add all the reasons
            List<SurveyAnswerReason> reasons = surveyService.findReasonsByKey( reasonKeys );
            for( SurveyAnswerReason reason : reasons )
            {
                answer.addReason( reason );
            }
        }
        answer = surveyService.persist( answer );
        return createJsonResponse( answer );
    }

Notice that the requiresReason, and answerReasons are marked as optional. This is because they may or may not be passed. If you have a problem with your mapping here, you may get a 400 error with a message that says, “The request sent by the client was syntactically incorrect ()” if you look at it in the XHR response. That’s what I was getting from tomcat. Once I set the required to false on the optional attributes, things went through much better.

The rest of the code is just for creating our entity and saving it. You can do whatever you want with the data you post. The next critical part is in the createJsonResponse method. You’ll notice that the controller method doesn’t return a String for the view, and it doesn’t return a ModelAndView. It is returning a ResponseEntity, which I create in the createJsonResponse method, which is as follows:


    private ResponseEntity<String> createJsonResponse( Object o )
    {
        HttpHeaders headers = new HttpHeaders();
        headers.set(  'Content-Type', 'application/json' );
        String json = gson.toJson( o );
        return new ResponseEntity<String>( json, headers, HttpStatus.CREATED );
    }

It’s a very simple method that just creates the ResponseEntity and sets the headers so the javascript receiving the response gets json as it is expecting (see the last parameter in the $.post method, it says we are expecting json in return.)

I am using Google’s JSON library to convert my entity object to a JSON object that I can return to the view. With that conversion, I can use the field names in the java object to reference the values in the returned JSON object. It’s really quite slick.

So, now we’ve done the work on the server and returned the response to the browser. The third argument to the $.post jquery method is a function that is called on successful return of the json object from the server. Here is my function again:

                    function( data )
                    {
                        // add the option to the list of answers, and select it.
                        var options = $('#'+data.severity.toLowerCase()+'Answer').attr( 'options' );
                        options[options.length] = new Option( data.text, data.key, true, true );
                        $('#newAnswerDialog').dialog( 'close' );
                    }

I’m taking the JSON object I receive and adding a new option to a select box further down in the page, and marking that option as selected. As I said above, I’m referencing the properties of the JSON object using the field names in the Java object.

There is a way to get a javascript method called when the request fails, but it’s not built into jquery’s post method, and I haven’t taken the time go through that part yet.

So, there you have it. A fair amount of time of trial and error all summed up in about 1000 words, including code.

Simple Application Configuration With Spring

Inevitably it happens in every project. You’re coding along, and you have a “constant” that isn’t really constant. In my case, it was the number of minutes that should pass before a given token is invalid. 2 hours? Yeah, that sounds good… for now. But you feel all dirty if you put it right in a .java file. You could provide the value as a property to your bean if you are doing XML configuration, but is that really that much better? You want it in a properties file, because that’s one reason properties files exist, and it’s all configurable and stuff, right?

The company at which I spend my daylight hours has a ConfigurationService that takes care of hierarchical property overriding and all that. I’m sure it’s nifty. I didn’t want to write anything like that for the project on which I spend my evening/weekend hours, so I found something in spring that would do it for me and had it going pretty quickly.

Alright, here we go with the simple solution built right into Spring.

My project is a multi-module maven project with a single parent pom and each module under that parent project. I believe it’s a fairly common setup. In a module early in the dependency tree, I created a spring configuration file that looks like this.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!-- a bean for storing configuration properties. -->    
    <bean id="runtimeConfig" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="locations">
            <list>
                <value>classpath*:/META-INF/config/*.properties</value>
                <value>file:///${user.home}/myproject.properties</value>
            </list>
        </property>
    </bean>
    
</beans>

Yep, one bean. It creates a single java Properties object from the list of files I give it, from top to bottom, with properties in later files overriding properties in earlier files. In this case, I added the wildcard /META-INF/config/*.properties, so all of my other modules can put their default property values in properties files in META-INF/config and if they depend on this module, it’ll find them. Note that you must use classpath*: and the path must have at least one directory in it or else you will likely read from the location in only one of your jar files.

Some considerations here:

If you are using another jar, say from a third party vendor, and they have properties in META-INF/config, then you may load all those properties too. I haven’t seen it in my limited testing, but that would stink. You might be better off changing that to something like META-INF/config/myproject-*-default.properties, then you would be more sure that you will only get your properties. You don’t really want to put specific properties file names in here because you don’t want this module, which is early in the dependency tree, to know explicitly about properties files in modules it knows nothing about.

Also, depending on how your properties files within your jar files are named, your property overriding may not occur as you hoped. Hopefully, you don’t have properties with the same name in different properties files, in which case this is a non-issue. If you do have properties with the same name in different properties files in your various modules you may have to be even more careful in how they are loaded in your bean definition.

Finally, with the file:///${user.home}/myproject.properties value last, you can override any of the properties in the default configuration files with properties in a single file in your user home directory. This is pretty cool. This way your application can define the default timeout at 120 minutes but when you are testing and don’t want to wait 2 hours for a timeout you just set the value in your home directory configuration file to 1 minute and Bob’s your uncle. No risk of checking in that configuration value because it’s not under source control.

Another thing you could likely do here is to load different properties files based on some environment variable. You want to test against postgres? Set an environment property when you run your build and set the pattern to something like file:///${user.home}/${dbtype}-config.properties. Each ${dbtype}-config.properties file could give connection information for the specified database, so your home directory would have postgres-config.properties, oracle-config.properties, mysql-config.properties, etc. Then, in hudson, bamboo, or whatever you define a property for the build that has the database type in it. For maven command line, your command would be something like this. I tried it with a simple property and it worked great.

mvn -DargLine="-Ddbtype=postgres" test

Ok, moving on. Now we want to use this fancy properties object we’ve created.

So, we’ve moved down the dependency tree to a module that depends on my module with the fancy runtimeConfig bean. In my spring configuration within that module, I do the following:

<!-- all that other spring stuff you have defined -->


    <import resource="classpath:/META-INF/spring/domain-api-beans.xml"/>
    <context:property-placeholder properties-ref="runtimeConfig" />

    <bean id="yourDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

So, we import our previous spring configuration file so we can use the awesome runtimeConfig bean. Next, we create a property-placeholder so we can reference the properties in our runtimeConfig within this very same configuration file. Then, magically, all of the ${…} values in our datasource definition are replaced by the values in our properties files.

“BUT WAIT!” You say, “This isn’t the use case you mentioned at the top of the post. I can do this by specifying the locations of the property-placeholder.” Yes. Yes you can. This was just extra credit to show that we don’t have to point to the same locations in two definitions. Just once will do.

So, now we have a service or some bean or something, and we want to get our expiration configuration value out of it. How would we accomplish such a thing? Funnily enough, that’s the easiest part of all this.


    // all my service bean code or whatever

    // here we read the value from the runtimeConfig bean using Spring's expression language.
    @Value("#{runtimeConfig['account.validation.expiration.minutes']}" )
    private long minutes;

    // here's a nice method to return the value so I don't have that ugly @Value thing everywhere I want to reference the value.
    public long getValidityMinutes()
    {
        return minutes;
    }
    
    // the rest of my service bean code and stuff

Voila, I’ve successfully read the property from the file in my user home, and if it’s not set there, then I’ve read it from the reasonable defaults set within the properties file in the jar that uses the value. I didn’t have to write any service, bean, or anything to implement a hierarchical properties based configuration system for my application.

Update: One thing I failed to mention, which you probably already figured out, is that since the runtimeConfig is just a bean, if you know that you are going to be reading a ton of properties out of it, you could just inject the entire bean, something like this.

@Resource( "runtimeConfig" )
private Properties config;

Spring MVC and JSR-303 Validation Groups

@Valid. That wonderful little annotation. In my Spring controller I do something like this.

    @RequestMapping( value="/editAccount", method=RequestMethod.POST )
    public String postEditAccount( Model model, HttpServletRequest request, 
            @Valid AccountInfo info, BindingResult infoResult )

and everything is great. I know that all of the JSR-303 annotations I’ve put on my AccountInfo bean have been validated and the data is all correct and good. Let’s say that my AccountInfo bean looks something like this.

public class AccountInfo
{

    @NotNull
    private String username;
    @NotNull
    private String newUsername;
    @NotNull
    private String confirmNewUsername;
    
    @NotNull
    private String password;
    @NotNull
    private String newPassword;
    @NotNull
    private String confirmNewPassword;
    
    @NotNull
    private String firstName;
    @NotNull
    private String lastName;
    @NotNull
    private String phone;
    private String fax;
    
    // constructors, getters, setters, etc. down here
}

Suddenly, everything isn’t so hunky dory anymore. Fortunately for us, JSR-303 has a great mechanism for only validating some portion of the object. It’s known as validation groups. There’s plenty of information out there on them, so I’ll give you the extreme Reader’s Digest version. Basically, you specify a list of marker interfaces in your validation annotations, and then when you call the validator, you can also pass in a list of the marker interfaces that you would like to validate against. Ok, that sentence doesn’t make much sense unless you already know about groups. So, here’s a new version of AccountInfo that demonstrates.


public class AccountInfo
{

    @NotNull( groups={ChangeUsername.class} )
    private String username;
    @NotNull( groups={ChangeUsername.class} )
    private String newUsername;
    @NotNull( groups={ChangeUsername.class} )
    private String confirmNewUsername;
    
    @NotNull( groups={ChangePassword.class} )
    private String password;
    @NotNull( groups={ChangePassword.class} )
    private String newPassword;
    @NotNull( groups={ChangePassword.class} )
    private String confirmNewPassword;
    
    @NotNull
    private String firstName;
    @NotNull
    private String lastName;
    @NotNull
    private String phone;
    private String fax;
    
    // constructors, getters, setters, etc. down here
    
    public interface ChangePassword {};
    public interface ChangeUsername {};

}

Now we’ve told the validator that when we run the validator without any groups, we want it to validate firstName, lastName, and phone. If you don’t specify any groups, they get the Default.class group. BUT, if we run the validator passing in the AccountInfo.ChangePassword.class, then it will only validate password, newPassword, and confirmNewPassword. If we want to do both, then we can pass in AccountInfo.ChangePassword.class AND Default.class and it will validate both groups. That’s awesome sauce right there. Now, we can use this same backing bean in the page where the user is created which contains all the fields, we can use it in the edit account info page which only has the stuff validated by Default, we can use it in our change password page, and we can also use it in our change username page, and in each case, we only validate the portions that we are concerned about for those pages. One bean for all four pages.

With that worked out, we should be able to just add the groups to our @Valid annotation, right? Nope. Wait, what? All that work to put in validation groups and we can’t even use them with the JSR-303 sanctioned validation annotation? Yep, that’s right. There’s an improvement in Spring’s Jira to add a new @Valid annotation that will allow you to specify groups, but until that happens, you’ll have to run the validator yourself.

I think it sound worse than it is. As you can see in the controller method I put at the start of this post, that after each @Valid annotated object, you need to have the BindingResult in order to see the errors. Then, in your controller method you have to check the BindingResult in order to see if there are errors, if there are, do something, if not, do something else. So, how is that any different than having to just run the check yourself? Here’s what I did.


    /**
     * Test validity of an object against some number of validation groups, or
     * Default if no groups are specified.
     * 
     * @param result Errors object for holding validation errors for use in
     *            Spring form taglib. Any violations encountered will be added
     *            to this errors object.
     * @param o Object to be validated
     * @param classes Validation groups to be used in validation
     * @return true if the object is valid, false otherwise.
     */
    private boolean isValid( Errors result, Object o, Class<?>... classes )
    {
        if ( classes == null || classes.length == 0 || classes[0] == null )
        {
            classes = new Class<?>[] { Default.class };
        }
        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<Object>> violations = validator.validate( o, classes );
        for ( ConstraintViolation<Object> v : violations )
        {
            Path path = v.getPropertyPath();
            String propertyName = "";
            if ( path != null )
            {
                for ( Node n : path )
                {
                    propertyName += n.getName() + ".";
                }
                propertyName = propertyName.substring( 0, propertyName.length()-1 );
            }
            String constraintName = v.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName();
            if ( propertyName == null || "".equals(  propertyName  ))
            {
                result.reject( constraintName, v.getMessage());
            }
            else
            {
                result.rejectValue( propertyName, constraintName, v.getMessage() );
            }
        }
        return violations.size() == 0;
    }

Alright, it’s a pretty simple method, but we’ll walk through it.


        Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<Object>> violations = validator.validate( o, classes );

Here we get the validator instance and get the set of violations back. This is based on the validation groups that were passed in, or Default if there were none passed. I believe I read somewhere that you can actually get the Validator injected by Spring, but I haven’t played with it yet to find out. If you do and it works, let me know!

Next is the part where we take the JSR-303 validations and map them to Spring form errors.


            Path path = v.getPropertyPath();
            String propertyName = "";
            if ( path != null )
            {
                for ( Node n : path )
                {
                    propertyName += n.getName() + ".";
                }
                propertyName = propertyName.substring( 0, propertyName.length()-1 );
            }

We get the property name of the violation, which will hopefully map to the “path” in the spring input tag you are using. I haven’t tested this on anything with any depth (for instance, if your bean contains an object that also has validation annotations on it) so I’m not sure how it’ll work there. Once again, if you find out, leave a comment. Anyway, now that we have the property name, we can use that later on to tell Spring which field failed validation so the correct errors field can be shown.


            String constraintName = v.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName();

Now we get the name of the constraint that failed. In all cases above, it would be NotNull. If you annotation is something like @Size( min=85 ) then the constraint would be Size. We use this so we can get error messages mapped the same way spring binding violations do, so if you are using custom messages in your messageSource for your fields or constraint messages, then this should work just the same.


            if ( propertyName == null || "".equals(  propertyName  ))
            {
                result.reject( constraintName, v.getMessage());
            }
            else
            {
                result.rejectValue( propertyName, constraintName, v.getMessage() );
            }

Finally, before returning the true or false, we have to add the violations to the Errors object. If we have a propertyName, then that means it’s a field error. If we don’t, it’s a global object error, which ought to happen if you use a class level validation annotation instead of a field level validation annotation. Yep, I’m going to say it one more time. I haven’t tested that yet, but it won’t be long before I do since I’ve got to get a class level validator to ensure the newPassword and confirmNewPassword fields contain the same value.

So, that’s a lot of explaining for a single method, but hopefully it shows that adding this validation really isn’t that much more difficult than checking the BindingResult that Spring gives back to you after the default @Valid processing. In places where I don’t have to use validation groups, I’m obviously still going to use the @Valid annotation as is, and if Spring gives me a new annotation I can use to run validation groups, I’ll jump to that and rip this out right away. BUT, until then, this will have to do.

Finally, here’s how I call that method in my controller.


    @RequestMapping( value="/editAccount", method=RequestMethod.POST )
    public String postEditAccount( Model model, HttpServletRequest request, 
            AccountInfo info, BindingResult infoResult )
    {
        if ( !isValid( infoResult, info, AccountInfo.ChangePassword.class, AccountInfo.ChangeUsername.class ))
        {
            return "editAccount";
        }
        // otherwise we process the form and do stuff.
    }

Obviously, you would want to move the isValid method out of this controller and into something that can be shared between Controllers.

JSP Date Formatting

I had an input field that took a date type as mentioned in my previous post. Now the problem was, while I input it in the form MM/dd/yyyy, when I was displaying it on the page for the user to modify, it would come back with time, timezone, all sorts of crap definitely NOT in MM/dd/yyyy format. This caused the form submission to fail unless the user corrected the field every time because date conversion would fail with the huge, lame format.

One wrinkle was that I wanted to support internationalization. While our application currently doesn’t have anything other than en_US right now, I want to make sure I am getting the right date pattern for all instances. So, this is what I did.

<label id="birthday_label" for="birthday" title="<spring:message code="user.birthday.alt" />">
    <spring:message code="user.birthday" />
</label>

<spring:message code="dateFormat" var="dateFormat" />

<input id="birthday" name="birthday" type="text" 
        value="<fmt:formatDate value="${reg.birthday}" 
        type="date" pattern="${dateFormat}" />" />

I have my spring message bundle available, and in that bundle, I have a field called dateFormat which contains the string MM/dd/yyyy. It’s also the field used for doing the date conversion on input. I needed to get the format for use in the fmt:formatDate tag, which is given as the value of the input tag. I’m not a fan of tags within attribute values of tags, but what can you do.

Well, I couldn’t have a tag, in a tag, in an attribute of a tag. Apparently you can only take that so far. So, the trick was using the var of the spring:message to store the dateFormat in something that I could later reference as ${dateFormat} in the pattern of the fmt:formatDate.

Spring MVC binding to Strings and Dates

I spent the entire morning trying to figure out how to get Spring MVC to allow for Null in my Date field.  I would get an exception if the Date value in the form was left Null.  Once I found that out, I wasn’t getting any validation messages for all the fields marked as @NotNull.  It turns out Spring just set the value to empty string instead of null if the field was empty.  Hibernate’s JSR-303 implementation has a @NotEmpty validation, but I decided to try to keep it to spec.

So, I implemented a custom @InitBinder for my @Controller and had an anonymous implementation of a custom editor all based off an answer on stackoverflow.com.  Finally, I found this bug logged against Roo

https://jira.springsource.org/browse/ROO-190

Using that single line in my @InitBinder method I was then able to set Dates to null.  For the second problem, I used this very helpful blog post by Stefan Reuter

http://blogs.reucon.com/srt/2007/11/25/spring_mvc_null_or_an_empty_string.html

So, now my @InitBinder method looks like this.

    @InitBinder
    public void allowEmptyDateBinding( WebDataBinder binder )
    {
        // Allow for null values in date fields.
        binder.registerCustomEditor( Date.class, new CustomDateEditor( new SimpleDateFormat( getDatePattern()), true ));
        // tell spring to set empty values as null instead of empty string.
        binder.registerCustomEditor( String.class, new StringTrimmerEditor( true ));
    }

And as simple as that I get null instead of empty string for my string values, and I can allow null values in my non-required date fields. Too bad it took me 6 hours this morning to find the answers.