Tag: java

Using Mockito To Test Spring MVC Ajax Interaction

So, I shared in Ajax Post to Spring MVC Controller what I learned about making an ajax post to a Spring MVC Controller. Then I shared in Mock Testing Spring MVC Controller what I learned about using Mockito to test my Spring MVC controller. So what about testing my RequestHandler that handles the ajax post and returns a JSON object? Well, as Samuel L. Jackson says in Jurassic Park, “Hold on to your butts”

Here’s the method that handles the ajax post of form data.

    @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 );
        this.getAnswers( sev ).add( answer );
        return createJsonResponse( answer );
    }

    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 );
    }

You can read the previous post for information on what’s going on here, but basically, we handle the form post, create a new SurveyAnswer, and then return the created answer as a JSON object using the createJsonResponse method.

In order to mock test this, I’m going to have to mock all the calls to the surveyService methods. That would be findReasonsByKey, and persist. The persist was a bit tricky because I wanted it to just return the answer that was passed as an argument to ensure that the controller was creating the answer correctly. Here’s the code to do that.


        when( surveyService.persist( any( SurveyAnswer.class ))).thenAnswer(
                new Answer<SurveyAnswer>()
                {
                    @Override
                    public SurveyAnswer answer( InvocationOnMock invocation ) throws Throwable
                    {
                        Object[] args = invocation.getArguments();
                        return (SurveyAnswer) args[0];
                    }
                });
        when ( surveyService.findReasonsByKey( anyCollectionOf( Long.class ))).thenReturn( getReasons() );

I put it in my @Before annotated setup method in my unit test. I didn’t come up with it myself, I adapted it from an excellent answer to this question on StackOverflow.com. That snippet allows me to just return the argument passed to the method, which is basically what JPA would do, other than setting the key and version, which I don’t really need for my test anyway. The mocked out findReasonsByKey just returns a list of objects that I’m creating elsewhere for testing purposes only.

So, on to the test. Here’s the code:


    @Test
    public void testNewAnswerWithReasons()
    {
        ResponseEntity<String> response = controller.newAnswer( answerSeverity.name(), answerText,
                true, getReasonKeys() );
        assertEquals( "application/json", response.getHeaders().get( "Content-Type" ).get( 0 ));
        SurveyAnswer answer = gson.fromJson( response.getBody(), SurveyAnswer.class );
        assertEquals( getSingleAnswerWithReasons(), answer );
    }

There are some helper methods that create the object graph needed for the SurveyAnswer. It then calls the method on the controller (which is also initialized in the @Before setup method) and checks the result. I’m really looking for two things. First, that the response has the Content-Type set correctly to application/json, and second, that I get an answer that corresponds to the values I passed in. Here again, I use Google’s GSON library for converting from my JSON string to my Java object. Once that is done, I can just test for equality with the answer I’m expecting. Obviously, for that to work, you’ll need to make sure your equals method is correct, but that’s an issue well addressed elsewhere on the internet and well beyond the scope of this post.

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.

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.

Accessing Spring Session Beans in JSP

I’m using Spring MVC in a project.  I wanted to create a session scoped bean that I could reference directly from my JSP.  In this case, it was a bean for holding status or error messages for display in the UI.  It would keep a queue of messages, and would clear them when displayed.

The interface for my MessageUtil class was simple, with an addMessage method for adding a message to the queue, and a getFlashMessages method that gets all messages as a list and clears the internal queue.

The implementation could be equally simple.  Mine has a touch more code in order to pull the actual message text from a resource bundle, but the class definition is very simple

public class MessageUtilImpl implements MessageUtil, Serializable
{
// implementation here
}

In my spring context configuration file, I defined the bean as follows:

    <bean id="messageUtil" class="mypackage.MessageUtilImpl" scope="session">
        <aop:scoped-proxy proxy-target-class="false"/>
        <property name="messageSource" ref="messageSource" />
    </bean>

Where the messageSource contains the bundle for messages. The real ticket here is the aop:scoped-proxy configuration.

Since I wanted to inject this message utility class into my Spring MVC controllers (which are of a greater scope than session scope) it was puking at me. Adding aop:scope-proxy configuration to the bean definition (which apparently isn’t available yet as an annotation, which is why I had to configure in xml instead) allows Spring to use AOP to inject the session bean into the controller for the thread that is processing the request, tying my messageUtil to the one that has been constructed for the current session.

