Reputation: 5185
First time post here...but I cannot find the solution in the many tutorials, SO posts, and documentation.
Creating a Spring MVC REST webapp using:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.8</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.8</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
<version>1.9.7</version>
</dependency>
My Controller is as
@Controller
public class HomeController {
@RequestMapping(value = "/login", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
@ResponseBody
public String login(@RequestBody Login login) {
if (login != null) {
logger.debug(login.toString());
} else {
logger.error("Null Login JSON received!");
}
return new Login();
}
private class Login {
String username;
String password;
..}
And I am trying to configure it all programatically via:
@Configuration
@EnableTransactionManagement
@EnableWebMvc
@ImportResource("classpath:applicationContext.xml")
@PropertySource("classpath:application.properties")
public class ApplicationContext {
@Bean
public MappingJacksonJsonView mappingJacksonJsonView() {
MappingJacksonJsonView mappingJacksonJsonView = new MappingJacksonJsonView();
return mappingJacksonJsonView;
}
@Bean
public ContentNegotiatingViewResolver contentNegotiatingViewResolver() {
Map<String, String> mediaTypes = new HashMap<String, String>();
mediaTypes.put("json", "application/json");
org.springframework.web.servlet.view.ContentNegotiatingViewResolver contentNegotiatingViewResolver = new ContentNegotiatingViewResolver();
contentNegotiatingViewResolver.setMediaTypes(mediaTypes);
return contentNegotiatingViewResolver;
}
@Bean
public org.codehaus.jackson.map.ObjectMapper objectMapper() {
org.codehaus.jackson.map.ObjectMapper objectMapper = new org.codehaus.jackson.map.ObjectMapper();
return objectMapper;
}
}
But when I send the request via AJAX or Firefox RESTClient:
{"username": "aname", "password" : "ahack"}
I get the message:
"NetworkError: 415 Unsupported Media Type - http://localhost:8080/edm/login"
I would really appreciate any pointers, this one has me stumped.
Upvotes: 1
Views: 13776
Reputation: 979
For this kind of error "NetworkError: 415 Unsupported Media Type",
you just need to investigate the following things: In your Web service:
In the client:
the mapping as follow:
For your problem , I think root cause should be you forgot to set the content type or accept type in AJAX or Firefox RESTClient request.
Upvotes: 0
Reputation: 21
If your configuration is ok, the problem could raise when Spring tries to serialize your parameter. If you have a problem in serialization (for example infinite recursion due to bidirectional properties in oneToMany relations), you get 415 error. Before consuming the web service, try to simulate what Spring does, for example:
try {
ObjectMapper mapper=new ObjectMapper();
//serialize
String json=mapper.writeValueAsString(login);
//deserialize
Login login2 = mapper.readValue(json, Login.class);
} catch (Exception e) {
e.printStackTrace();
}
//consume the ws
restTemplate.postForObject(URI,login,String.class);
if something goes wrong, you get an exception showing you the cause.
Upvotes: 1
Reputation: 49935
You don't need to register AnnotationHandlerMethodAdapter, since you are using Spring 3.1, @EnableMVC alone should be sufficient(which actually registers a RequestMappingHandlerAdapter) - same with objectMapper, contentNegotiatingViewResolver, mappingJacksonJsonView.
You can also annotate your method this way:
@RequestMapping(value = "/login", method = RequestMethod.POST, consumes="application/json", produces="application/json")
Here is a one page test using your same annotations - this test is using Spring-test-mvc:
package org.bk.webtest;
import static org.springframework.test.web.server.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.server.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.server.setup.MockMvcBuilders.*;
import org.junit.Test;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
public class WebContextConfigurationTest {
@Test
public void testWebFlow() throws Exception {
annotationConfigSetup(WebContextConfigurationTest.TestConfiguration.class)
.build()
.perform(post("/login").contentType(MediaType.APPLICATION_JSON).body("{\"username\":\"user\",\"password\":\"password\"}".getBytes()))
.andExpect(status().isOk())
.andExpect(content().string("{\"username\":\"user\",\"password\":\"password\"}"));
}
@Configuration
@EnableWebMvc
@ComponentScan(basePackages="org.bk.webtest")
public static class TestConfiguration{
}
}
@Controller
class JsonController{
@RequestMapping(value = "/login", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
@ResponseBody
public Login login(@RequestBody Login login) {
System.out.println(login);
return login;
}
}
class Login{
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Upvotes: 2