Question

I really like spring and the @Configuration style to get rid of xml based configuration. I successfully use it for the service and repository layer. What I also love is the dependency injection feature and the JDO/JPA/Jdbc utilities!

What I don't really get is, how the Spring WebMVC works. There is too much uncontrollable magic for me. (and with @EnableAutoConfiguration there is even more magic introduced. Good for easy prototyping, difficult to maintain).

That is how I configure my webapp:

public class SpringWebBooter implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigApplicationContext rootContext = new AnnotationConfigApplicationContext();
        rootContext.register(SpringConfiguration.class); //main configuration class for all beans
        rootContext.refresh();

        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.setParent(rootContext);
        ctx.register(SpringWebConfiguration.class); //web context configuration class

        ServletRegistration.Dynamic api = servletContext.addServlet("api", new DispatcherServlet(ctx));
        api.setLoadOnStartup(1);
        api.addMapping("/api/*");
    }

}

Now I want to add type converters and httpMessageConverters, so in the SpringWebConfiguration class I tried:

@EnableWebMvc
@Configuration
@ComponentScan
public class SpringWebConfiguration {

    //works but feels very *magic*
    @Autowired
    public void configureConversionService(FormattingConversionService conversionService) {
        conversionService.addConverter(new PointConverter(GEOMETRY_FACTORY));
        conversionService.addConverterFactory(new StringToEnumConverterFactory());
    }

    //not working yet
    @Bean
    public MappingJackson2HttpMessageConverter createJsonMessageConverter() {
        ObjectMapper o = new ObjectMapper();
        o.enable(SerializationFeature.INDENT_OUTPUT);
        MappingJackson2HttpMessageConverter c = new MappingJackson2HttpMessageConverter();
        c.setObjectMapper(o);
        return c;
    }
}

What I'd rather find intuitive is to add type and message converters when I construct the dispatcher servlet. That would be much clearer than some dubious autowiring or bean creation. I always "hope" that the Dispatcher Servlet internally pics up my beans, but it is often just trial and error. Is it possible to set up spring Mvc in a directer way? With less magic and more concrete instantiations and #addHttpMessageConverter(...) calls for example?

Same basically for the ExceptionResolvers, RequestHandler and RequestAdapter.

Jan

Was it helpful?

Solution

The most direct way would be to extend WebMvcConfigurationSupport. You can setup almost everything that way by overriding the methods.

But be aware that it is a very direct way to setup stuff. It gives you much more control than you have now or than even WebMvcConfigurerAdapter would give you. From the docs:

If the customization options of {@link WebMvcConfigurer} do not expose
something you need to configure, consider removing the {@code @EnableWebMvc}
annotation and extending directly from {@link WebMvcConfigurationSupport}
overriding selected {@code @Bean} methods

Custom (or customized) message converters can be added by overriding configureMessageConverters.

OTHER TIPS

If you extend the WebMvcConfigurerAdapter for your web configuration, it should feel a little less magic and also give you the hook to configure your message converters as well as a number of other components.

    @Configuration
    @ComponentScan
    @EnableWebMvc
    public class WebConfiguration extends WebMvcConfigurerAdapter
    {
      @Autowired
      private CustomObjectMapper domainMapper;

      @Override
      public void configureMessageConverters(List<HttpMessageConverter<?>> converters)
      {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(domainMapper);
        converters.add(converter);
        super.configureMessageConverters(converters);
      }

    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top