How to pass json data with GET method call in java RestAPI - java

I need make my method capable of accepting JSON data. Say I need to make a GET REST method call with JSON data.
GET /player/login/ HTTP/1.0
Content-Type: application/json
Request Body
{
"username": ”xyz”,
"password": "234fsf34"
}
I am not getting how to take this JSON data within my REST API method.
#GET
#Path("player/login")
#Produces("application/json)
public responseData loginPlayer(){
}

If you want to use authentication with a GET, the 'proper' way to do it is to use basic access authentication.
http://en.wikipedia.org/wiki/Basic_access_authentication
The client takes the username and password and forms a string of the form user:password. So in your example, that will be:
"xyz:234fsf34"
The client then base64 encodes this string. If the client is also Java, you could use the apache commons Base64 class for encoding/decoding:
http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html
So you get something like:
"eHl6OjIzNGZzZjM0"
And the client sends this in the GET, but as an HTTP Header (not Request Body):
GET /player/login/ HTTP/1.0
Content-Type: application/json
Authorization: Basic eHl6OjIzNGZzZjM0
The server reads this in the HTTP Header 'Authorization' much like the example code here:
https://cwiki.apache.org/WINK/jax-rs-http-headers.html
Then decodes it with the (Base64 apache commons class).
Then you can respond to the GET with appropriate data.

From the syntax, it appears you are using JAX-RS.
You need to use the #Consumes annotation.
The documentation is for #Consumes is at:
http://docs.oracle.com/javaee/6/tutorial/doc/gilik.html#gipyt
A rather detailed tutorial (which uses Jersey, the reference JAX-RS implementation) is here:
http://blogs.oracle.com/enterprisetechtips/entry/configuring_json_for_restful_web
Eventually, your method should be defined to accept the deserialized java object corresponding to the JSON body received from the client, and you need to set up things so that this deserialization is done before your method gets invoked. Read the second link for how to do it.
On a side note: GET methods typically do not have a 'Request Body'. It is kind of weird to have that. The POST method is meant for posting request bodies. While the HTTP standard does not explicitly disallow GET requests to have a body, POST is the appropriate choice.

Related

How to have different JSON responses registered for a GET call

GET http://localhost/foo/api/v1/bars/:id
How to have different JSON responses registered for a GET call. We would like the GET call to return a separate response based on whether a CLI is invoking or the user interface is calling the API by passing a query parameter. But how do we register different serializers dynamically on the response.
You can use a User-Agent request header to identify the application doing the request. There are good tutorials to check how to access the headers in Spring, like this Baeldung one.

Is it good practice to use #Produces("application/json") on all JSON producing endpoints?

We started using Jersey/JAX-RS for internal REST endpoints that get used by our front-end code. Endpoints that have to return a result, always send JSON objects.
For debugging purposes, we are using the firefox restclient extension. Until recently, I would just enter the URL and hit send, and would get back content displayed as JSON.
But when I did that this morning, the FF extension comes back and tells me that I have to change the response type to binary (BLOB). Doing so results in displaying an encoded string instead of JSON.
I could resolve that by setting a request header (Accept: to be application/json).
Doing some more research, I came across this question. My conclusion is: probably we should add #Produces("application/json") to all these endpoints.
Question: is it really that simple, or are there good technical reasons to not do that?
You should always declare the #Produces and #Consumes annotations (either at the class level or method level) for the purpose of Content Negotiation and HTTP protocol correctness. Without these annotations, the result will be dependent on the client request and the default behavior of the server (which may be different across implementations), which leads to unpredictable and ambiguous results.
With these annotations, we advertise what media types we can produce and consume. On Retrieve (GET) requests, the client should send an Accept header with the media type of the resource they expect back. And on Create requests (PUT, POST), the client should send a Content-Type header telling the server what media type the data is that they are sending. If these headers don't match what the server is advertised to handle, then the client will get error responses back telling them what the problem is; with a Retrieve request and a non-matching Accept header, the response will be a 406 Not Acceptable. With a Create request and a non-matching Content-Type header, the response will be a 415 Unsupported Media Type.
This is how content negotiation works. And to make sure our server behaves as the clients expect, we should declare what we can handle on the server. The annotations do just this.
As you mentioned, when you left off the #Produces, the client told you you needed to change the response type. This is because the result was that the Content-Type response header was set to application/octet-stream, which is what the answers here conclude. Clients use the Content-Type header to determine how to handle the response.
That last example was for a Retrieve request. If we left off the #Consumes on a Create endpoint, a lot of different things can go wrong. Take for example we have an endpoint that we want to accept JSON, so we create a POJO to map the JSON to.
#POST
public Response create(Customer customer) {}
For this to work, it is dependent on the client setting the Content-Type header on the request to application/json. But without the #Consumes annotation, we are basically advertising this endpoint to be able to accept any media type, which is just ridiculous. The #Consumes annotation acts like a guard saying "If you don't send the right type of data, you cannot pass". But since we don't have the guard, all data is allowed through, and the result is unpredictable, because depending on what the client sets the Content-Type to, we don't know what MessageBodyReader1 will handle the conversion from the entity body to Customer. If the correct MessageBodyReader is not chosen (the one that converts JSON to POPJOs), then most likely it will lead to an exception, and the client will get back a 500 Internal Server Error, which is not as specific as getting a 415 Unsupported Media Type.
1. See chapter 8 and 9 of the Jersey docs. It will explain how entity bodies are converted to Java objects (and vice versa) using MessageBodyReader and MessageBodyWriter, respectively.
Is it good practice to use #Produces("application/json") on all JSON producing endpoints?
If your resource methods produce JSON as representation of your resources, they should be annotated with #Produces(MediaType.APPLICATION_JSON). As a result, the response will have a Content-Type header indicating the media type of the payload.
The #Produces annotation is also used for request matching: The JAX-RS runtime matches the media type sent in the Accept header with the media type defined in the #Produces annotation.
If you don't want to annotate every resource method in your application, you can annotate the resource classes instead. It will indicate that all methods defined in such class must produce JSON as representation of your resources.
The media type defined in the #Produces annotation indicates the media type that will be produced by the MessageBodyWriter instances registered in the application. Consider the following example:
#GET
#Produces(MediaType.APPLICATION_JSON)
public Foo getFoo() {
Foo foo = new Foo();
return Response.ok(foo).build();
}
Once the getFoo() method is annotated with #Produces(MediaType.APPLICATION_JSON), JAX-RS will write the Foo instance as a JSON document. It's done in a MessageBodyWriter implementation. If your application uses Jackson, for example, the JacksonJsonProvider will be used to convert Java objects to JSON documents.

