Sunday, September 28, 2014

Spring WebApplicationInitializer and ApplicationContextInitializer confusion

These are two concepts that I mix up occasionally - a WebApplicationInitializer and an ApplicationContextInitializer, and wanted to describe each of them to clarify them for myself.

I have previously blogged about WebApplicationInitializer here and here. It is relevant purely in a Servlet 3.0+ spec compliant servlet container and provides a hook to programmatically configure the servlet context. How does this help - you can have a web application without potentially any web.xml file, typically used in a Spring based web application to describe the root application context and the Spring web front controller called the DispatcherServlet. An example of using WebApplicationInitializer is the following:

public class CustomWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
 @Override
 protected Class<?>[] getRootConfigClasses() {
  return new Class<?>[]{RootConfiguration.class};
 }

 @Override
 protected Class<?>[] getServletConfigClasses() {
  return new Class<?>[]{MvcConfiguration.class};
 }

 @Override
 protected String[] getServletMappings() {
  return new String[]{"/"};
 }
}

Now, what is an ApplicationContextInitializer. It is essentially code that gets executed before the Spring application context gets completely created. A good use case for using an ApplicationContextInitializer would be to set a Spring environment profile programmatically, along these lines:

public class DemoApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

 @Override
 public void initialize(ConfigurableApplicationContext ac) {
  ConfigurableEnvironment appEnvironment = ac.getEnvironment();
  appEnvironment.addActiveProfile("demo");

 }
}

If you have a Spring-Boot based application then registering an ApplicationContextInitializer is fairly straightforward:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class SampleWebApplication {
 
 public static void main(String[] args) {
  new SpringApplicationBuilder(SampleWebApplication.class)
    .initializers(new DemoApplicationContextInitializer())
    .run(args);
 }
}

For a non Spring-Boot Spring application though, it is a little more tricky, if it is a programmatic configuration of web.xml, then the configuration is along these lines:
public class CustomWebAppInitializer implements WebApplicationInitializer {

 @Override
 public void onStartup(ServletContext container) {
  AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
  rootContext.register(RootConfiguration.class);
  ContextLoaderListener contextLoaderListener = new ContextLoaderListener(rootContext);
  container.addListener(contextLoaderListener);
  container.setInitParameter("contextInitializerClasses", "mvctest.web.DemoApplicationContextInitializer");
  AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
  webContext.register(MvcConfiguration.class);
  DispatcherServlet dispatcherServlet = new DispatcherServlet(webContext);
  ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", dispatcherServlet);
  dispatcher.addMapping("/");
 }
}

If it a normal web.xml configuration then the initializer can be specified this way:
<context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>com.myapp.spring.SpringContextProfileInit</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

So to conclude, except for the Initializer suffix, both WebApplicationInitializer and ApplicationContextInitializer serve fairly different purposes. Whereas the WebApplicationInitializer is used by a Servlet Container at startup of the web application and provides a way for programmatic creating a web application(replacement for a web.xml file), ApplicationContextInitializer provides a hook to configure the Spring application context before it gets fully created.

Tuesday, September 16, 2014

Scala and Java 8 type inference in higher order functions sample

One of the concepts mentioned in the Functional Programming in Scala is about the type inference in higher order functions in Scala and how it fails in certain situations and a workaround for the same. So consider a sample higher order function, purely for demonstration:

def filter[A](list: List[A], p: A => Boolean):List[A] = {
 list.filter(p)
} 

Ideally, passing in a list of say integers, you would expect the predicate function to not require an explicit type:

val l = List(1, 5, 9, 20, 30) 

filter(l, i => i < 10)

Type inference does not work in this specific instance however, the fix is to specify the type explicitly:

filter(l, (i:Int) => i < 10)

Or a better fix is to use currying, then the type inference works!

def filter[A](list: List[A])(p: A=>Boolean):List[A] = {
 list.filter(p)
}                                         

filter(l)(i => i < 10) 
//OR
filter(l)(_ < 10) 
I was curious whether Java 8 type inference has this issue and tried a similar sample with Java 8 Lambda expression, the following is an equivalent filter function -
public <A> List<A> filter(List<A> list, Predicate<A> condition) {
 return list.stream().filter(condition).collect(toList());
}
and type inference for the predicate works cleanly -
List ints = Arrays.asList(1, 5, 9, 20, 30);
List lessThan10 =  filter(ints, i -> i < 10);
Another blog entry on a related topic by the author of the "Functional Programming in Scala" book is available here - http://pchiusano.blogspot.com/2011/05/making-most-of-scalas-extremely-limited.html

Sunday, September 14, 2014

Customizing HttpMessageConverters with Spring Boot and Spring MVC

Exposing a REST based endpoint for a Spring Boot application or for that matter a straight Spring MVC application is straightforward, the following is a controller exposing an endpoint to create an entity based on the content POST'ed to it:

@RestController
@RequestMapping("/rest/hotels")
public class RestHotelController {
        ....
 @RequestMapping(method=RequestMethod.POST)
 public Hotel create(@RequestBody @Valid Hotel hotel) {
  return this.hotelRepository.save(hotel);
 }
}

Internally Spring MVC uses a component called a HttpMessageConverter to convert the Http request to an object representation and back.

A set of default converters are automatically registered which supports a whole range of different resource representation formats - json, xml for instance.

Now, if there is a need to customize the message converters in some way, Spring Boot makes it simple. As an example consider if the POST method in the sample above needs to be little more flexible and should ignore properties which are not present in the Hotel entity - typically this can be done by configuring the Jackson ObjectMapper, all that needs to be done with Spring Boot is to create a new HttpMessageConverter bean and that would end up overriding all the default message converters, this way:

@Bean
 public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
  MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
  ObjectMapper objectMapper = new ObjectMapper();
  objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
  jsonConverter.setObjectMapper(objectMapper);
  return jsonConverter;
 }

This works well for a Spring-Boot application, however for straight Spring MVC applications which do not make use of Spring-Boot, configuring a custom converter is a little more complicated - the default converters are not registered by default and an end user has to be explicit about registering the defaults - the following is the relevant code for Spring 4 based applications:

@Configuration
public class WebConfig extends WebMvcConfigurationSupport {

 @Bean
 public MappingJackson2HttpMessageConverter customJackson2HttpMessageConverter() {
  MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
  ObjectMapper objectMapper = new ObjectMapper();
  objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
  jsonConverter.setObjectMapper(objectMapper);
  return jsonConverter;
 }
 
 @Override
 public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  converters.add(customJackson2HttpMessageConverter());
  super.addDefaultHttpMessageConverters();
 }
}

Here WebMvcConfigurationSupport provides a way to more finely tune the MVC tier configuration of a Spring based application. In the configureMessageConverters method, the custom converter is being registered and then an explicit call is being made to ensure that the defaults are registered also. A little more work than for a Spring-Boot based application.