Validating Spring MVC Request Mapping Method parameters

This short post demonstrates how to set up and use JSR-303 Validation for the arguments in Spring MVC request mapping methods for path variable and request parameter arguments. I am using Spring Boot v1.2.5 with Maven 3.

I. MethodValidationPostProcessor

The only configuration needed is adding the MethodValidationPostProcessor (javadoc) bean to the Spring configuration, e.g.

 @Bean
 public MethodValidationPostProcessor methodValidationPostProcessor() {
      return new MethodValidationPostProcessor();
 }

II Add validation to controller request mapping method

First, add the @Validate annotation to the controller class as follows:

@RestController
@Validated
public class HelloController {
     ...

Then add any JSR-303 validation annotation to a request mapping method arguments:

 @RequestMapping("/hi/{name}")
 public String sayHi(@Size(max = 10, min = 3, message = "name should have between 3 and 10 characters") @PathVariable("name") String name) {
      return "Hi " + name;
 }

The example codes above shows how to validate a value in the request path marked by @PathVariable. You can do the same with @RequestParam

III Validation exception handling

A ConstraintViolationException will be thrown if the size of the path variable is not within 3 to 10 characters. You may need to catch this exception and process it using a Spring MVC exception handler, for example to return the error messages in the response:

 @ExceptionHandler(value = { ConstraintViolationException.class })
 @ResponseStatus(value = HttpStatus.BAD_REQUEST)
 public String handleResourceNotFoundException(ConstraintViolationException e) {
      Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
      StringBuilder strBuilder = new StringBuilder();
      for (ConstraintViolation<?> violation : violations ) {
           strBuilder.append(violation.getMessage() + "\n");
      }
      return strBuilder.toString();
 }
Advertisements

Setup Spring Security with Active Directory LDAP in Spring Boot Web Application

This post illustrates how to set up Spring Security in Spring Boot configuration with Active Directory LDAP for a Spring MVC web application. I will also show what needs to be configured for the embedded tomcat to accept HTTPS.

Spring Security with LDAP

To configure Spring Security in Spring Boot, add the following Configuration class to your project. Note the use of annotation @EnableWebMvcSecurity. The configuration class extends the WebSecurityConfigurerAdapter class in Spring Security. More information can be found in the Spring Security Reference here.

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

     @Value("${ldap.domain}")
     private String DOMAIN;

     @Value("${ldap.url}")
     private String URL;

     @Value("${http.port}")
     private int httpPort;

     @Value("${https.port}")
     private int httpsPort;

     @Override
     protected void configure(HttpSecurity http) throws Exception {
          /*
           * Set up your spring security config here. For example...
          */
          http.authorizeRequests().anyRequest().authenticated().and().formLogin().loginUrl("/login").permitAll();
          /*
           * Use HTTPs for ALL requests
          */
          http.requiresChannel().anyRequest().requiresSecure();
          http.portMapper().http(httpPort).mapsTo(httpsPort);
     }

     @Override
     protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
          authManagerBuilder.authenticationProvider(activeDirectoryLdapAuthenticationProvider()).userDetailsService(userDetailsService());
     }

     @Bean
     public AuthenticationManager authenticationManager() {
          return new ProviderManager(Arrays.asList(activeDirectoryLdapAuthenticationProvider()));
     }
     @Bean
     public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
          ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(DOMAIN, URL);
          provider.setConvertSubErrorCodesToExceptions(true);
          provider.setUseAuthenticationRequestCredentials(true);
          return provider;
     }
}

Add HTTPS connector for embedded Tomcat in Spring Boot

Now that Spring Security is set up, you need to update the web server to accept requests from HTTPS. To do that using the embedded Tomcat server in Spring Boot, add the following EmbeddedServletContainerCustomizer bean to the application configuration as shown below. Note I am using anonymous inner classes here instead of lambda expression as I see in other examples for Java 7 compatibility. You will need a keystore file for this to work.

