I have a problem with my Spring Rest controller.
I am trying to post (PUT) data from my client (angularJS) to my server (Spring), but every time I try to send something I get a 415 Media not supported
error.
With Maven I have added jackson-core (2.6.3)
and jackson-databind (2.6.3)
to my Spring API. I am also using @EnableWebMvc
to automatically add the Jackson message converter to Spring. In my Spring controller I am using @RestController
for access to the REST methods of Spring.
My REST API controller:
@RequestMapping(value = "/location/update/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
public RippleUser updateUserLocation(@PathVariable("id") Integer id, @RequestBody RippleUser user) {
return user;
}
I have tried differend types of consumes:
MediaType.APPLICATION_JSON_VALUE
"application/json"
- Without consumes
- And so on
My RippleUser model (partially)
@Entity
@Table(name = "user")
@JsonRootName(value = "user")
public class RippleUser implements Serializable {
@NotNull
@Column(name = "active", nullable = false)
private boolean activeUser;
@Column(name = "latitude", nullable = true)
private Float lattitude;
@Column(name = "longitude", nullable = true)
private Float longitude;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "lastActive", nullable = true)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy HH:mm:ss")
private Date timestamp;
}
In this model I have all the necessary getters and setters.
My AngularJS client:
httpService.updateInBackend = function (url, data, callback, errorCallback) {
http.put(url, data)
.then(function successCallback(response) {
callback(response.data);
}, function errorCallback(response) {
errorCallback(response);
});
};
The URL: http://server:port/app/location/update/{id}
The data:
params: {
{
"user": {
"latitude": 52.899370,
"longitude": 5.804548,
"timestamp": 1449052628407
}
}
};
For this method I also added @JsonRootName(value = "user")
to my RippleUser model.
I have also tried without the user attribute (also removed it from my model):
params: {
{
"latitude": 52.899370,
"longitude": 5.804548,
"timestamp": 1449052628407
}
};
The AngularJS HTTP method (PUT, POST, DELETE, GET, and so on) checks what type is in the parameters and automatically sets the right headers.
Chrome Postman
Just to make sure I have also tried this method in the Chrome Postman plugin
The URL: http://server:port/app/location/update/2
Method: PUT
Headers: Content-Type: application/json
Body:
{
"latitude": 52.899370,
"longitude": 5.804548,
"timestamp": 1449052628407
}
The error this gives is:
HTTP Status 415 The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.
Update
I can receive information in my RestController when I change my @ResponseBody from RippleUser to String:
@RequestMapping(value = "/location/update/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
public RippleUser updateUserLocation(@PathVariable("id") Integer id, @RequestBody String user) {
return user;
}
I also tried sending an empty user object, but that results in the same error message
Answer to my problem is below.
The problem with this code is a bit different than I expected. The 415 media not supported error is thrown by Spring, because it could not fill in all the required fields with the post.
My solution was to add a class especially used by Spring to convert data to and from while sending and receiving. The benefit of this extra class is that I can manage the data the API sends and receives.
UserLocation
Adding the following class to my project did the trick (with getters and setters):
This class contains all the necessary data for my PUT request. Spring automatically fills in all the fields.
Controller
To make this work I also had to modify my controller. The new code is as follows:
Hope this helps anyone