One item of note is the proxy-target-class attribute. If you set it to false, then spring aop will use a java interface based proxy. This means that your bean must have an interface and an implementation, and that everywhere you use the bean, you must reference it via the interface and NOT the implementation. Well… DUH. If you have an interface and an impl, and you are referencing the impl, then what can I say? If you set that value to true, then spring aop will use cglib (which now must be on your build path, probably runtime path) to proxy the implementation class, meaning you don’t need to have an interface and implementation, you can simple have a class. I didn’t want to need cglib, so I chose interface based proxy.

With that magic done, now all I had to do was reference my messageUtil bean in the jsps so I could call the getFlashMessages() method and display them.

Now, I’m no JSP guru. I’ve spent the last 3 years in JSF land. I’m sure I could wire this up to get the messages via ajax and do something super awesome… but I didn’t. I’m using the Pines Notify jQuery plugin to show a simple growl-type message.

<script type="text/javascript" >
    <c:forEach var="flashMessage" items="${sessionScope['scopedTarget.messageUtil'].flashMessages}" >
        $.pnotify( {
            pnotify_title: "${flashMessage.title}",
            pnotify_text: "${flashMessage.message}",
            pnotify_type: "${flashMessage.severity}",
            pnotify_shadow: true
        })
    </c:forEach>
</script>

Besides the aop:scoped-proxy, the thing that took the longest to figure out was how to get the stinking spring session bean. You can see that I’m accessing it like this

${sessionScope['scopedTarget.messageUtil'].flashMessages}

The answer is the ‘scopedTarget’ prefix to the bean name. Since it uses a dot in the name, you can’t use sessionScope.scopedTarget.messageUtil, so the way it’s referenced above is the only way I know how to do it. It took surprisingly long for me to find it.

I’m sure as soon as I publish this, someone will find a reference to it in the official spring documentation, but Adobe Reader didn’t find it in the 799 page Spring Documentation PDF I have.

That’s it for this one. Have fun with spring session scoped beans and jsp el.

Guice and JSF 2

As I’m sure you can tell from previous entries, I’ve been playing with JSF 2 in Google App Engine.  I decided to give Google’s Guice a try for dependency injection instead of Spring.  Why?  This is really just a learning app and why not try something new.

So how do you get Guice to play nicely with JSF?  One solution I saw online was to write a custom ELResolver for JSF that will do the injection.  I found this resource http://snippets.dzone.com/posts/show/7171 that had a full ELResolver implementation.  I had to modify it slightly to get it to work.  Namely, I had to move the Guice Injector creation out of getValue and into a private static variable.  I suspect I could make it not static, but I never gave it a try.  Here’s the source just in case that link dies at some point.  Again, I take no credit for this code other than the small modification mentioned.

/**
 * Bulk of the code taken from
 * http://snippets.dzone.com/posts/show/7171
 **/
package jota.soc.guice;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.ServletModule;
import java.beans.FeatureDescriptor;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.el.ELContext;
import javax.el.ELResolver;

/**
 */
public class GuiceResolver extends ELResolver
{

    Injector injector = Guice.createInjector(
            new ServletModule(),
            new SocGuiceModule() );

    //We only need to see the currently processed Objects in our Thread, that
    //prevents multithread issues without synchronization
    private static ThreadLocal currentlyProcessedThreadLocal = new ThreadLocal()
    {
        @Override
        protected Object initialValue()
        {
            return new LinkedList();
        }
    };

    //Im not sure if the synchronized lists seriously slow down the whole EL
    //resolving process
    private static List<WeakReference> alreadyInjectedObjects = Collections.
            synchronizedList( new LinkedList() );