@Bean
EmbeddedServletContainerCustomizer containerCustomizer (

     @Value("${https.port}") final int port, 
     @Value("${keystore.file}") Resource keystoreFile,
     @Value("${keystore.alias}") final String alias, 
     @Value("${keystore.password}") final String keystorePass,
     @Value("${keystore.type}") final String keystoreType) throws Exception {
          final String absoluteKeystoreFile = keystoreFile.getFile().getAbsolutePath();
          return new EmbeddedServletContainerCustomizer() {
               public void customize(ConfigurableEmbeddedServletContainer container) {
                    TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container;
                    tomcat.addConnectorCustomizers(new TomcatConnectorCustomizer() {
                         public void customize(Connector connector) {
                              connector.setPort(port);
                              connector.setSecure(true);
                              connector.setScheme("https");
                              Http11NioProtocol proto = (Http11NioProtocol) connector.getProtocolHandler();
                              proto.setSSLEnabled(true);
                              proto.setKeystoreFile(absoluteKeystoreFile);
                              proto.setKeyAlias(alias);
                              proto.setKeystorePass(keystorePass);
                              proto.setKeystoreType(keystoreType);
                        }
               });
           }
     };
 }

 

Using Spring 4 WebSocket, sockJS and Stomp support to implement two way server client communication

One exciting new feature of Spring 4 is the support for WebSocket, SockJS and STOMP messaging. This allows two way communication between the server and its clients in a Spring MVC web application using the standard point-to-point and publish-subscribe messaging protocols. In this post, I will demonstrate how to set up a basic boilerplate project to start using this new feature. It is in part based on this article.

Maven Setup

First we need to add the Spring messaging modules in the POM file:

<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-messaging</artifactId>
 <version>4.0.0.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-websocket</artifactId>
 <version>4.0.0.RELEASE</version>
 </dependency>

Spring MVC Configuration

Next, we need to add the message broker config to the Spring MVC config XML file.

<beans
 ...
 xmlns:websocket="http://www.springframework.org/schema/websocket"
 xsi:schemaLocation="
 ...
 http://www.springframework.org/schema/websocket
 http://www.springframework.org/schema/websocket/spring-websocket-4.0.xsd">
<websocket:message-broker application-destination-prefix="/app">
       <websocket:stomp-endpoint path="/hello">
            <websocket:sockjs/>
       </websocket:stomp-endpoint>
       <websocket:simple-broker prefix="/topic"/>
</websocket:message-broker>
<!-- Other MVC config omitted here-->

The main thing here is the set up of the message broker for handling the message exchange between the server and its clients. This is done via the <message-broker> and its child tags. The tag <websocket:simple-broker> indicates we are using in-memory message broker.

It is easy to understand together with the server and client codes so I will include them below first before attempting to give a bit more explanations by cross-referencing the client and server codes.

Spring MVC Controller

Below is my Spring MVC Controller

 @Controller
 public class MessageController {
      @MessageMapping("/hello")
      @SendTo("/topic/greetings")
      public Greeting greeting(HelloMessage message) throws Exception {
           return new Greeting("Hello, " + message.getName() + "!");
     }
}

The method argument HelloMessage and output Greeting are just POJOs representing the body of the messages being sent and returned.

public class Greeting {
    private String content;
    public Greeting(String content) {
           this.content = content;
    }
    public String getContent() {
      return content;
    }
}
public class HelloMessage {
    private String name;
    public String getName() {
        return name;
    }
}

Client sockJS and STOMP codes

On the client side, I use the sockJS protocol fallback option as outlined in the Spring documentation. The javascript codes are included below

// Create stomp client over sockJS protocol (see Note 1)
 var socket = new SockJS("/hello");
 var stompClient = Stomp.over(socket);

 // callback function to be called when stomp client is connected to server (see Note 2)
 var connectCallback = function() {
      alert("connected!");
      stompClient.subscribe('/topic/greetings', function(greeting){
           alert(JSON.parse(greeting.body).content);
      });
 }; 

 // callback function to be called when stomp client could not connect to server (see Note 3)
 var errorCallback = function(error) {
      // display the error's message header:
      alert(error.headers.message);
 };

 // Connect as guest (Note 4)
 stompClient.connect("guest", "guest", connectCallback, errorCallback);

