How to consume json parameter in java restful service - java

How can i consume json parameter in my webservice, I can able to get the parameters using #PathParam but to get the json data as parameter have no clue what to do.
#GET
#Path("/GetHrMsg/json_data")
#Consumes({ MediaType.APPLICATION_JSON })
#Produces(MediaType.APPLICATION_JSON)
public String gethrmessage(#PathParam("emp_id") String empid) {
}
What to use in place of #PathParam and how to parse it later.

I assume that you are talking about consuming a JSON message body sent with the request.
If so, please note that while not forbidden outright, there is a general consensus that GET requests should not have request bodies. See the "HTTP GET with request body" question for explanations why.
I mention this only because your example shows a GET request. If you are doing a POST or PUT, keep on reading, but if you are really doing a GET request in your project, I recommend that you instead follow kondu's solution.
With that said, to consume a JSON or XML message body, include an (unannotated) method parameter that is itself a JAXB bean representing the message.
So, if your message body looks like this:
{"hello":"world","foo":"bar","count":123}
Then you will create a corresponding class that looks like this:
#XmlRootElement
public class RequestBody {
#XmlElement String hello;
#XmlElement String foo;
#XmlElement Integer count;
}
And your service method would look like this:
#POST
#Path("/GetHrMsg/json_data")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public void gethrmessage(RequestBody requestBody) {
System.out.println(requestBody.hello);
System.out.println(requestBody.foo);
System.out.println(requestBody.count);
}
Which would output:
world
bar
123
For more information about using the different kinds of HTTP data using JAXB, I'd recommend you check out the question "How to access parameters in a RESTful POST method", which has some fantastic info.

Bertag is right about the comment on the GET. But if you want to do POST request that consumes json data, then you can refer to the code below:
#POST
#Path("/GetHrMsg/json_data")
#Consumes(MediaType.APPLICATION_JSON)
public Response gethrmessage(InputStream incomingData) {
StringBuilder crunchifyBuilder = new StringBuilder();
try {
BufferedReader in = new BufferedReader(new InputStreamReader(incomingData));
String line = null;
while ((line = in.readLine()) != null) {
crunchifyBuilder.append(line);
}
} catch (Exception e) {
System.out.println("Error Parsing: - ");
}
System.out.println("Data Received: " + crunchifyBuilder.toString());
// return HTTP response 200 in case of success
return Response.status(200).entity(crunchifyBuilder.toString()).build();
}
For referencing please click here

#PathParam is used to match a part of the URL as a parameter. For example in an url of the form http:/example.com/books/{bookid}, you can use #PathParam("bookid") to get the id of a book to a method.
#QueryParam is used to access key/value pairs in the query string of the URL (the part after the ?). For example in the url http:/example.com?bookid=1, you can use #QueryParam("bookid") to get the value of `bookid.
Both these are used when the request url contains some info regarding the parameters and you can use the data directly in your methods.
Please specify the problem in detail if this post doesn't help you.

Related

Restful Webservice string response

I have an endpoint where it supposes to sends a string as a response. My question is do I need to use to response Entity to send string response or just return the string to the consumer?
#GetMapping(value = "/word")
public String getWord() {
String response = "webservice";
return response;
}
Second approach:
#GetMapping(value = "/word", produces ={MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<String> getWord() {
String response = "webservice";
return new ResponseEntity<>(response, HttpStatus.OK);
}
What is the correct approach to send just a string or use response entity?
What is the correct approach to send just a string or use response entity?
The Spring MVC documentation lists a number of types that can be returned from controller methods.
As I previously answered here and here, ResponseEntity<T> represents the entire HTTP response. Besides the body, its API allows you to set headers and a status code to the response.
Returning just a bean instance or a string is fine but doesn't give you much flexibility: In the future, if you need to add a header to the response or modify the status code, for example, you need to change the method return type.

Use #POST instead of #GET to get user input