        @Override
    public Object getValue( ELContext context, Object base, Object property )
    {

        //if the list of currently processed property objects doesnt exist for this
        //thread, create it
        List<Object> currentlyProcessedPropertyObjects = (List<Object>) currentlyProcessedThreadLocal.
                get();

        //Handle only root inquiries, we wont handle property resolving
        if ( base != null )
        {
            return null;
        }

        //checking if this property is currently processed, if so ignore it -> prevent
        //endless loop
        if ( checkIfObjectIsContained( property,
                currentlyProcessedPropertyObjects ) )
        {
            return null;
        }

        //add the to-be-resolved object to the currently processed list
        currentlyProcessedPropertyObjects.add( property );

        //now we can savely invoke the getValue() Method of the composite EL
        //resolver, we wont process it again
        Object resolvedObj = context.getELResolver().getValue( context, base,
                property );

        //ok, we got our result, remove the object from the currently processed list
        removeObject( property, currentlyProcessedPropertyObjects );

        if ( resolvedObj == null )
        {
            return null;
        }

        //ok we got an object
        context.setPropertyResolved( true );

        //check if the object was already injected
        if ( !checkIfObjectIsContainedWeak( resolvedObj, alreadyInjectedObjects ) )
        {
            injector.injectMembers( resolvedObj );
            //prevent a second injection by adding it as weakreference to our list
            alreadyInjectedObjects.add( new WeakReference( resolvedObj ) );
        }

        return resolvedObj;
    }