Note

  1. The client starts by create a sockJS by specifying the endpoint (ie. /hello) to connect to and then a stomp client is created over the socket. The endpoint here should match that defined in the Spring MVC configuration in the lines. Note also the 2nd line referring to sockJS.

    <websocket:stomp-endpoint path=”/hello”>
    <websocket:sockjs/>
    </websocket:stomp-endpoint>

  2. Then a callback function is created and assigned to a variable connectCallback. This is called when a successful connection is made by the stomp client. This allows us to start making subscriptions to messages (as in codes, repeated below) and sending messages. Note the subscription is for the topic “/topic/greetings”

    stompClient.subscribe(‘/topic/greetings’, function(greeting){
    alert(JSON.parse(greeting.body).content);
    });

  3. A error callback function is defined if stomp client fails to connect to server.
  4. This line makes the connection registering the callback functions.

Now we are ready to send messages from the client, e.g. using the following javascript function

// function to send message
 function fnSayHi() {
       stompClient.send("/app/hello", {}, JSON.stringify({ 'name': 'Joe' }));
 }

The message will be sent to the Spring MVC message handler method greeting() as defined via the annotation @MessageMapping(“/hello”).

 <websocket:message-broker application-destination-prefix=”/app”>

Note the prefix “/app” is defined in the Spring config as  application-destination-prefix attribute of the message broker: Note also, the use of @SendTo annotation to direct the message to a given destination. I repeat the controller method below

 @MessageMapping("/hello")
 @SendTo("/topic/greetings")
 public Greeting greeting(HelloMessage message) throws Exception {
      return new Greeting("Hello, " + message.getName() + "!");
 }

That’s it for now.

Configure Spring MVC ContentNegotiatingViewResolver to generate RSS feeds

The spring 3.2 document provides the following example for configuring the ContentNegotiatingViewResolver for generating rss feeds:

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
  <property name="mediaTypes">
    <map>
      <entry key="atom" value="application/atom+xml"/>
      <entry key="html" value="text/html"/>
      <entry key="json" value="application/json"/>
    </map>
  </property>
  <property name="viewResolvers">
    <list>
      <bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
      </bean>
    </list>
  </property>
  <property name="defaultViews">
    <list>
      <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" />
    </list>
  </property>
</bean>

However when I run this, I got class cast exception with the mediaTypes properties

java.lang.ClassCastException: java.lang.String cannot be cast to org.springframework.http.MediaType
 at org.springframework.web.accept.MappingMediaTypeFileExtensionResolver.<init>(MappingMediaTypeFileExtensionResolver.java:56)
 at org.springframework.web.accept.AbstractMappingContentNegotiationStrategy.<init>(AbstractMappingContentNegotiationStrategy.java:42)
 at org.springframework.web.accept.PathExtensionContentNegotiationStrategy.<init>(PathExtensionContentNegotiationStrategy.java:74)
 at org.springframework.web.accept.ServletPathExtensionContentNegotiationStrategy.<init>(ServletPathExtensionContentNegotiationStrategy.java:47)
 at org.springframework.web.accept.ContentNegotiationManagerFactoryBean.afterPropertiesSet(ContentNegotiationManagerFactoryBean.java:166)
 at org.springframework.web.servlet.view.ContentNegotiatingViewResolver.afterPropertiesSet(ContentNegotiatingViewResolver.java:270)

This is because the map expects a MediaType objects as values but got String objects instead, e.g. “application/atom+xml”. The correct way to setup the view resolver should be:

<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
 <property name="contentNegotiationManager">   [1]
      <bean class="org.springframework.web.accept.ContentNegotiationManager">
           <constructor-arg>
                <bean class="org.springframework.web.accept.PathExtensionContentNegotiationStrategy">
                     <constructor-arg>
                     <map>
                        <entry key="atom">
                             <util:constant static-field="org.springframework.http.MediaType.APPLICATION_ATOM_XML" />  [2]
                        </entry>
                        <entry key="rss" value-ref="rssMediaType"/>
                     </map>
                     </constructor-arg>
                </bean>
           </constructor-arg>
      </bean>
 </property>