Reading URL parameters when POST request with data arrives in Java Servlet

In Java servlets you read a JSON from a POST request e.g. via
new JSONObject(toString(httpRequest.getInputStream()))
Now additionally to the JSON I would like to specify parameters in the URL, they can be read via:
httpRequest.getParameterMap().get("someURLParam")
All is working (I'm using AJAX post requests and jetty for server side)
BUT
I'm concerned and confused if and when these two methods influence each other as the javadocs from javax.​servlet.​ServletRequest.getParamter(String) says:
If the parameter data was sent in the request body, such as occurs
with an HTTP POST request, then reading the body directly via
ServletRequest.getInputStream or ServletRequest.getReader can
interfere with the execution of this method.
What does it mean in my case? Or do they only interfere if content type is x-www-form-urlencoded? Or only if using getParameter and the method getParameterMap is fine?
If you are only using getParameter/getParameterMap, you will be fine. This is because, behind the scenes, those methods may call getInputStream. The spec says MAY because it's up to the implementation, so the behavior may vary from one container to another.
If your content isn't form encoded, or you are processing a GET request, etc., getParameter/getParameterMap only needs to get the parameters from the query string, so it makes sense that Jetty wouldn't read the body in those cases.

For a #GET operation which one to use #QueryParam or #FormParam

I am developing a server side application (not client). I have a list operation where I am using #GET and I am passing the parameters as #QueryParam. Should I use #FormParam? Will it be helpful while developing the client?
The #FormParam annotation will expect the parameter to be in the body of the request as sent by an HTML form submit.
An HTTP GET should not use a request body. So, keep using #QueryParam for #GET.
See also:
HTTP GET with request body

How to distinguish what format a client requests back to my REST webservice?

I have a Java WebService setup which consumes an xml file and want to be able to produce either xml or json based on what the client requests. I know that this is possible through reading up on Jersey REST methods but it does not show how to extract this information. I have also looked on google all over but can't seem to find any examples of this.
http://wikis.sun.com/display/Jersey/Overview+of+JAX-RS+1.0+Features is the site that I was initially referencing which shows that it is possible, I was just wondering if anyone would be able to help me find out how to actually distinguish the client's request. Is it in the html header? body? And if so what is the proper way to extract it?
This is what my method currently looks like, I do not have any issues with connection, just finding out what the client requests as a return type.
#POST
#Path("getStatisticData")
#Produces ({"application/xml","application/json"})
#Consumes ("application/xml")
public String getStatisticData(#FormParam("xmlCoords") String xmlFile) throws Exception{
Thanks in advance.
You can extract it using the #HeaderParam annotation:
...
public String getStatisticData(#HeaderParam("Accept") String accept,
#FormParam("xmlCoords") String xmlFile) throws Exception {
...
}
The Accept header in the request is used for the client to indicate to the server what methods it supports.
If the client can set HTTP headers, the proper way to do it is to use the Accept header:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
IF this is not possible, the type requested could be passed in as an argument.
Alternatively, expose two different web services: one that returns XML, one that returns JSON. Each web service would call the same code but with a parameter specifying which format to use.

Categories