title: How to use Conversion Service in Spring MVC 4 JavaConfig?
body: <p>I am facing a problem with a migration from Spring Mvc 4 Xml to JavaConfig.</p>
  
  <p>I have a xml config that works perfect with conversion</p>
  
  <pre><code>&lt;bean id="objectMapper" class="com.xetec.flexmaint.common.Jackson2ObjectMapperFlexmaint" /&gt;
  
  &lt;mvc:annotation-driven validator="validator" conversion-service="conversionService"&gt;
      &lt;mvc:message-converters&gt;
          &lt;bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"&gt;
              &lt;property name="objectMapper" ref="objectMapper"/&gt;
          &lt;/bean&gt;
      &lt;/mvc:message-converters&gt;       
  &lt;/mvc:annotation-driven&gt;
  
  &lt;bean id="conversionService"
        class="org.springframework.context.support.ConversionServiceFactoryBean"&gt;
      &lt;property name="converters"&gt;
          &lt;list&gt;
              &lt;bean class="com.xetec.flexmaint.common.JodaLocalTimeConverter"/&gt;
              &lt;bean class="com.xetec.flexmaint.common.JavaUtilDateConverter"/&gt;
              &lt;bean class="com.xetec.flexmaint.common.JodaDateTimeConverter"/&gt;
              &lt;bean class="com.xetec.flexmaint.common.JodaLocalDateConverter"/&gt;
              &lt;bean class="com.xetec.flexmaint.common.JodaLocalDateTimeConverter"/&gt;
          &lt;/list&gt;
      &lt;/property&gt;
  &lt;/bean&gt;
  </code></pre>
  
  <p>Jackson2ObjectMapperFlexmaint</p>
  
  <pre><code>public class Jackson2ObjectMapperFlexmaint extends Jackson2ObjectMapperFactoryBean {
  
      @Override
      public void afterPropertiesSet() {
          super.afterPropertiesSet();
          getObject().setSerializationInclusion(JsonInclude.Include.NON_NULL).setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
          Hibernate5Module hibernateModule = new Hibernate5Module();
          hibernateModule.disable(Feature.USE_TRANSIENT_ANNOTATION);
          hibernateModule.enable(Feature.FORCE_LAZY_LOADING);
          getObject().registerModules(new JavaTimeModule(), hibernateModule);
          getObject().configure(SerializationFeature.INDENT_OUTPUT, true);
          getObject().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
          getObject().setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"));
      }
  }
  </code></pre>
  
  <p>Now I am trying to convert from Xml Config to Javaconfig/annotation.</p>
  
  <pre><code>@EnableWebMvc
  public class WebMvcConfig extends WebMvcConfigurerAdapter {
      @Override
      public void addFormatters(FormatterRegistry registry) {
  
          registry.addConverter(new LocalTimeConverter());
          registry.addConverter(new JavaUtilDateConverter());
          registry.addConverter(new ZonedDateTimeConverter());
          registry.addConverter(new LocalDateConverter());
          registry.addConverter(new LocalDateTimeConverter());
          registry.addConverter(new StringToZonedDateTimeConverter());
  
  
      }
  }
  
  @Bean(name = "validatorBeanFactory")
  public HibernateValidatorDefaultMessagesBeanFactory validator() {
      return new HibernateValidatorDefaultMessagesBeanFactory();
  }
  </code></pre>
  
  <p>Using command line if I send a json property(<strong>"scheduledStart":"2015-08-21T16:07:30"</strong>) I got <strong>HTTP Status 400 - The request sent by the client was syntactically incorrect.</strong></p>
  
  <pre><code>curl -H "Content-Type: application/json" -X POST -d '
  {
      "title": "New JSON",
      "scheduledStart":"2015-08-21T16:07:30",
      "assetId": "2",
      "workOrderStatus": {
          "workOrderStatusID": "1"
      },
      "partDtoList": [
          {
              "barcode": "1440169305037",
              "quantity": "1"
          }
      ]
  }
  ' -b ~/Downloads/cookies2.txt http://localhost:8080/flexmaintwebservice/api/workOrder/formCreate
  </code></pre>
  
  <p>Field sheduledStart</p>
  
  <pre><code>@Type(type="org.hibernate.type.ZonedDateTimeType")
  private ZonedDateTime scheduledStart;
  </code></pre>
  
  <p>If I try the same command line using Xml Config works, why?</p>
  
  <p>Thanks!</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>My entire Java Config class</p>
  
  <pre><code>@Configuration
  @PropertySource({
      "classpath:webServiceConfig.properties",
      "classpath:config.properties"
  })
  @ComponentScan({
      "com.xetec.flexmaint.webservice",
      "com.xetec.flexmaint.controller.validator",
  }) 
  @EnableWebMvc
  public class WebMvcConfig extends WebMvcConfigurerAdapter {
      @Value("${apiUrl}")
      private String basePath;
  
      @Override
      public void configureMessageConverters(List&lt;HttpMessageConverter&lt;?&gt;&gt; converters) {
          converters.add(mappingJackson2HttpMessageConverter());
          super.configureMessageConverters(converters);
      }
  
      @Override
      public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
          configurer.enable();
      }
  
      @Override
      public void addResourceHandlers(ResourceHandlerRegistry registry) {
          registry.addResourceHandler("/static/**").addResourceLocations("/resources/");
      }
  
      @Override
      public void addInterceptors(InterceptorRegistry registry) {
          LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
          interceptor.setParamName("lang");
          registry.addInterceptor(interceptor);
      }
  
      @Override
      public void addFormatters(FormatterRegistry registry) {
  
  
  
          registry.addConverter(new LocalTimeConverter());
          registry.addConverter(new JavaUtilDateConverter());
          registry.addConverter(new ZonedDateTimeConverter());
          registry.addConverter(new LocalDateConverter());
          registry.addConverter(new LocalDateTimeConverter());
          registry.addConverter(new StringToZonedDateTimeConverter());
  
      }
  
      @Bean
      public JSONDocController documentationController() {
          List&lt;String&gt; packages = Arrays.asList("com.xetec.flexmaint.webservice", "com.xetec.flexmaint.common.helper", "com.xetec.flexmaint.entity.entity");
          JSONDocController jsonDocController = new JSONDocController("1.0", basePath, packages);
          jsonDocController.setPlaygroundEnabled(true);
          jsonDocController.setDisplayMethodAs(MethodDisplay.URI);
          return jsonDocController;
      }
  
      @Bean
      public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
          return new PropertySourcesPlaceholderConfigurer();
      }
  
      @Bean
      public CookieLocaleResolver localeResolver() {
          CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
          cookieLocaleResolver.setDefaultLocale(Locale.getDefault());
          return cookieLocaleResolver;
      }
  
      @Bean(name = "validatorBeanFactory")
      public HibernateValidatorDefaultMessagesBeanFactory validator() {
          return new HibernateValidatorDefaultMessagesBeanFactory();
      }
  
      @Bean
      public BeanNameUrlHandlerMapping beanNameUrlHandlerMapping() {
          return new BeanNameUrlHandlerMapping();
      }
  
      @Bean
      public CommonsMultipartResolver multipartResolver() {
          return new CommonsMultipartResolver();
      }
  
      @Bean
      public RequestMappingHandlerMapping requestMappingHandlerMapping() {
          return new RequestMappingHandlerMapping();
      }
  
      @Bean
      public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
          return new MappingJackson2HttpMessageConverter(jackson2ObjectMapperFlexmaint().getObject());
      }
  
      @Bean
      public Jackson2ObjectMapperFlexmaint jackson2ObjectMapperFlexmaint() {
          return new Jackson2ObjectMapperFlexmaint();
      }
  
      @Bean
      public TilesViewResolver tilesViewResolver() {
          TilesViewResolver url = new TilesViewResolver();
          url.setOrder(1);
          return url;
      }
  
      @Bean
      public InternalResourceViewResolver internalResourceViewResolver() {
          InternalResourceViewResolver url = new InternalResourceViewResolver();
          url.setViewClass(JstlView.class);
          url.setPrefix("/WEB-INF/tiles/");
          url.setSuffix(".jsp");
          url.setOrder(2);
          return url;
      }
  
      //TODO How to migrate this?
      /**
       *  &lt;wss:binding url="/asset"&gt;
          &lt;wss:service&gt;
              &lt;ws:service bean="#assetControllerWs" /&gt;
          &lt;/wss:service&gt;
      &lt;/wss:binding&gt;
  
      &lt;wss:binding url="/barcodeScannerWs"&gt;
          &lt;wss:service&gt;
              &lt;ws:service bean="#barcodeScannerWs" /&gt;
          &lt;/wss:service&gt;
      &lt;/wss:binding&gt;
  
      &lt;wss:binding url="/maintenanceWebServiceWs"&gt;
          &lt;wss:service&gt;
              &lt;ws:service bean="#maintenanceWebServiceWs" /&gt;
          &lt;/wss:service&gt;
      &lt;/wss:binding&gt;
  
       */
  }
  </code></pre>
  
  <p>ADD Controller Mapping</p>
  
  <pre><code>@Api(name = "work order services", description = "Methods for managing work orders")
  @Controller
  @RequestMapping("/api/workOrder")
  public class WorkOrderRestFulApiController extends AbstractBaseController {
  
      @ApiMethod(description = "Api for create work order")
      @RequestMapping(value = "/formCreate", method = RequestMethod.POST, consumes="application/json;charset=utf-8", produces="application/json;charset=utf-8")
      @ApiResponseObject @ResponseBody
      public ResponseEntity&lt;Object&gt; createWorkOrder(@ApiPathParam @RequestBody WorkOrderDto workOrderDto, BindingResult result) throws Exception {
            ...
      }
  }
  </code></pre>
  
  <p>Add Stack Trace</p>
  
  <pre><code>org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Text '2015-08-21T16:07:30' could not be parsed at index 2 (through reference chain: com.xetec.flexmaint.webservice.dto.WorkOrderDto["scheduledStart"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Text '2015-08-21T16:07:30' could not be parsed at index 2 (through reference chain: com.xetec.flexmaint.webservice.dto.WorkOrderDto["scheduledStart"])
      at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:224)
      at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:208)
      at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:197)
      at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:147)
      at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:125)
      at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:78)
      at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162)
      at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:129)
      at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
      at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814)
      at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737)
      at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
      at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
      at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
      at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
      at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
      at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:316)
      at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
      at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
      at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
      at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:122)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
      at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
      at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
      at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
      at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:205)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
      at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
      at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
      at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
      at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53)
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
      at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213)
      at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176)
      at org.springframework.security.web.debug.DebugFilter.invokeWithWrappedRequest(DebugFilter.java:75)
      at org.springframework.security.web.debug.DebugFilter.doFilter(DebugFilter.java:62)
      at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
      at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:178)
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:217)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
      at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
      at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
      at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673)
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
      at java.lang.Thread.run(Thread.java:745)
  Caused by: com.fasterxml.jackson.databind.JsonMappingException: Text '2015-08-21T16:07:30' could not be parsed at index 2 (through reference chain: com.xetec.flexmaint.webservice.dto.WorkOrderDto["scheduledStart"])
      at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:210)
      at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:177)
      at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1474)
      at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:341)
      at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:133)
      at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736)
      at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2810)
      at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:221)
      ... 81 more
  Caused by: java.time.format.DateTimeParseException: Text '2015-08-21T16:07:30' could not be parsed at index 2
      at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
      at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1777)
      at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:151)
      at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:45)
      at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520)
      at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:95)
      at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:339)
      ... 85 more
  </code></pre>