Note:

  1. The use of property contentNegotiationManager and injection of the bean ContentNegotiationManager
  2. Static field of MediaType org.springframework.http.MediaType.APPLICATION_ATOM_XML
  3. The MediaType class does not define a constant for RSS type so you have to create your own:
<bean id="rssMediaType" class="org.springframework.http.MediaType">
      <constructor-arg value="application"/>
      <constructor-arg value="rss+xml"/>
</bean>

Integrating ZK/MVVM and Spring MVC

This blog demonstrates how to use the ZK framework as the view in a Spring MVC web application to leverage ZK’s rich UI and transparent Ajax capabilities. In particular, I will show how to pass data between the 2 frameworks.

Getting data from Spring MVC to ZK View (.zul)

Passing values from Spring MVC to ZK can be done in the same way as for JSP by adding attributes to the response model:

@RequestMapping(“/hello.action”)
public String passToZK(Model model) {
model.addAttribute(“appname”, “zk”);
return “/demo/hellozk.zul”;
}

and use in the ZK view file hellozk.zul:

<window>
<label>Hello from ${appname}!</label>
</window>

Binding data in ZK View to Spring MVC

Getting data from ZK back to Spring MVC involves a bit more work. Suppose we have to implement a web form to get the first and last names of a customer. The Customer class is a normal POJO:

public class Customer {

private String firstname;
private String lastname;

// getters and setters here…

}

and the .zul file:

<zk xmlns:n=”native”>

<window apply=”org.zkoss.bind.BindComposer” viewModel=”@id(‘vm’) @init(‘myblog.viewmodel.CustomerViewModel’)”>
<n:form action=”save.action” method=”post”>
<div width=”700px” class=”form”>
<vlayout spacing=”7px”>
<hlayout spacing=”20px”>
<label class=”name” value=”Firstname :” />
<textbox id=”firstname” value=”@bind(vm.entity.firstname)” />
<textbox visible=”false” name=”firstname” value=”@bind(vm.entity.firstname)” />
</hlayout>
<hlayout spacing=”20px”>
<label class=”name” value=”Lastname :” />
<textbox id=”name” value=”@bind(vm.entity.lastname)” />
<textbox visible=”false” name=”lastname” value=”@bind(vm.entity.lastname)” />
</hlayout>
<hlayout spacing=”20px”>
<button label=”Save” onClick=”@command(‘submit’)” />
</hlayout>
</vlayout>
</div>
</n:form>
</window>

Note

  1. Native form is used: “<n:form action=”save.action” method=”post”>
  2. The attributes firstname and lastname are bind to a ZK viewmodel (to be discussed later)
  3. In order to pass the form values (firstname and lastnames) back to Spring MVC when the form is submitted, the attributes are also bind to invisible textbox elements, e.g.:

<textbox visible=”false” name=”lastname” value=”@bind(vm.entity.lastname)” />

The zul form is bind to MVVM class myblog.viewmodel.CustomerViewModel

