Why try-with-resources causes Truncated chunk error with CloseableHttpClient? - java

Could you please help me with the following:
I have the following method:
public static CloseableHttpResponse getRequest (String url) {
try (CloseableHttpClient httpClient = HttpClients.createDefault();){
HttpGet httpget = new HttpGet(url); //http get request (create get connection with particular url)
return httpClient.execute(httpget);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
Where I use CloseableHttpClient with try-with-resources
I invoke method in some simple test:
CloseableHttpResponse closeableHttpResponse = RestClient.getRequest("https://reqres.in/api/users?page=2");
String responseString = EntityUtils.toString(closeableHttpResponse.getEntity(), "UTF-8");
JSONObject responseJson = new JSONObject(responseString);
System.out.println(responseJson);
And I am getting error: org.apache.http.TruncatedChunkException: Truncated chunk (expected size: 379; actual size: 358)
When I am not using try-with-resources like that:
public static CloseableHttpResponse getRequest (String url) throws IOException {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpget = new HttpGet(url); //http get request (create get connection with particular url)
return httpClient.execute(httpget);
}
I have no error at all! Could you please explain - what the wrong? I am newbie and have no clue - some examples from internet are working good...

The try-with-resources block will automatically call close() on the object, so the return from one of those getRequest calls is a closed CloseableHttpClient instance.
The call without try-with-resources will return a working (not closed) CloseableHttpClient.

Related

Send HTTPS request with JSON through Java [duplicate]

I would like to make a simple HTTP POST using JSON in Java.
Let's say the URL is www.site.com
and it takes in the value {"name":"myname","age":"20"} labeled as 'details' for example.
How would I go about creating the syntax for the POST?
I also can't seem to find a POST method in the JSON Javadocs.
Here is what you need to do:
Get the Apache HttpClient, this would enable you to make the required request
Create an HttpPost request with it and add the header application/x-www-form-urlencoded
Create a StringEntity that you will pass JSON to it
Execute the call
The code roughly looks like (you will still need to debug it and make it work):
// #Deprecated HttpClient httpClient = new DefaultHttpClient();
HttpClient httpClient = HttpClientBuilder.create().build();
try {
HttpPost request = new HttpPost("http://yoururl");
StringEntity params = new StringEntity("details={\"name\":\"xyz\",\"age\":\"20\"} ");
request.addHeader("content-type", "application/x-www-form-urlencoded");
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
} catch (Exception ex) {
} finally {
// #Deprecated httpClient.getConnectionManager().shutdown();
}
You can make use of Gson library to convert your java classes to JSON objects.
Create a pojo class for variables you want to send
as per above Example
{"name":"myname","age":"20"}
becomes
class pojo1
{
String name;
String age;
//generate setter and getters
}
once you set the variables in pojo1 class you can send that using the following code
String postUrl = "www.site.com";// put in your url
Gson gson = new Gson();
HttpClient httpClient = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(postUrl);
StringEntity postingString = new StringEntity(gson.toJson(pojo1));//gson.tojson() converts your pojo to json
post.setEntity(postingString);
post.setHeader("Content-type", "application/json");
HttpResponse response = httpClient.execute(post);
and these are the imports
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
and for GSON
import com.google.gson.Gson;
#momo's answer for Apache HttpClient, version 4.3.1 or later. I'm using JSON-Java to build my JSON object:
JSONObject json = new JSONObject();
json.put("someKey", "someValue");
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
try {
HttpPost request = new HttpPost("http://yoururl");
StringEntity params = new StringEntity(json.toString());
request.addHeader("content-type", "application/json");
request.setEntity(params);
httpClient.execute(request);
// handle response here...
} catch (Exception ex) {
// handle exception here
} finally {
httpClient.close();
}
It's probably easiest to use HttpURLConnection.
http://www.xyzws.com/Javafaq/how-to-use-httpurlconnection-post-data-to-web-server/139
You'll use JSONObject or whatever to construct your JSON, but not to handle the network; you need to serialize it and then pass it to an HttpURLConnection to POST.
protected void sendJson(final String play, final String prop) {
Thread t = new Thread() {
public void run() {
Looper.prepare(); //For Preparing Message Pool for the childThread
HttpClient client = new DefaultHttpClient();
HttpConnectionParams.setConnectionTimeout(client.getParams(), 1000); //Timeout Limit
HttpResponse response;
JSONObject json = new JSONObject();
try {
HttpPost post = new HttpPost("http://192.168.0.44:80");
json.put("play", play);
json.put("Properties", prop);
StringEntity se = new StringEntity(json.toString());
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(se);
response = client.execute(post);
/*Checking response */
if (response != null) {
InputStream in = response.getEntity().getContent(); //Get the data in the entity
}
} catch (Exception e) {
e.printStackTrace();
showMessage("Error", "Cannot Estabilish Connection");
}
Looper.loop(); //Loop in the message queue
}
};
t.start();
}
Try this code:
HttpClient httpClient = new DefaultHttpClient();
try {
HttpPost request = new HttpPost("http://yoururl");
StringEntity params =new StringEntity("details={\"name\":\"myname\",\"age\":\"20\"} ");
request.addHeader("content-type", "application/json");
request.addHeader("Accept","application/json");
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
// handle response here...
}catch (Exception ex) {
// handle exception here
} finally {
httpClient.getConnectionManager().shutdown();
}
I found this question looking for solution about how to send post request from java client to Google Endpoints. Above answers, very likely correct, but not work in case of Google Endpoints.
Solution for Google Endpoints.
Request body must contains only JSON string, not name=value pair.
Content type header must be set to "application/json".
post("http://localhost:8888/_ah/api/langapi/v1/createLanguage",
"{\"language\":\"russian\", \"description\":\"dsfsdfsdfsdfsd\"}");
public static void post(String url, String json ) throws Exception{
String charset = "UTF-8";
URLConnection connection = new URL(url).openConnection();
connection.setDoOutput(true); // Triggers POST.
connection.setRequestProperty("Accept-Charset", charset);
connection.setRequestProperty("Content-Type", "application/json;charset=" + charset);
try (OutputStream output = connection.getOutputStream()) {
output.write(json.getBytes(charset));
}
InputStream response = connection.getInputStream();
}
It sure can be done using HttpClient as well.
You can use the following code with Apache HTTP:
String payload = "{\"name\": \"myname\", \"age\": \"20\"}";
post.setEntity(new StringEntity(payload, ContentType.APPLICATION_JSON));
response = client.execute(request);
Additionally you can create a json object and put in fields into the object like this
HttpPost post = new HttpPost(URL);
JSONObject payload = new JSONObject();
payload.put("name", "myName");
payload.put("age", "20");
post.setEntity(new StringEntity(payload.toString(), ContentType.APPLICATION_JSON));
For Java 11 you can use the new HTTP client:
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("http://localhost/api"))
.header("Content-Type", "application/json")
.POST(ofInputStream(() -> getClass().getResourceAsStream(
"/some-data.json")))
.build();
client.sendAsync(request, BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join();
You can use publishers from InputStream, String, File. Converting JSON to a String or IS can be done with Jackson.
Java 11 standardization of HTTP client API that implements HTTP/2 and Web Socket, and can be found at java.net.HTTP.*:
String payload = "{\"name\": \"myname\", \"age\": \"20\"}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder(URI.create("www.site.com"))
.header("content-type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
Java 8 with apache httpClient 4
CloseableHttpClient client = HttpClientBuilder.create().build();
HttpPost httpPost = new HttpPost("www.site.com");
String json = "details={\"name\":\"myname\",\"age\":\"20\"} ";
try {
StringEntity entity = new StringEntity(json);
httpPost.setEntity(entity);
// set your POST request headers to accept json contents
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
try {
// your closeablehttp response
CloseableHttpResponse response = client.execute(httpPost);
// print your status code from the response
System.out.println(response.getStatusLine().getStatusCode());
// take the response body as a json formatted string
String responseJSON = EntityUtils.toString(response.getEntity());
// convert/parse the json formatted string to a json object
JSONObject jobj = new JSONObject(responseJSON);
//print your response body that formatted into json
System.out.println(jobj);
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
I recomend http-request built on apache http api.
HttpRequest<String> httpRequest = HttpRequestBuilder.createPost(yourUri, String.class)
.responseDeserializer(ResponseDeserializer.ignorableDeserializer()).build();
public void send(){
ResponseHandler<String> responseHandler = httpRequest.execute("details", yourJsonData);
int statusCode = responseHandler.getStatusCode();
String responseContent = responseHandler.orElse(null); // returns Content from response. If content isn't present returns null.
}
If you want send JSON as request body you can:
ResponseHandler<String> responseHandler = httpRequest.executeWithBody(yourJsonData);
I higly recomend read documentation before use.

Right way to close CloseableHttpResponse/CloseableHttpClient [duplicate]

This question already has answers here:
What is the difference between CloseableHttpClient and HttpClient in Apache HttpClient API?
(8 answers)
Closed 2 years ago.
I'm using CloseableHttpResponse (from apache-httpclient-4.5.3) and I'm not sure I'm using it right, I saw an answer with no votes to use EntityUtils.consume on finally:
CloseableHttpResponse response1 = httpclient.execute(httpGet);
try {
System.out.println(response1.getStatusLine());
} finally {
EntityUtils.consume(response1.getEntity());
CloseableHttpClient is abstract and has no close method to call although in this answer it's used:
CloseableHttpResponse response = httpclient.execute(httpget);
try {
//do something
} finally {
response.close();
}
Currently I'm using try with resources for CloseableHttpClient and CloseableHttpResponse inside of send method.
Am I not missing any resource open or using it in a wrong way?
private CloseableHttpResponse send()
throws URISyntaxException, UnsupportedEncodingException, IOException, ClientProtocolException {
URIBuilder uriBuilder = new URIBuilder(BASE_URL);
HttpHost target = new HttpHost(uriBuilder.getHost(), uriBuilder.getPort(), uriBuilder.getScheme());
HttpPost post = new HttpPost(uriBuilder.build());
try (CloseableHttpClient httpClient = HttpClients.custom().build(); CloseableHttpResponse response = httpClient.execute(target, post)) {
return response;
}
It has been explained in detail in the docs here.
Quoting the pseudo code from the docs here's a typical way to allocate/deallocate an instance of CloseableHttpClient:
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
<...>
}
The same applies to CloseableHttpResponse :
try (CloseableHttpResponse response = httpclient.execute(httpget)) {
<...>
}
Now, about the close method in CloseableHttpClient. CloseableHttpClient is an abstract class that implements Closeable interface. That is, although it doesn't have a close method itself the classes that extend it are required to implement the close method. One class is InternalHttpClient. You can check the source code for the details.
Before Java7, explicit close would be required:
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
<...>
} finally {
httpclient.close();
}
CloseableHttpResponse response = httpclient.execute(httpget);
try {
<...>
} finally {
response.close();
}
You can avoid the finally by using the try(resource)
try (CloseableHttpResponse response = httpclient.execute(httpGet)) {
... }

Oauth token requests before provider credentials issuance

Please forgive me if I ask something stupid, I am a novice here. I need to implement OAuth in my Java application to authenticate against launchpad.net API. The documentation specifies an initiation of a token request with three parameters : oauth_consumer_key e.g. (name of my application), oauth_signature_method e.g. "PLAINTEXT" and oauth_signature e.g. The string "&". I realised that most OAuth libraries require that
I have already acquired a Consumer key and Consumer Id/Secret from
the OAuth provider (e.g as issued in Twitter), and most examples are organised in this manner. However, launchpad.net will issue these parameters only after issuance of request token (they use no third party provider). How can I proceed?I am currently stuck after trying some libraries that threw errors. Many thanks for any useful information. The official launchpad library is in python.
My initial code is below:
public class Quicky {
public static void main(String[] args) throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpGet httpGet = new HttpGet("https://launchpad.net/+request-token");
CloseableHttpResponse response1 = httpclient.execute(httpGet);
try {
System.out.println("Your current GET request status:" + response1.getStatusLine());
HttpEntity entity1 = response1.getEntity();
EntityUtils.consume(entity1);
} finally {
response1.close();
}
HttpRequest request;
HttpPost httpPost = new HttpPost("https://launchpad.net/+request-token");
PostMethod poster = new PostMethod();
List <NameValuePair> postParams = new ArrayList <NameValuePair>();
postParams.add(new BasicNameValuePair("oauth_customer_key", "XXXX"));
postParams.add(new BasicNameValuePair("oauth_signature_method", "PLAINTEXT"));
postParams.add(new BasicNameValuePair("oauth_signature", "&"));
httpPost.setEntity(new UrlEncodedFormEntity(postParams, "utf-8"));
// httpPost.setEntity(entity1);
httpclient.execute(httpPost);
HttpParameters requestParams = (HttpParameters) postParams;
CloseableHttpResponse response2 = httpclient.execute(httpPost);
try {
System.out.println("Your current POST request status:" + response2.getStatusLine());
HttpEntity entity2 = response2.getEntity();
// do something useful with the response body
// and ensure it is fully consumed
EntityUtils.consume(entity2);
} finally {
response2.close();
}
} finally {
httpclient.close();
}
}
}
I finally resolved the issue error messages after some research and code re-factoring. The correct code is below, maybe it could be useful to someone out there.
public class LaunchPadTokenRetriever {
public static void main(String[] args) throws ClientProtocolException, IOException{
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("https://launchpad.net/+request-token");
httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
List <NameValuePair> urlParams = new ArrayList <NameValuePair>();
urlParams.add(new BasicNameValuePair("oauth_signature", "&"));
urlParams.add(new BasicNameValuePair("oauth_consumer_key", "tester"));
urlParams.add(new BasicNameValuePair("oauth_signature_method", "PLAINTEXT"));
httpPost.setEntity(new UrlEncodedFormEntity(urlParams));
CloseableHttpResponse response = httpclient.execute(httpPost);
System.out.println(response);
try {
System.out.println(response.getStatusLine());
HttpEntity entity = response.getEntity();
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = httpclient.execute(httpPost, responseHandler);
System.out.println("Initial credentials ---> "+ responseBody);
System.out.println();
String getresponse = responseBody;
EntityUtils.consume(entity);
} finally {
response.close();
}
}
}

How to send HttpPost every 5 secs

In a Java, I want to send HttpPost every 5 secs without waiting for the response. How can I do that?
I use the following code:
HttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
StringEntity params = new StringEntity(json.toString() + "\n");
post.addHeader("content-type", "application/json");
post.setEntity(params);
httpClient.execute(post);
Thread.sleep(5000);
httpClient.execute(post);
but it does not work.
Even though I lose the previous connection and set up a new connection to send the second, the second execute function is always blocked.
Your question leaves a bunch of questions, but the basic point of it can be achieved by:
while(true){ //process executes infinitely. Replace with your own condition
Thread.sleep(5000); // wait five seconds
httpClient.execute(post); //execute your request
}
I tried your code and I got the exception :
java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one.
This exception is already logged in HttpClient 4.0.1 - how to release connection?
I was able to release the connection by consuming the response with the following code:
public void sendMultipleRequests() throws ClientProtocolException, IOException, InterruptedException {
HttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost("http://www.google.com");
HttpResponse response = httpClient.execute(post);
HttpEntity entity = response.getEntity();
EntityUtils.consume(entity);
Thread.sleep(5000);
response = httpClient.execute(post);
entity = response.getEntity();
EntityUtils.consume(entity);
}
Using DefaultHttpClient is synchronous which means that program is blocked waiting for the response. Instead of that you could use async-http-client library to perform asynchronous requests (you can download jar files from search.maven.org if you're not familiar with Maven). Sample code may look like:
import com.ning.http.client.*; //imports
try {
AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
while(true) {
asyncHttpClient
.preparePost("http://your.url/")
.addParameter("postVariableName", "postVariableValue")
.execute(); // just execute request and ignore response
System.out.println("Request sent");
Thread.sleep(5000);
}
} catch (Exception e) {
System.out.println("oops..." + e);
}

Application getting website response

net developer and dont know about android. could you please help me to fix this code
Exception: android.os.networkmainthreadException on
client.execute(get1)
try
{
HttpGet get1 = new HttpGet ("http://www.google.com/");
HttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(get1);
HttpEntity entity = response.getEntity();
String responseText = EntityUtils.toString(entity);
}
catch(Exception e )
{
urlview.setText( "hi bug"+ e.toString());
}
You are doing network operation on UI thread which in not allowed in android version >=3.0 So use AsyncTask

Categories