I am using okhttp lib with Java and PHP. My Java client is running the following code.
public class Connection {
public static final MediaType JSON = MediaType
.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder().url(url).post(body).build();
Response response = client.newCall(request).execute();
return response.body().string();
}
public static void main(String[] args) throws IOException {
Connection example = new Connection();
String json = "{'input':'test'}";
String response = example.post("http://localhost/android_api/index.php", json);
System.out.println(response);
}
}
On the server-side I try to decode the JSON String with code following below but my webservice just return a NULL.
<?php
$rawData = file_get_contents("php://input");
$json = json_decode($rawData);
var_dump($json);
?>
What am I doint wrong?
First, you are calling an http request on the main-thread which will cause an error. So you use AsyncTask
Related
Suffered a lot in finding how to mock http response . Mocking http request for the same library was easy . Thought to create a thread here , to save your time should you need it .
Requirement ->
Wanted to mock a HttpResponse that is returned when any HttpRequest object is executed . (Note - this is specifically for google client api library)
//creating mockContent for httpRequest
MockHttpContent mockHttpContent = new MockHttpContent();
String content = new String("requestBody");
mockHttpContent.setContent(str.getBytes());
//mocking httpResponse and linking to httpRequest's execution
HttpTransport transport =
new MockHttpTransport() {
#Override
public LowLevelHttpRequest buildRequest(String method, String url) throws IOException {
return new MockLowLevelHttpRequest() {
#Override
public LowLevelHttpResponse execute() throws IOException {
MockLowLevelHttpResponse result = new MockLowLevelHttpResponse();
result.setContent("responseBody");
result.setContentEncoding("UTF-8");//this is very important
result.setHeaderNames(List.of("header1","header2"));
result.setHeaderValues(List.of("header1","header2"));
return result;
}
};
}
};
HttpRequest httpRequest = transport.createRequestFactory().buildPostRequest(HttpTesting.SIMPLE_GENERIC_URL,mockHttpContent);
//getting httpResponse from httpRequest
httpResponse = httpRequest.execute();
//condition to verify the content (body) of the response
assertEquals("responseBody",IOUtils.toString(httpResponse.getContent()));
When sending a request in Postman, I get this output:
{
"valid": false,
"reason": "taken",
"msg": "Username has already been taken",
"desc": "That username has been taken. Please choose another."
}
However when doing it using okhttp, I get encoding problems and can't convert the resulting json string to a Java object using gson.
I have this code:
public static void main(String[] args) throws Exception {
TwitterChecker checker = new TwitterChecker();
TwitterJson twitterJson = checker.checkUsername("dogster");
System.out.println(twitterJson.getValid()); //NPE
System.out.println(twitterJson.getReason());
System.out.println("Done");
}
public TwitterJson checkUsername(String username) throws Exception {
HttpUrl.Builder urlBuilder = HttpUrl.parse("https://twitter.com/users/username_available").newBuilder();
urlBuilder.addQueryParameter("username", username);
String url = urlBuilder.build().toString();
Request request = new Request.Builder()
.url(url)
.addHeader("Content-Type", "application/json; charset=utf-8")
.build();
OkHttpClient client = new OkHttpClient();
Call call = client.newCall(request);
Response response = call.execute();
System.out.println(response.body().string());
Gson gson = new Gson();
return gson.fromJson(
response.body().string(), new TypeToken<TwitterJson>() {
}.getType());
}
Which prints this:
{"valid":false,"reason":"taken","msg":"\u0414\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u0443\u0436\u0435 \u0437\u0430\u043d\u044f\u0442\u043e","desc":"\u0414\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u0443\u0436\u0435 \u0437\u0430\u043d\u044f\u0442\u043e. \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0434\u0440\u0443\u0433\u043e\u0435."}
and then throws a NullPointerException when trying to access a twitterJson. Debugger shows that object as being null.
TwitterJson:
#Generated("net.hexar.json2pojo")
#SuppressWarnings("unused")
public class TwitterJson {
#Expose
private String desc;
#Expose
private String msg;
#Expose
private String reason;
#Expose
private Boolean valid;
public String getDesc() {
return desc;
}
public String getMsg() {
return msg;
}
public String getReason() {
return reason;
}
public Boolean getValid() {
return valid;
}
...
How can I fix the encoding issues with okhttp?
It is because the response object can be consumed only once. OKHTTP says that in their documentation. After the execute is invoked, you are calling the response object twice. Store the result of response.body().string() to a variable and then do the convert into GSON.
If I were to use a hello world example...
private void testOkHttpClient() {
OkHttpClient httpClient = new OkHttpClient();
try {
Request request = new Request.Builder()
.url("https://www.google.com")
.build();
Call call = httpClient.newCall(request);
Response response = call.execute();
System.out.println("First time " + response.body().string()); // I get the response
System.out.println("Second time " + response.body().string()); // This will be empty
} catch (IOException e) {
e.printStackTrace();
}
}
The reason it is empty the second time is because the response object can be consumed only once. So you either
Return the response as it is. Do not do a sysOut
System.out.println(response.body().string()); // Instead of doing a sysOut return the value.
Or
Store the value of the response to a JSON then convert it to GSON and then return the value.
EDIT: Concerning Unicode characters. It turned out since my location is not an English-speaking country, the json i was accepting was not in English as well. I added this header:
.addHeader("Accept-Language", Locale.US.getLanguage())
to the request to fix that.
I'm using Servlet to handle request and response.
I have used following code to Servlet my request to sublet using webservice:
JSONObject parans = new JSONObject();
parans.put("commandid", "Enamu7l");
System.out.println("parans = " + parans);
Client restClient = Client.create();
WebResource webResource = restClient.resource("URL");
ClientResponse resp = webResource.accept(MediaType.APPLICATION_JSON)
.post(ClientResponse.class, parans.toJSONString());
Here is my servlet code to receive data.
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String commandid= request.getParameter("commandid");
System.out.println(commandid);
}
commandid recieve null from webservice.
What to do in webservice to get data in servlet?
WebResource not sending the data as part of the url, so you can not use request.getParameter. The data is send as request body using the post method.Read the data using the reader.
StringBuilder sb = new StringBuilder();
while ((s = request.getReader().readLine()) != null) {
sb.append(s);
}
JSONObject jSONObject = new JSONObject(sb.toString());
System.out.println(jSONObject.getString("commandid"));
You are sending JSON in request body, so you need to get it:
String json = request.getReader().lines().collect(Collectors.joining());
Convert to JSON:
JSONObject jsonObject = new JSONObject(json);
And get the value:
String value = jsonObject.getString("commandid");
I am trying to read simple json object in the Java program below:
public class Hello{
#POST
#Path("/jsonRequest")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response getJson(String url) throws InterruptedException, IOException {
JSONObject json= readJsonFromUrl(url);
Response.ResponseBuilder response = Response.ok(json);
return response.build();
}
public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {
JSONObject json = new JSONObject(IOUtils.toString(new URL(url), Charset.forName("UTF-8")));
return json;
}
However, when I try to give a POST request via POSTMAN I get the following error:
javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.net.MalformedURLException: no protocol:{"name":"pallavi",
"location":"Bangalore"}
The POSTMAN request looks like:
Can someone please help me identify where exactly am I going wrong? Any help is highly appreciated
When my Java web application receives an HTTP POST request, it needs to create a new OkHttp3 Request from the HttpServletRequest and send this to another URL. The original post request could be simple form data or multi-part.
Here's the interface that I am looking to implement:
import okhttp3.Request;
public interface OkHttp3RequestBuilder {
Request create(HttpServletRequest request);
}
Looks like the challenge boils down to how I would create an okhttp3.RequestBody. Here's the relevant part of the implementation...
final HttpUrl targetUrl = HttpUrl.get("http://internal.xyz.com");
final RequestBody requestBody = // ?????
final Request httpRequest = new Request.Builder()
.post(requestBody)
.url(targetUrl)
.build();
return httpRequest;
How do I go about doing it? Any suggestions? Thanks!
This should work, but request.getReader() must never have been called as you can call it only once.
Request create(HttpServletRequest request)
{
final HttpUrl targetUrl = HttpUrl.get("http://internal.xyz.com");
final String originalBody = request.getReader().lines().collect (Collectors.joining (System.lineSeparator()));
final RequestBody requestBody = RequestBody.create(MediaType.parse(request.getContentType()), originalBody);
final Request httpRequest = new Request.Builder()
.post(requestBody)
.url(targetUrl)
.build();
return httpRequest;
}
Thanks for your answer, ETL! This seems to work for me:
#Override
public RequestBody getRequestBody(final HttpServletRequest httpServletRequest) throws IOException {
final InputStream inputStream = httpServletRequest.getInputStream();
final byte[] requestBodyBytes = ByteStreams.toByteArray(inputStream);
final String contentType = httpServletRequest.getContentType();
final MediaType mediaType = MediaType.parse(contentType);
final RequestBody requestBody = RequestBody.create(mediaType, requestBodyBytes);
return requestBody;
}