public class CustomerViewModel {

private Customer entity;
@Init
public void init(@ExecutionParam(“customer”) Customer             customer) {
this.entity = customer;
}

@Command(“submit”)
public void submit() {

// submit form
Clients.evalJavaScript(“jq(‘form’)[0].submit();”);
}

Note the annotation @ExecutionParam in the init method. This is required so to pass the model attribute in the Spring MVC controller to the form to populate any initial form values, for updating an existing customer. The submit command method is simple – it just calls the client method to submit the form to Spring MVC. For completeness, below is the controller’s submit method:

@RequestMapping(“/save.action”)
public String save(@ModelAttribute Customer customer, Model model) {
// implementation here
}

That’s it. It involves a bit of work to put the 2 frameworks together but may be useful if you have already had the web app implemented using Spring MVC and/or experienced in Spring MVC and just interested in using the rich UI and Ajax side of the ZK framework.

Searchable dropdown for Spring MVC/Hibernate web applications – Part I

Introduction

One common feature in a J2EE web application is to provide a dropdown box for user to select from a number of options. Typically, the selected option represents a key to the underlying domain object in the system. For example, a user may select a share code and the application will then display the detailed information of the chosen share by loading the share domain object using the value selected from the database.

In this  blog, I will demonstrate how to implement an end-to-end searchable dropdown solution for Spring MVC/Hibernate web applications. In this article, I will focus on building the backend codes required to provide a generic solution for generating option lists for any entities defined in the system. I will demonstrate how to build the searchable dropdown functions at the front-end in another blog.

Back-end solution design

1. Domain model

The domain model for the dropdown option is simple. It has 2 properties: name and value which correspond to the name and value attributes used in option elements in HTML:

public class DropdownOption {

private String name;

private String value;

public DropdownOption(String name, String value) {
this.name = name;
this.value = value;
}

2. Repository layer

The repository layer is where most of the implementation happens. There is only one method in the interface :

public interface IDropdownRepository {

List<DropdownOption> getOptions(String entityName, String nameProp, String valueProp, String filter);
}

The getOptions() method has 4 arguments:

  1. entityName – name of the entity to get values from
  2. nameProp – name of the entity’s property to use as the name of the dropdown option
  3. valueProp – name of the entity’s property to use as the value of the dropdown option
  4. filter – optional HQL string to filter search result

The implementation of IDropdownRepository using Spring Hibernate support:

@Repository
public class DropdownRepositoryImpl extends HibernateDaoSupport implements
IDropdownRepository {

@Autowired(required=true)
public DropdownRepositoryImpl(SessionFactory sessionFactory) {
super.setSessionFactory(sessionFactory);
}

public List<DropdownOption> getOptions(String entityName, String nameProp,
String valueProp, String filter) {
String where = StringUtils.isBlank(filter) ? “” : ” ” + filter;
 final String hql = “SELECT new com.rlee.myapp.domain.DropdownOption(” + nameProp + “,” + valueProp  + “) FROM ” + entityName + where;
List<DropdownOption> options = getHibernateTemplate().find(hql);
return options;
}

}

As shown in the codes above, the implementation constructs the proper HQL using the input arguments and then execute the query to get the result list. Note

  • the use of constructor of the DropdownOption(name,value) in the HQL SELECT statement to create the DropdownOption domain objects.
  • HQL functions can be used in either or both nameProp and valueProp values. E.g. it is possible to use concat() function to use values of multiple properties (i.e. multiple database columns) of the entity as the display option names.

3. Service layer

Typically, you would access repository via the service layer. In our case, the service just delegates the method to its repository.

Interface:

public interface IDropdownService {
List<DropdownOption> getOptions(String entityName, String nameProp, String valueProp, String filter);
}

Implementing class:

@Service
public class DropdownServiceImpl implements IDropdownService {

@Autowired(required=true)
private IDropdownRepository repository;

public List<DropdownOption> getOptions(String entityName, String nameProp,
String valueProp, String filter) {
return repository.getOptions(entityName, nameProp, valueProp, filter);
}

}

4. Controller

The dropdown option list is obtained via AJAX with requests with  address /dropdown/<entity>/get.action where <entity> is the name of the entity required:

@Controller
@RequestMapping(value = “/dropdown”)
public class DropdownController {

@Autowired(required = true)
private IDropdownService service;

@RequestMapping(value = “/{entity}/get.action”, method = RequestMethod.GET)
public @ResponseBody List<DropdownOption> getDropdownList(
@PathVariable(“entity”) String entity, HttpServletRequest request)
throws ServletRequestBindingException {
// Get name and value property from request
String nameProp = ServletRequestUtils.getRequiredStringParameter(
request, “nameProp”);
String valueProp = ServletRequestUtils.getRequiredStringParameter(
request, “valueProp”);
String filter = ServletRequestUtils.getStringParameter(request,
“filter”);
return service.getOptions(entity, nameProp, valueProp, filter);
}

}

Using Spring MVC JSON support, the method getDropdownList() will return the result as the JSON object representing the underlying list of DropdownOption objects, which can then be easily converted into the corresponding HTML option elements.

That’s it for now. I will show how to use the codes above to implement AJAX based searchable dropdown in the front-end.

Validation in Spring 3 MVC App

Summary

Validating user inputs is an important function for most web applications. Typically, you need to validate the values a user enters, e.g. via a web form, to ensure that all the required fields are provided and that the values are acceptable according to the system’s business rules and logics.

This article demonstrates how to setup Spring 3 MVC web applications to support bean validation with JSR 303, as well as extending the standard validation capability by adding custom validators.

Set up Spring 3 validation support

Enabling JSR-303 bean validation support in Spring 3 is straight forward. Just add the following bean definition in your application context xml file:

    <bean id=”validator” class=”org.springframework.validation.beanvalidation.LocalValidatorFactoryBean”
/>

From the javadoc, the above class is:

the central class for javax.validation (JSR-303) setup in a Spring application context: It bootstraps a javax.validation.ValidationFactory and exposes it through the Spring org.springframework.validation.Validator interface  as well as through the JSR-303 javax.validation.Validator interface and the javax.validation.ValidatorFactory interface itself.

Basically, what it means is it allows you to inject the above bean directly into any other bean without the need to access the factory. We will encounter an example later in this article when writing a custom bean to support cross field validation.

Note you will need to add the following dependency if you are using Maven:

 <dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>

Bean validation in Spring 3 MVC – An Example

Now we can add validation annotations to the bean. For example,

public class MyBean {

@NotNull
private String requiredStr; // cannot be null

@Min(1)
private int positiveInt; // positive integer

Other useful validators include:

  • Digits – a number within a specified range
  • Future – a future date
  • Past – a past date

See javadoc for a complete list of standard annotations supported in JSR-303. You can also use the following non-standard validators if you are using Hibernate:

  • Email – a valid email address
  • Length – a string has length within min and max lengths
  • NotEmpty – string not null or blank
  • Range – between a min and max values

Then, use @Valid in the request mapping method of a Spring MVC controller. To validate the above object:

@RequestMapping(method = RequestMethod.POST)
public String handleFormSubmission(@Valid MyBean mybean, BindingResult result) {
if (result.hasErrors()) {
// model has error(s)
}

Any validation errors are included in the BindingResult object. Validating error messages can be defined using “message” attribute of the validating tag. Alternatively, you can define messages using keys in a properties file. The key is in the format <validator>.<object name>.<property>. For example,

NotNull.myobj.requiredStr=This string is required

Min.myobj.positiveInt=Must be a positive value

Writing Custom validation annotation

It is also possible to write your own validating annotation. First, define the annotation interface. For example:

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=CreditCardValidator.class)
public @interface CreditCard {

String message() default “{com.rlee.CreditCardValidating.message}”;

Class<?>[] groups() default { };

Class<? extends Payload>[] payload() default {};
}

Next write the implementing class

public class CreditCardValidator implements ConstraintValidator<CreditCard, String> {

public void initialize(CreditCard constraintAnnotation) {
}

public boolean isValid(String value, ConstraintValidatorContext context) {

}

Note the validator needs to implement the generic ConstraintValidator class.

Writing custom validator for cross field validation

In many cases, an application will need to perform validations across multiple fields. For example, the minimum value of one field may depend on the chosen value of another field. In such case, a custom bean validator is required. Spring MVC allows you to do this easily by supporting binding of the custom validator to a controller using the @initBinder tag and method:

@Controller
public class MyController {

@Autowired
private MyValidator myValidator;

@InitBinder
protected void initBinder(WebDataBinder webDataBinder) {
webDataBinder.setValidator(myValidator);
}

The custom validator must implement Spring validator interface org.springframework.validation.Validator:

public class MyValidator implements Validator {

@Autowired
private Validator validator;

public boolean supports(Class<?> clazz) {

}

public void validate(Object target, Errors errors) {
// customer validation here

// delegate to standard validator

validator.validate(target, errors);
}

Note the injection of the standard validator, i.e. LocalValidatorFactoryBean.