I am a newbie to JSON. I wish to ask that how can I convert the following code from #GET to #POST so that I can retrieve the appdataid from user JSON input and not from the link.
AppDataService ads = new AppDataService();
#GET
#Path("/{appdataid}")
#Produces(MediaType.APPLICATION_JSON)
public AppData getAppData(#PathParam("appdataid")long appdataid){
return ads.getAppData(appdataid);
}
Code for AppDataService
public AppDataService(){
appdatas.put(1L, new AppData(1,"Success", " ", "123456"));
appdatas.put(2L, new AppData(2,"Failure", " ", "654321"));
}
public AppData getAppData(long id){
return appdatas.get(id);
}
Instead of user entering http://localhost:8080/gni/webapi/appdata/1 for the result
{
"id": 1,
"message": " ",
"status": "Success",
"token": "123456"
}
I hope that I can receive the user input with #POST and JSON format.
I have tried the following code but not working.
#POST
#Path("/{appdataid}")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public AppData getAppData(#PathParam("appdataid")long appdataid){
return ads.getAppData(appdataid);
}
Thanks for everyone that willing to help me.
If you want to POST JSON to your resource, you need to define a POJO for it to deserialise the message body into, for example:
public class AppDataRequest {
#JsonProperty
private long id;
public long getId() {
return id;
}
}
The use this type for in the resource:
#POST
#Path("/")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public AppData getAppData(AppDataRequest appDataRequest){
return ads.getAppData(appDataRequest.getId());
}
Note, the #Path annotation no longer has appdataid templated, and the parameter does not have an annotation.
SIDE NOTE
I have to wonder what you are trying to achieve here. The HTTP methods can and should be used to help describe the behaviour of your system. A request to get data should use a GET resource. POST resources should be used for creating new data. Sometimes there are good reasons to break this convention (such as the lack of a message body in a GET request), but there are usually other ways around them. Everything about your example tells my it should be a GET request, but I do not know the specifics of you application, so feel free to ignore this if it does not apply.
I don't think you really need JSON for that. You can use #FormParam for such a simple payload (ID)
#POST
#Path("some_url")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)//optional
public AppData getAppData(#FormParam("appdataid")long appdataid){
return ads.getAppData(appdataid);
}
You can call your web service from a console (Jersey assumed)
WebTarget target = client.target(UriBuilder.fromUri("http://localhost:8088/Your_root_url").build());
try{
MultivaluedMap<String, Integer> formData = new MultivaluedHashMap<String, String>();
formData.add("appdataid", 1);
Response res= target.path("some_url").request().
post(Entity.entity(formData, MediaType.APPLICATION_FORM_URLENCODED));
AppData entity = (AppData) res.readEntity(AppData.class);
//System.out.println(entity);//if toString() is overriden
}catch(Exception e){
System.out.println(e);
return;
}
EDIT: The only reason I see for wanting to use a POST in this situation is securiry (and even that is arguable)

wrong encoding in jaxrs post method

I'm having an Encoding problem when trying to consume an Arabic json message, however when producing the json in a get method I get the message right here is the code:
#Path("/json")
public class HelloJson {
#GET
#Path("/get")
#Produces("application/json; charset=UTF-8")
public Track getTrackInJSON() {
Track track = new Track();
track.setTitle("الليله");
track.setSinger("عمرو دياب");
return track;
}
#POST
#Path("/post")
#Consumes("application/json; charset=UTF-8")
public Response createTrackInJSON(Track track) throws UnsupportedEncodingException{
String result = new String (("Track saved : " + track).getBytes(), "UTF-8");
System.out.println(result);
return Response.status(201).entity(result).type("text/plain; charset=UTF-8").build();
}
}
you can try this webservice on the following link:
http://java7learning-khalidspace.rhcloud.com/rest/json/get
if asked for authentication use username admin and password admin
this link will return you a json with Arabic values without any Encoding problems.
now take this json message and use it in the post method using the following link:
http://java7learning-khalidspace.rhcloud.com/rest/json/post
you can use the post method using the webservice tester from eclipse or any other webservice just insert the content-type=application/json and authorization = Basic YWRtaW46YWRtaW4= as request headers and but the json in the request body.
the post method will return a massage with the arabic characters as "????"
please tell me what I'm missing and thanks for help.
Already have you tried to send them with the escaped characters?:
{
"title" : "\u0627\u0644\u0644\u064A\u0644\u0647",
"singer" : "\u0639\u0645\u0631\u0648 \u062F\u064A\u0627\u0628"
}
I get with this way using SoapUI and your http://java7learning-khalidspace.rhcloud.com/rest/application.wadl:
Track saved : Track [title=الليله, singer=عمرو دياب]

Get status for a PUT request on Jersey client

