I'm calling the Solr REST api using a Jersey client:
final ClientResponse resp =
client().path(queryPath())
.queryParam("q", query.getQuery())
.queryParam("wt", "json")
.accept(MediaType.APPLICATION_JSON_TYPE)
.get(ClientResponse.class);
resp.getEntity(HttpResponse.class)
and when I run it I get:
A message body reader for Java class challenger.HttpResponse, and Java type class challenger.HttpResponse, and MIME media type text/plain; charset=UTF-8 was not found
Which suggests to me that the response is 'text/plain' rather than the 'application/json' requested.
Is it possible to get a real JSON response from a solr get query or do I need to marshal the JSON returned as text into an object myself?
The wt param, should take care of JSON response format, as per this. However, things can go wrong sometimes, as mentioned like JSON responses can be returned as plain text, with a change in solrconfig.xml. Please check that option also. Hope this helps you in identifying the issue.
Related
What type of object/content is the following piece of response from an API
The Content-Type of the API response is coming as text/HTML
a:3:
{s:6:"status"
;i:1;
s:3:"msg"
;s:22:"Transaction is Pending"
;s:6:"result";
}
Ideally I am expecting a way to make this object into a JSON object or a way in which Java is able to handle such objects.
When I usually make controller endpoints with Java Spring that return JSON data, my return type is usually String; I'll toString() my JSON objects and parse them in my Javascript. Recently, I read somewhere that that wasn't the "correct" way to do it (trying to follow best practices and guidelines). I am starting a new project where my return type is a JSON object (dependency is org.json).
When I try to hit the endpoint in the browser, I'm getting a 406 error with a description of "The resource identified by this request is only capable of generating responses with characteristics not acceptable according to the request "accept" headers.".
Here is what my endpoint looks like now:
#RequestMapping(value = "/api/get-items", method = {RequestMethod.GET, RequestMethod.POST}, headers = "Accept=application/json")
#ResponseBody
public JSONObject doGetItems(HttpServletRequest request, HttpServletResponse response) {
JSONObject data = new JSONObject();
JSONArray items = new JSONArray();
JSONObject item1 = new JSONObject().put("id", 123);
JSONObject item2 = new JSONObject().put("id", 456);
JSONObject item3 = new JSONObject().put("id", 789);
items.put(item1).put(item2).put(item3);
data.put("data", items);
return data;
}
How can I get this to work and return JSON? Or am I supposed to be returning a stringified version of my JSON object and I was doing this correctly all along?
Update
First, I tried taking out the headers parameter in the #RequestMapping annotation. I still got a 406 error.
I then tried changing/adding the parameters in the #RequestMapping annotation, with no luck as well. This is what I tried changing it to:
#RequestMapping(value = "/api/get-items",
method = {RequestMethod.GET, RequestMethod.POST},
headers = "Accept=*/*",
produces = MediaType.APPLICATION_JSON_VALUE)
I'm still getting a 406 error.
The HyperText Transfer Protocol (HTTP) 406 Not Acceptable client error response code indicates that the server cannot produce a response matching the list of acceptable values defined in the request's proactive content negotiation headers, and that the server is unwilling to supply a default representation.
Proactive content negotiation headers include:
A client (e.g. your Web browser or our CheckUpDown robot) can indicate to the Web server (running the Web site) the characteristics of the data it will accept back from the Web server. This is done using 'accept headers' of the following types:
Accept: The MIME types accepted by the client. For example, a browser may only accept back types of data (HTML files, GIF files etc.) it knows how to process.
Accept-Charset: The character sets accepted by the client.
Accept-Encoding: The data encoding accepted by the client e.g. the file formats it understands.
Accept-Language: The natural languages (English, German etc.) accepted by the client.
Accept-Ranges: Whether the client accepts ranges of bytes from the resource i.e. a portion of the resource.
By changing or removing header content at client side it should work.
When you specify headers = "Accept=application/json", then you're saying that an Accept header must be present and have exactly that value.
The client didn't send exactly that value, and there is not reason it should be required to do so, because the Accept header value is a comma-separated list of acceptable values, so it just needs to list application/json, it doesn't have to only specify that value.
To fix, replace headers = "Accept=application/json" with produces = "application/json".
Of course, the client still needs to specify that application/json, application/*, or */* is acceptable.
I am using Jax-RS to make a request to a server, which just returns a one word String, and read that response into a String variable. The issue is that I have no idea how to use the response, as its Content-Type is *; charset=UTF-8 (I verified this using Postman). Jax-RS has difficulty parsing this kind of header. Here is my code:
MultivaluedMap<String, String> formData = new MultivaluedHashMap<String, String>();
formData.add("username", username);
formData.add("target", "10");
Response response = target.request().accept(MediaType.APPLICATION_JSON_TYPE).post(Entity.form(formData));
String responseString = response.readEntity(String.class);
This POST request works. I get an actual Response that I can inspect. However, when I try to read this response into a String (last line of code), the following error is thrown:
org.glassfish.jersey.message.internal.HeaderValueException: Unable to parse "Content-Type" header value: "*; charset=UTF-8" ! at
org.glassfish.jersey.message.internal.InboundMessageContext.exception(InboundMessageContext.java:338) ! at
org.glassfish.jersey.message.internal.InboundMessageContext.singleHeader(InboundMessageContext.java:333) ! at
org.glassfish.jersey.message.internal.InboundMessageContext.getMediaType(InboundMessageContext.java:446) ! at
org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:869)
How do I make Jax-RS properly read this kind of Content-Type?!?
I do not think there is any way to get Jersey / Jax-RS to properly read that kind of Content-Type. A solution for any kind of Response that has a Content-Type that Jax-RS does not like is to simply remove the header and (if needed) add your own Content-Type header that is more appropriate for the Response. Do this BEFORE trying to read the Response entity. This fixed my issue:
response.getHeaders().remove("Content-Type");
response.getHeaders().add("Content-Type", "text/plain");
String responseString = response.readEntity(String.class);
I created a program to get an API response from a URL.
But for some reason it's printing it out in one long line. Is there any way to print it out the way I see it in postman? I guess what I mean is if there is a way to see the response from the API server printed out line by line instead of one long line.
ResponseBody body = response.getBody();
System.out.println("Response Body is: " + body.asString());
The server response is
[RemoteTestNG] detected TestNG version 6.13.1
Status code is 200
Response Body is:
{"request_id":"Z36ec5ee76a4788bfe83655edbbe9f0","status":"OK","data":{ONE LONG STRING OF DATA WITH NO END IN SIGHT!}
You can use prettyPrint method of Response class. Status you will have to print.
(Response to comment)
If your API call return JSON responses, you can use a JSON validator module.
What it does is: you provide a JSON schema, and it compares it with the response. The JSON schema syntax is defined over there: http://json-schema.org/latest/json-schema-validation.html (it looks more complex than it actually is) and here are some examples http://json-schema.org/examples.html. You can define, in your schema, if a field is "required", and also which "type" it should be (string, integer etc.) and many other things!
Here's a simple tutorial that helped me implement it with Rest-Assured: https://blog.jayway.com/2013/12/10/json-schema-validation-with-rest-assured/
My web clients send GET requests with URL query parameters. The receiving App can only accept POST requests with JSON body. I would like to embed a jetty servlet to the receiving App which converts GET requests to POST request, with url parameters being converted to json format body.
Input GET url for example: http://localhost:8081/?key_1=value_1&key_2=3value_2...&key_n=value_n
Expected POST json payload: {"key_1":"value_1", "key_2":"value_2", ..."key_n":"value_n"}
Could you please illustrate how to implement such functions?
I`ve worked with other programming languages, but am completely new to java. I really really appreciate your help.
Thanks and best regards,
Fischlein
You can read all the query string parameter and put it into HashMap. Then serialize this hashmap using jackson-json api or google gson api.
Jackson Reference Url :
http://wiki.fasterxml.com/JacksonHome
Read the parameters from the get request, create a json string and post it with a utility library like http://hc.apache.org/httpclient-3.x/