I cannot seem to get this to work for me ,I have seen this in other posts and was hoping someone may be able to spot what im doing wrong.I am trying to get the body of a request to this rest api but cannot seem to pull back what i need and just get null in the string below.
#POST
#Path("/SetFeeds")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public String setFeed(#PathParam("name")String name2, #QueryParam("name") String name,#Context UriInfo uriInfo){
MultivaluedMap<String,String> queryParams = uriInfo.getQueryParameters();
String query = uriInfo.getRequestUri().getQuery();
String response = queryParams.getFirst("name");
return response;
}
A method parameter to accept the body of the request should not be annotated with anything (except in few cases like individual form params and multipart). So to get the raw JSON, you could simply add a String parameter
public String setFeed(#PathParam("name")String name2,
#QueryParam("name") String name,
#Context UriInfo uriInfo,
String jsonBody){
Or if you want to do the more common thing and use POJOs (so you don't need to parse the JSON yourself), you should look at this answer
Great answer, but I would like to add that you can use an object instead of a String and the Jackson of REST will take care the transformation without any further definition.
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public String setFeed(#PathParam("name")String name2,
#QueryParam("name") String name,
MyJson json,
#Context UriInfo uriInfo){
MultivaluedMap<String,String> queryParams = uriInfo.getQueryParameters();
String query = uriInfo.getRequestUri().getQuery();
String response = queryParams.getFirst("name");
return response;
and a pojo as a json object:
#JsonIgnoreProperties(ignoreUnknown = true)
public class MyJson{
private String name;
public MyJson(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
Related
I want to return an error when the body of a REST request is empty (e.g contains only {}) but there is no way to detect if the request body contains an empty JSON or not.
I tried to change #RequestBody(required = true) but it's not working.
#PatchMapping("{id}")
public ResponseEntity<Book> updateAdvisor(#PathVariable("id") Integer id,
#Valid #RequestBody BookDto newBook) {
Book addedBook = bookService.updateBook(newBook);
return new ResponseEntity<>(addedBook,HttpStatus.OK);
}
If the body sent contains an empty JSON I should return an exception.
If the body is not empty and at least one element is provided I won't return an error.
Try #RequestBody(required = false)
This should cause the newBook parameter to be null when there is no request body.
The above still stands and is the answer to the original question.
To solve the newly edited question:
Change the #RequestBody BookDto newBook parameter to a String parameter
(for example, #RequestBody String newBookJson).
Perform pre-conversion validation (such as, "is the body an empty JSON string value").
If the body contains valid JSON,
parse the JSON into to an object (example below).
#Autowired
private ObjectMapper objectMapper; // A Jackson ObjectMapper.
#PatchMapping("{id}")
public ResponseEntity<Book> updateAdvisor(
#PathVariable("id") Integer id,
#Valid #RequestBody String newBookJson)
{
if (isGoodStuff(newBookJson)) // You must write this method.
{
final BookDto newBook = ObjectMapper.readValue(newBookJson, BookDto.class);
... do stuff.
}
else // newBookJson is not good
{
.. do error handling stuff.
}
}
Let's suppose you have a Class BookDto :
public class BookDto {
private String bookName;
private String authorName;
}
We can use #ScriptAssert Annotation on Class BookDto:
#ScriptAssert(lang = "javascript", script = "_this.bookName != null || _this.authorName != null")
public class BookDto {
private String bookName;
private String authorName;
}
then in the resource/controller Class:
#PatchMapping("{id}")
public ResponseEntity<Book> updateAdvisor(#PathVariable("id") Integer id,
#Valid #RequestBody BookDto newBook) {
Book addedBook = bookService.updateBook(newBook);
return new ResponseEntity<>(addedBook,HttpStatus.OK);
}
Now #Valid annotation will validate whatever we have asserted in the #ScriptAssert annotation's script attribute. i.e it now checks if the body of a REST request is empty (e.g contains only {}).
I have a Spring rest endpoint doing a simple hello app. It should accept a {"name":"something"} and return "Hello, something".
My controller is:
#RestController
public class GreetingController {
private static final String template = "Hello, %s!";
#RequestMapping(value="/greeting", method=RequestMethod.POST)
public String greeting(Person person) {
return String.format(template, person.getName());
}
}
Person:
public class Person {
private String name;
public Person() {
this.name = "World";
}
public Person(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
When I make a request to the service like
curl -X POST -d '{"name": "something"}' http://localhost:8081/testapp/greeting
I get
Hello, World!
Looks like it isn't deserializing the json into the Person object properly. It's using the default constructor and then not setting the name. I found this: How to create a POST request in REST to accept a JSON input? so I tried adding an #RequestBody on the controller but that causes some error about "Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported". I see that is covered here: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported for #RequestBody MultiValueMap which suggests removing the #RequestBody
I have tried removing the default constructor which it doesn't like either.
This question covers null values REST webservice using Spring MVC returning null while posting JSON but it suggests adding #RequestBody but that conflicts with above...
You must set the #RequestBody to tell to Spring what should be use to set your personparam.
public Greeting greeting(#RequestBody Person person) {
return new Greeting(counter.incrementAndGet(), String.format(template, person.getName()));
}
You must set 'produces' with #RequestMapping(value="/greeting", method=RequestMethod.POST)
use below code
#RequestMapping(value="/greeting", method=RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
public String greeting(#RequestBody Person person) {
return String.format(template, person.getName());
}
I implemented this POST operation in Jax-RS and it is working fine, however I am sure I can send the body in other way somehow. Any hint to simplify it? (By receiving an object for instance?)
Thanks!
#POST
#Path("updateUser/{name}/{surname}/{address}")
#Produces(MediaType.TEXT_PLAIN)
public Response updateUser(#FormParam("user") String name,
#FormParam("surname") String surname,
#FormParam("address") String address) throws UnknownHostException {
User user;
user = new CorporateUser(name, surname, address);
usersService.updateUser(user);
return Response.ok(user).build();
}
You can pass json string of object by using #consumes annotaion.
#POST
#Path("/updateUser")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.TEXT_PLAIN)
public Response updateUser(User bean) {
usersService.updateUser(user);
return Response.ok(user).build();
}
Add a JSON provider like Jackson to your project.
#POST
#Path("updateUser")
#Consumes(value = { MediaType.APPLICATION_JSON })
#Produces(value = { MediaType.APPLICATION_JSON })
public Response updateUser(NewCorporateUserRequest req) throws UnknownHostException {
User user;
user = new CorporateUser(req.getName(), req.getSurname(), req.getAddress());
usersService.updateUser(user);
return Response.ok().entity(user).type(MediaType.APPLICATION_JSON).build();
}
public class NewCorporateUserRequest implements java.io.Serializable {
private String name;
private String surname;
private String address;
... Getters and Setters.
}
I have a model class with an #XmlRootElement annotation. I want to know how I can receive it as a response in a function.
My model class:
#XmlRootElement
public class SurveyAnswers {
List<Long> Q_id;
Date date;
String SurveyType;
List<Answers> answers;
float versionid;
String mac;
String remarks;
// getter and setter here
}
I have previously used MultivaluedMap<String, String> for all my string based responses, but here it is a different structure to receive.
If your SurveyAnswers class is the only POST param then you can simply do like this:
#POST
#Path("/postpath")
#Consumes(MediaType.APPLICATION_JSON)
public Response handlePostRequest(SurveyAnswers surveyAnswers)
Follow this sample to learn more about consuming custom classes as the input params to jersey webservices:
http://www.mkyong.com/webservices/jax-rs/json-example-with-jersey-jackson/
I am implementing simple RESTful webservice using Jersey API. My server project is hosted on Apache Tomcat ver 6.0 and it contains asm-3.0.jar, jersey-bundle-1.9.1.jar and jsr311-api-1.1.1.jar.
I have two resource classes. One is UserItemsResource which is intended to represent collection of UserItem objects. The other one is UserItemResource which represents a single UserItem resource.
Below is code for UserItemsResource class:
#Path("/useritems")
public class UserItemsResource {
#Context
UriInfo uriInfo;
#Context
Request request;
#Path("{userId}")
public UserItemResource getUserItemResource(#PathParam("userId") long userId) {
return new UserItemResource(uriInfo, request, userId);
}
}
The UserItemResource class:
public class UserItemResource {
#Context
UriInfo uriInfo;
#Context
Request request;
private long userId;
public UserItemResource(UriInfo uriInfo, Request request, long userId) {
this.uriInfo = uriInfo;
this.request = request;
this.userId = userId;
}
#GET
#Produces(MediaType.APPLICATION_JSON)
public UserItem getUserItem() {
return new UserItem(userId, 'M', "Pawan");
}
}
And the UserItem class:
#XmlRootElement
public class UserItem {
private long userId;
private char sex;
private String displayName;
public UserItem() {
}
public UserItem(long userId, char sex, String displayName) {
this.userId = userId;
this.sex = sex;
this.displayName = displayName;
}
public long getUserId() {
return userId;
}
public char getSex() {
return sex;
}
public String getDisplayName() {
return displayName;
}
public void setUserId(long userId) {
this.userId = userId;
}
public void setSex(char sex) {
this.sex = sex;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
}
When I invoke the resource (like /useritems/101), I am getting following response from server.
HTTP/1.1 200 OK
Date: Wed, 24 Oct 2012 11:30:35 GMT
Transfer-Encoding: chunked
Content-Type: application/json
Server: Apache-Coyote/1.1
{
"displayName": "Pawan",
"sex": "77",
"userId": "101"
}
You can see that the value for "sex" attribute is generated as "77", which is ASCII equivalent of character 'M'. I believe this should come as "M" only, so that my client code can successfully parse it back to 'M'. I am using Jackson API (ver 2.0.2) to parse the json entity in the server response back to object of UserItem class.
Am I missing something? Or is this a bug?
Jersey supports few JSON notations and each one of them has a slightly different convention on how the resulting JSON should look like. You can see the difference between notations in this JavaDoc. The default one is MAPPED which put quotes around numbers in JSON output as you've already found out.
There are two things you can do:
turn on the Jackson POJO support which uses the Jackson library to create JSON output (maybe this would be a better option if you're using Jackson on the client side as well). There is also an example how to use it - JacksonJsonProvider.
use NATURAL JSON notation which handles numbers as you'd expect. To do this you need to provide a custom ContextResolver and register it in your application. Examples how to achieve this can be found in Jersey User Guide (JSON Support - Configuration Options) or in one of the samples json-from-jaxb (see JAXBContextResolver).