title: Why is my controller sending the content type "application/octet-stream"?
body: <p>I have a REST controller:</p>
  
  <pre><code>@RequestMapping(value = "greeting", method = RequestMethod.GET, produces = "application/json; charset=utf-8")
  @Transactional(readOnly = true)
  @ResponseBody
  public HttpEntity&lt;GreetingResource&gt; greetingResource(@RequestParam(value = "message", required = false, defaultValue = "World") String message) {
      GreetingResource greetingResource = new GreetingResource(String.format(TEMPLATE, message));
      greetingResource.add(linkTo(methodOn(AdminController.class).greetingResource(message)).withSelfRel());
      HttpHeaders responseHeaders = new HttpHeaders();
      responseHeaders.add("Content-Type", "application/json; charset=utf-8");
      return new ResponseEntity&lt;GreetingResource&gt;(greetingResource, responseHeaders, HttpStatus.OK);
  }
  </code></pre>
  
  <p>As you can see, I'm trying hard to specify the content type returned by the controller.</p>
  
  <p>It is accessed with a REST client:</p>
  
  <pre><code>public String getGreetingMessage() {
      String message;
      try {
          HttpHeaders httpHeaders = Common.createAuthenticationHeaders("stephane" + ":" + "mypassword");
          ResponseEntity&lt;GreetingResource&gt; responseEntity = restTemplate.getForEntity("/admin/greeting", GreetingResource.class, httpHeaders);
          GreetingResource greetingResource = responseEntity.getBody();
          message = greetingResource.getMessage();
      } catch (HttpMessageNotReadableException e) {
          message = "The GET request FAILED with the message being not readable: " + e.getMessage();
      } catch (HttpStatusCodeException e) {
          message = "The GET request FAILED with the HttpStatusCode: " + e.getStatusCode() + "|" + e.getStatusText();
      } catch (RuntimeException e) {
          message = "The GET request FAILED " + ExceptionUtils.getFullStackTrace(e);
      }
      return message;
  }
  </code></pre>
  
  <p>The http headers are created by a utility:</p>
  
  <pre><code>static public HttpHeaders createAuthenticationHeaders(String usernamePassword) {
      HttpHeaders headers = new HttpHeaders();
      headers.setContentType(MediaType.APPLICATION_JSON);
      headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
      byte[] encodedAuthorisation = Base64.encode(usernamePassword.getBytes());
      headers.add("Authorization", "Basic " + new String(encodedAuthorisation));
      return headers;
  }
  </code></pre>
  
  <p>The web security configuration and code work fine. I make sure of this using a mockMvc based integration test which succeeds.</p>
  
  <p>The only test that fails is the one based on the REST template:</p>
  
  <pre><code>@Test
  public void testGreeting() throws Exception {
      mockServer.expect(requestTo("/admin/greeting")).andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.OK));
      String message = adminRestClient.getGreetingMessage();
      mockServer.verify();
      assertThat(message, allOf(containsString("Hello"), containsString("World")));
  }
  </code></pre>
  
  <p>The exception given in the Maven build console output is:</p>
  
  <pre><code>java.lang.AssertionError: 
  Expected: (a string containing "Hello" and a string containing "World")
  got: "The GET request FAILED org.springframework.web.client.RestClientException : Could not extract response: no suitable HttpMessageConverter found for response type [class com.thalasoft.learnintouch.rest.resource.GreetingR esource] and content type [application/octet-stream]\n\tat org.springframework.web.client.HttpMessageConverte rExtractor.extractData(HttpMessageConverterExtract or.java:107)
  </code></pre>
  
  <p>I'm using the Spring Framework 3.2.2.RELEASE version and the Spring Security 3.1.4.RELEASE version on the Java 1.6 version.</p>
  
  <p>At first, I had a bare bone REST template:</p>
  
  <pre><code>@Bean
  public RestTemplate restTemplate() {
      RestTemplate restTemplate = new RestTemplate();
      return restTemplate;
  }
  </code></pre>
  
  <p>I have now added to it, hoping it would help:</p>
  
  <pre><code>private static final Charset UTF8 = Charset.forName("UTF-8");
  
  @Bean
  public RestTemplate restTemplate() {
      List&lt;HttpMessageConverter&lt;?&gt;&gt; messageConverters = new ArrayList&lt;HttpMessageConverter&lt;?&gt;&gt;();
      MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();        
      mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("application", "json", UTF8)));
      messageConverters.add(mappingJackson2HttpMessageConverter);
  
      Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
      jaxb2Marshaller.setClassesToBeBound(new Class[] {
          GreetingResource.class
      });
      MarshallingHttpMessageConverter marshallingHttpMessageConverter = new MarshallingHttpMessageConverter(jaxb2Marshaller, jaxb2Marshaller);
      messageConverters.add(marshallingHttpMessageConverter);
  
      messageConverters.add(new ByteArrayHttpMessageConverter());
      messageConverters.add(new FormHttpMessageConverter());
      StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
      stringHttpMessageConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("text", "plain", UTF8)));
      messageConverters.add(stringHttpMessageConverter);
      messageConverters.add(new BufferedImageHttpMessageConverter());
      messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
      messageConverters.add(new AllEncompassingFormHttpMessageConverter());
      RestTemplate restTemplate = new RestTemplate();
      restTemplate.setMessageConverters(messageConverters);
      return restTemplate;
  }
  </code></pre>
  
  <p>But it didn't change anything and the exception remains the same.</p>
  
  <p>My understanding is that, it is not the REST template that needs any specific JSON configuration, but rather, that, for some reason, my controller is spitting out some application/octet-stream content type instead of some application/json content type.</p>
  
  <p>Any clue?</p>
  
  <p>Some additional information...</p>
  
  <p>The admin rest client bean in the web test configuration:</p>
  
  <pre><code>@Configuration
  public class WebTestConfiguration {
  
      @Bean
      public AdminRestClient adminRestClient() {
          return new AdminRestClient();
      }
  
      @Bean
      public RestTemplate restTemplate() {
          List&lt;HttpMessageConverter&lt;?&gt;&gt; messageConverters = new ArrayList&lt;HttpMessageConverter&lt;?&gt;&gt;();
          MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();        
          mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("application", "json", UTF8)));
          messageConverters.add(mappingJackson2HttpMessageConverter);
  
          Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
          jaxb2Marshaller.setClassesToBeBound(new Class[] {
              Greeting.class
          });
          MarshallingHttpMessageConverter marshallingHttpMessageConverter = new MarshallingHttpMessageConverter(jaxb2Marshaller, jaxb2Marshaller);
          messageConverters.add(marshallingHttpMessageConverter);
  
          messageConverters.add(new ByteArrayHttpMessageConverter());
          messageConverters.add(new FormHttpMessageConverter());
          StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
          stringHttpMessageConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("text", "plain", UTF8)));
          messageConverters.add(stringHttpMessageConverter);
          messageConverters.add(new BufferedImageHttpMessageConverter());
          messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
          messageConverters.add(new AllEncompassingFormHttpMessageConverter());
          RestTemplate restTemplate = new RestTemplate();
          restTemplate.setMessageConverters(messageConverters);
          return restTemplate;
      }
  
  }
  </code></pre>
  
  <p>The base test class:</p>
  
  <pre><code>@RunWith(SpringJUnit4ClassRunner.class)
  @WebAppConfiguration
  @ContextConfiguration( classes = { ApplicationConfiguration.class, WebSecurityConfig.class, WebConfiguration.class, WebTestConfiguration.class })
  @Transactional
  public abstract class AbstractControllerTest {
  
      @Autowired
      private WebApplicationContext webApplicationContext;
  
      @Autowired
      private FilterChainProxy springSecurityFilterChain;
  
      @Autowired  
      protected RestTemplate restTemplate;  
  
      protected MockRestServiceServer mockServer;
  
      @Before
      public void setup() {
          this.mockServer = MockRestServiceServer.createServer(restTemplate);
      }
  
  }
  </code></pre>
  
  <p>The web init class:</p>
  
  <pre><code>public class WebInit implements WebApplicationInitializer {
  
      private static Logger logger = LoggerFactory.getLogger(WebInit.class);
  
      @Override
      public void onStartup(ServletContext servletContext) throws ServletException {
          registerListener(servletContext);
  
          registerDispatcherServlet(servletContext);
  
          registerJspServlet(servletContext);
  
          createSecurityFilter(servletContext);
      }
  
      private void registerListener(ServletContext servletContext) {
          // Create the root application context
          AnnotationConfigWebApplicationContext appContext = createContext(ApplicationConfiguration.class, WebSecurityConfig.class);
  
          // Set the application display name
          appContext.setDisplayName("LearnInTouch");
  
          // Create the Spring Container shared by all servlets and filters
          servletContext.addListener(new ContextLoaderListener(appContext));
      }
  
      private void registerDispatcherServlet(ServletContext servletContext) {
          AnnotationConfigWebApplicationContext webApplicationContext = createContext(WebConfiguration.class);
  
          ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(webApplicationContext));
          dispatcher.setLoadOnStartup(1);
  
          Set&lt;String&gt; mappingConflicts = dispatcher.addMapping("/");
  
          if (!mappingConflicts.isEmpty()) {
            for (String mappingConflict : mappingConflicts) {
              logger.error("Mapping conflict: " + mappingConflict);
            }
            throw new IllegalStateException(
                "The servlet cannot be mapped to '/'");
          }
      }
  
      private void registerJspServlet(ServletContext servletContext) {
      }
  
      private AnnotationConfigWebApplicationContext createContext(final Class... modules) {
          AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
          appContext.register(modules);
          return appContext;
      }
  
      private void createSecurityFilter(ServletContext servletContext) {
          FilterRegistration.Dynamic springSecurityFilterChain = servletContext.addFilter("springSecurityFilterChain", DelegatingFilterProxy.class);
          springSecurityFilterChain.addMappingForUrlPatterns(null, false, "/*");
      }
  
  }
  </code></pre>
  
  <p>The web configuration:</p>
  
  <pre><code>@Configuration
  @EnableWebMvc
  @EnableEntityLinks
  @ComponentScan(basePackages = "com.thalasoft.learnintouch.rest.controller")
  public class WebConfiguration extends WebMvcConfigurerAdapter {
  
      @Override
      public void addArgumentResolvers(List&lt;HandlerMethodArgumentResolver&gt; resolvers) {
          PageableArgumentResolver resolver = new PageableArgumentResolver();
          resolver.setFallbackPageable(new PageRequest(1, 10));
          resolvers.add(new ServletWebArgumentResolverAdapter(resolver));
          super.addArgumentResolvers(resolvers);
      }
  
  }
  </code></pre>
  
  <p>The application configuration is empty for now:</p>
  
  <pre><code>@Configuration
  @Import({ ApplicationContext.class })
  public class ApplicationConfiguration extends WebMvcConfigurerAdapter {
  
      // Declare "application" scope beans here, that is, beans that are not only used by the web context
  
  }
  </code></pre>