    /**
     * This method will search for an object in a Weak List. If there are any
     * WeakReferences on the way that were removed by the garbage collection
     * we will remove them from this list
     * @param object
     * @param list
     * @return
     */
    private boolean checkIfObjectIsContainedWeak( Object object,
                                                  List<WeakReference> list )
    {
        for ( int i = 0; i < list.size(); i++ )
        {
            WeakReference curReference = list.get( i );
            Object curObject = curReference.get();
            if ( curObject == null )
            {
                //ok, there is are slight chance that could go wrong, if you
                //have to prevent a double injection by all means, you might
                //want to add a synchronized block here
                list.remove( i );
                i--;
            }
            else
            {
                if ( curObject == object )
                {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * checks if an object is contained in a collection (really the same object '==' not equals)
     * @param object
     * @param collection
     * @return
     */
    private boolean checkIfObjectIsContained( Object object,
                                              Collection collection )
    {
        for ( Object curObject : collection )
        {
            if ( object == curObject )
            {
                return true;
            }
        }
        return false;
    }

    /**
     * removes an object from a list. really removes the given instance, not an other
     * object that fits equals
     * @param object
     * @param list
     */
    private void removeObject( Object object, List list )
    {
        for ( int i = 0; i < list.size(); i++ )
        {
            if ( list.get( i ) == object )
            {
                list.remove( i );
            }
        }
    }

    @Override
    public Class<?> getType( ELContext context, Object base, Object property )
    {
        return null;
    }

    @Override
    public void setValue( ELContext context, Object base, Object property,
                          Object value )
    {
    }

    @Override
    public boolean isReadOnly( ELContext context, Object base, Object property )
    {
        return false;
    }

    @Override
    public Iterator<FeatureDescriptor> getFeatureDescriptors( ELContext context,
                                                              Object base )
    {
        return null;
    }

    @Override
    public Class<?> getCommonPropertyType( ELContext context, Object base )
    {
        return null;
    }
}

That sure looks like a lot of code to me. I know Spring also provides a custom ELResolver for dependency injection. I found two links talking about resource injection here and here and thought I would try writing my own resource injector. Here’s how it ended up:

package jota.soc.guice;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.ServletModule;

import com.sun.faces.spi.InjectionProvider;
import com.sun.faces.spi.InjectionProviderException;
import com.sun.faces.vendor.WebContainerInjectionProvider;

/**
 * JSF injection provider for Guice.
 * @author Joel Weight
 */
public class GuiceInjectionProvider implements InjectionProvider
{
    public GuiceInjectionProvider()
    {
        System.out.println( "creating guice injection provider" );
    }

    /**
     * default injector provided by the web container.
     */
    private static final WebContainerInjectionProvider con =
                                                       new WebContainerInjectionProvider();

    /**
     * Custom guice injector that will load our modules.
     */
    private static final Injector injector = Guice.createInjector(
            new ServletModule(),
            new SocGuiceModule() );

    @Override
    public void inject( Object managedBean ) throws InjectionProviderException
    {
        // allow the default injector to inject the bean.
        con.inject( managedBean );
        // then inject with the google injector.
        injector.injectMembers( managedBean );
    }

    @Override
    public void invokePostConstruct( Object managedBean )
            throws InjectionProviderException
    {
        // don't do anything here for guice, just let the default do its thing
        con.invokePostConstruct( managedBean );
    }

    @Override
    public void invokePreDestroy( Object managedBean ) throws
            InjectionProviderException
    {
        con.invokePreDestroy( managedBean );
    }
}

It’s a very simple implementation. It delegates everything to the default container InjectionProvider, and then adds a touch of Guice. I then added this to web.xml:

    <context-param>
        <param-name>com.sun.faces.injectionProvider</param-name>
        <param-value>jota.soc.guice.GuiceInjectionProvider</param-value>
    </context-param>

And all my guice injections are occurring as expected. I am no longer using the custom ELResolver implementation. Obviously it’s not a general solution since I am instantiating my guice modules right in the provider rather than configuring it somehow, but it was enough for me right now.

If I run into any problems with this solution I’ll let you know, otherwise I would love to hear from any gurus as to how this could be problematic.

JSF 2, JSR-303, and you

In JSF 2, they added some nifty stuff.  One of the items they added was that JSF will seamlessly validate input values using a JSR-303 implementation if one is available.  “That’s nifty!” you say, “But how do I get an implementation of JSR-303 into my webapp?”

The reference implementation of JSR-303 is in hibernate validator version 4.  What if you don’t want to use hibernate?  That’s fine, because the validator project stands alone.  You don’t need to use any other parts of hibernate if you don’t want to.  Here’s what you should put in your maven pom in order to get hibernate 4 validators.

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>4.0.2.GA</version>
        </dependency>

Now you should be able to add JSR-303 validators to your project. Something like this should do:

    @NotNull
    @Size(min=3, max=10)
    private String username;

Now, when you tie an input control to that field in the bean, the value will be validated with the NotNull and Size constraints.

Obviously, the next thought is, “Awesome, now I can easily do multi-field constraints.”  For instance, you have a New Password form. You want the user to enter the password, and then to confirm the password. The simple answer is to write a validator that checks that the values of the two fields are equal and place the constraint on the Type, not on the Field. Something like the FieldMatch validator in the answer to this question on stackoverflow would be perfect.

So you implement the FieldMatch validator, and place it on your type. You then deploy your fancy JSF application and test the validator. Strangely your validator is never run. After reading more closely, you discover that JSF does “Field Level” validation using JSR-303 validators. Well, that should be easily enough overcome, right?

Next, you add an f:event tag to the page containing the bean to be validated. The event is preValidate, and you call a method on your bean containing the values. The method you call runs the validator manually. Perfect, right? More testing reveals that the your validator returns true every time, and even more than that, the values it’s testing are both null (which is why they are also equal).

Alright, let’s figure out what’s really going on.

After a half day of reading and testing, you finally go back to JSF basics and remember the JSF lifecycle. Alright, the phases are:

  1. Restore View
  2. Apply Request Values
  3. Process Validations
  4. Update Model Values
  5. Invoke Application
  6. Render Response

Notice that process validations comes before update model values. Well, no wonder putting the type constraint on the bean wasn’t validating the values that were set in the input controls. The values from the controls are validated before they are set on the bean. That explains why JSF 2 only does field level validation. They can take those validators, and apply them to the values that are set on the input controls before they are set in the bean.

So, what’s the answer to this problem? I haven’t decided yet. In this particular case, there are already JSF validators available for just this kind of validation, but what about the general case of type level validators. If I figure anything out, I’ll let you know. If you have any great ideas, chime in on the comments.

Spring Roo and JSF 2?

In my latest project we’ve been playing with Spring Roo.  You can read all about the advantages of it on that site, but the gist is that it creates your entities and JPA persistence code for them.  It will also configure your database connection, generate unit tests, generate a JSP/JSTL based UI with all of the Spring MVC controllers, and selenium tests for it.  It will also optionally integrate Spring Web Flow into the mix.  It’s basically a web based CRUD application in a box.

I spent the last 3 days trying to figure out how to use JSF 2 in Glassfish 3 with a Roo generated application.  Much of this pain may have been caused by my lack of experience with JPA and Spring, but here are a few of the difficulties I faced.

  • JSF 2 is not well supported in eclipse yet, whereas Netbeans 6.8 has excellent JSF 2 support.
  • All of the entities created by Roo just have properties.  All of the getters, setters, and other methods are all included in aspect files and compiled into the entity through AspectJ.  The AspectJ plugin for eclipse takes care of this if you have weaving enabled.  Guess what… There’s no aspect based plugin available for Netbeans, so you get a ton of compile problems in your Roo generated project if you try to open it within Netbeans.
  • The Roo projects are all maven based.  I have yet to see really good success with any maven integration within Eclipse.  Netbeans maven integration is spot on.  For the past 2.5 years I’ve been developing within Eclipse and simply doing all of the maven stuff from the command line because it’s much simpler than dealing with Maven in Eclipse.
  • JSF can’t be used to call Spring MVC controllers.  The Spring MVC controllers generated by Roo are nice.  They are simple and clean, and having them managed by Roo is just that much better.  Unfortunately, Spring MVC is stateless, whereas JSF is stateful, so calling any Spring MVC controller from JSF without using Spring’s Web Flow just doesn’t work.
  • JSF 2 can’t be used in the current version of Spring Web Flow.  Even though a sub component of Web Flow is Spring Faces, the current version of Spring Faces only supports JSF 1.x.  As soon as I put Spring Faces in the classpath, my JSF 2 app wouldn’t render any .xhtml files for me.  Removing Spring Faces from the classpath allowed me to render .xhtml with JSF 2.
  • The transaction type specified in the Roo generated persistence unit is RESOURCE_LOCAL.  Glassfish 3 told me I had to use JTA.  I believe Roo can generate a jndi based data source, which I haven’t tried yet.  I ended up manually modifying the persistence unit (after a lot of time on Google) to be jndi based and have the JTA transaction type.  Unfortunately, this means that all of the Roo generated unit tests fail.  I suspect if I had Roo generate the jndi data source then the unit tests would also pass, so hopefully this issue was self inflicted.  Update: I created a simple project with a jndi datasource.  Unfortunately, all of the unit tests fail.   There is some information in the (closed as won’t fix) bug at https://jira.springsource.org/browse/ROO-311 It would be nice if the unit tests that are created for Roo would use the Spring SimpleNamingContext (and I may be just making stuff up now because I don’t know a lot about Spring/JNDI stuff) or something to allow the unit tests to run if the persistence setup uses jndi.

So why would I continue in my endeavor to use JSF 2 with my Roo project, and where do I go from here?

We are trying to make development as easy as possible for the designers.  They have next to no Java experience at best and just want to tweak styles, layout, and images.  I believe JSF can do a great job of giving us that separation.  I can get the controls working in the form, and they can move them around and do whatever they want with them.  Also, with the composite components in JSF 2, we should be able to make some very nice reusable components for the designers to use in our application.  Finally, many of those components we should be able to share with other projects in the company.

So what is the solution to all of the above problems?

  • Education.  Obviously learning more about JPA and Spring will make the whole journey a little easier for me.
  • Separate projects.  If we have all of the domain model in one maven project, and have the web based UI in another (which is how it really ought to be anyway) then the java developers can use Eclipse or STS for their IDE and get the AspectJ support, and the web designers can use Netbeans 6.8 for the JSF 2 project and get the great support there.  Because the domain model will simply be a jar dependency for the web project all of the aspect based methods will be compiled into the class, meaning we won’t need any Aspect support within Netbeans.

What would it take to get a JSF 2 UI generator into Roo?

  • The Roo team has released a nearly 100 page document about Roo.  Unfortunately, all of the parts about how to implement a new addon for Roo are marked as TBC.  There’s precious little detail on the web too.  Unfortunately, I’m not quite ready to dive into the source code to try to figure it out.  So, a simple Roo addon isn’t quite there.  Update: The only reference I found regarding writing your own Roo addon is at http://www.slideshare.net/desmax74/spring-roo-internals-javaday-iv and the slides leave a lot to the imagination of the reader.
  • Rumors in the Spring forums are that Spring Faces is going to be a new top level project, freed from the grasp of Spring Web Flow, and that the next version (due in June 2010?) will support JSF 2.  I was quite excited to use Web Flow with JSF 2 for the bean management relating to flows.  For instance, a new whatsit wizard that spans multiple pages and manages the scope of the new whatsit bean.
  • Because JSF doesn’t work so well with Spring MVC without Web Flow, and Web Flow won’t support JSF 2 until Spring Faces is split out and both Web Flow and Spring Faces release their next version I believe it’ll be months at best before we see any JSF 2 capabilities within Roo.  The only way it could happen sooner is if someone dives into the Roo source code and creates a third-party addon that will generate JSF 2 controllers and xhtml pages.

So, there it is.  At least 3 days of pain, trial and error, and research all wrapped up in one blog post.