Let's say that I have a Spring 4 web application with a Hibernate-based persistence layer. I'd like to create a RestController
that supports basic CRUD operations for my models. Creating a method for fetching records works without a hitch:
@RequestMapping(value = "/stuff/list", method = RequestMethod.GET)
public List<Stuff> getStuff(){
return stuffService.findAll();
}
Jackson handles the object serialization, no problem. But what if I want to add a method for creating new records via a POST request? Is there any easy way to support a simple method like this?
@RequestMapping(value = "/stuff/new", method = RequestMethod.POST)
public Integer getStuff(@RequestParam("stuff") Stuff stuff){
return stuffService.save(stuff);
}
Is something like this possible? Or do I need to manually map posted form data to a new object?
SOLUTION
Here is how I solved my problem, there were a couple steps. First, my final controller method:
@RequestMapping(value = "/stuff/new", method = RequestMethod.POST)
public Integer getStuff(@RequestBody Stuff stuff){
return stuffService.save(stuff);
}
I already had a filter applied to all requests to the application API, to allow cross origin resource sharing, but modifications to this were needed to allow requests to specify content type:
public class SimpleCORSFilter implements Filter{
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Content-Type");
filterChain.doFilter(servletRequest, servletResponse);
}
@Override public void init(FilterConfig filterConfig) throws ServletException { }
@Override public void destroy() { }
}
Which is registered in my web.xml
file:
<filter>
<filter-name>cors</filter-name>
<filter-class>com.company.app.util.SimpleCORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
Now when I make a request, such as the one below, it will correctly map my submitted JSON to my model and persist a new instance:
var stuff = {
name: "Some stuff",
description: "This is some stuff."
}
$.ajax({
url: url,
method: "post",
dataType: "json",
data: JSON.stringify(stuff),
contentType: "application/json"
}).done(function(data){
console.log(data);
}).fail(function(x, status, e){
console.log(e);
});