I have a webservice defined with Jersey in the server side like this:
#POST
#Consumes(MediaType.APPLICATION_XML)
#Path("/foo")
public Response bar(List<Foo> listFoo) {
try {
//save the resource
} catch (Exception e) {
log.error("Error saving", e);
return Response.status(Status.INTERNAL_SERVER_ERROR).build();
}
return Response.status(Status.OK).build();
}
I am trying to get the server status in my Jersey client like this:
Response response = ws.type(MediaType.APPLICATION_XML).post(Response.class,list);
But I get the error:
A message body reader for Java class javax.ws.rs.core.Response, and Java type class javax.ws.rs.core.Response, and MIME media type application/xml was not found javax.ws.rs.core.Response
I don't really need the Response object, just the status code, how could I get it?
Ok, I solved it by changing the request response type:
Response response = ws.type(MediaType.APPLICATION_XML).post(Response.class,list);
with
ClientResponse response = ws.type(MediaType.APPLICATION_XML).post(ClientResponse.class,list);
being ClientResponse a com.sun.jersey.api.client.ClientResponse
Add #Consumes annotation to your web-serivce and the parameter to your bar() method, because you are trying to put there some object named list.
And I would recommend you to use #POST instead, because canonical #PUT does not return a response.
UPD. By the way, you have your entity empty - you should better remove your #Produces annotation and just return Response with its status set.
UPD2. and remove .accept(MediaType.APPLICATION_XML) method from client side.

Changing content type in jax-rs REST service

Forgive me, but I may not be familiar with all the lingo necessary to ask this question properly.
I'm working on a fairly simple REST web service in Java using the org.apache.cxf.jaxrs.ext implementation of jax-rs. The method header is like this:
#GET
#Path("json/{fullAlias}")
#Produces({"application/json"})
public String json(#PathParam("fullAlias") String fullAlias, #Context MessageContext req)
where MessageContext is org.apache.cxf.jaxrs.ext.MessageContext.
There are two things I'm trying to accomplish that I can't seem to figure out:
Change the content-type if certain conditions are met (e.g. for an error)
Change the status code of the response
I've tried using changing the response by accessing it through the MessageContext:
HttpServletResponse response = req.getHttpServletResponse();
response.setContentType("text/plain")
response.setStatus("HttpServletResponse.SC_BAD_REQUEST);
But these changes have no bearing on the response sent; with or without the #Produces annotation, setting the content type inside the method doesn't affect the actual content type (With the annotation, it of course returns "application/json", without it defaults to "text/html").
I am returning a simple String as the body. I've entertained trying to return a javax.ws.rs.core.Response object to do what I want, but I don't know much about it.
How would I change the content type and/or the status codes from inside this method?
One approach is to throw a WebApplicationException, as described by Pace, which will work if you are looking to specifically handle an error condition. If you are looking to be able to change your content at any time for any reason, then you will want to take a look at returning a Response as the result of your service method rather than a String. Returning a Response gives you the greatest amount of control over how your service responds to the client request (it does require more code than returning a simple string).
Here is an example of how you would can make use of the Response object:
#GET
#Path("json/{fullAlias}")
public Response json(#PathParam("fullAlias") String fullAlias, #Context MessageContext req) {
...
if (success) {
ResponseBuilder rBuild = Response.ok(responseData, MediaType.APPLICATION_JSON);
return rBuild.build();
}
else {
ResponseBuilder rBuild = Response.status(Response.Status.BAD_REQUEST);
return rBuild.type(MediaType.TEXT_PLAIN)
.entity("error message")
.build();
}
}
I'm not sure if it's the best approach but I've done the following to solve your question #1.
public WebApplicationException createStatusException(String statusMessage) {
ResponseBuilder rb = Response.noContent();
rb = rb.type(MediaType.TEXT_PLAIN);
rb = rb.status(Status.BAD_REQUEST);
rb = rb.entity(statusMessage);
return new WebApplicationException(rb.build());
}
EDIT: I then threw the resulting WebApplicationException.
You can write your own Response Filter to change the content-type header.
#Provider
public class MimeAddingFilter implements ContainerResponseFilter {
#Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
throws IOException {
responseContext.getHeaders().add("Content-Type", "image/png");
}
}
This filter will add the "image/png" content-type header. You can also change or remove headers in JAX-RS response filters.

Categories

Resources