Move CloseableHttpResponse inside nested try with resources - java

I have the following code using try with resources with CloseableHttpResponse
CloseableHttpResponse response = null;
try (CloseableHttpClient httpClient = HttpClients.custom().build()){
//code...
response = httpClient.execute(target, post);
String responseText = EntityUtils.toString(response.getEntity());
} catch (Exception e) {
logger.error("Failed sending request", e);
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
logger.error("Failed releasing response", e);
}
}
}
Can I safely replace with nested try with resources:
try (CloseableHttpClient httpClient = HttpClients.custom().build()){
URIBuilder uriBuilder = new URIBuilder(url);
HttpHost target = new HttpHost(uriBuilder.getHost(), uriBuilder.getPort(), uriBuilder.getScheme());
HttpPost post = new HttpPost(uriBuilder.build());
try (CloseableHttpResponse response = httpClient.execute(target, post)) {
String responseText = EntityUtils.toString(response.getEntity());
}
} catch (Exception e) {
logger.error("Failed sending request", e);
}
Or is it better to use a single try with resources block:
try (CloseableHttpClient httpClient = HttpClients.custom().build();
CloseableHttpResponse response = getResponse(httpClient, url)) {
Sometime refactoring to single block is problematic, so I wanted to know the a nested/additional block is a valid solution.

HttpClient never returns a null HttpResponse object. The first construct is simply not useful. Both the second and the third constructs are perfectly valid

Related

How can I set default headers for all requests?

I have a lot of requests. How can I set default headers for all requests? Please, give me examples
Now My code look like this:
HttpPost request = new HttpPost(url);
StringEntity params = null;
try {
params = new StringEntity(o.writeValueAsString(auth));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
request.addHeader("content-type", "application/json");
request.setEntity(params);
try {
client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(request);
} catch (IOException e) {
e.printStackTrace();
}
So I have many requests like this
Since you're using the HttpClientBuilder, why not try using its setDefaultHeaders() method?
HttpClientBuilder client = HttpClientBuilder.create();
Header header = new BasicHeader(HttpHeaders.CONTENT_TYPE, "application/json");
client.setDefaultHeaders(header);
HttpPost request = new HttpPost(url);
StringEntity params = null;
try {
params = new StringEntity(o.writeValueAsString(auth));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
request.setEntity(params);
try {
client.build();
HttpResponse response = client.execute(request);
} catch (IOException e) {
e.printStackTrace();
}
Hope that helps!
The most awkward are the try-catches. Best would be to throw them to the caller, and rely on the logging there.
However a single try-catch is possible too. There the style declaration of var + try{ assigning to var } processing var should better be try { declaration + assigning + processing }
Then one already gets shorter, more readable code.
HttpPost request = new HttpPost(url);
request.addHeader("content-type", "application/json");
try {
request.setEntity(new StringEntity(o.writeValueAsString(auth)));
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(request);
} catch (IOException e) {
Logger.log(Level.SEVERE, e);
}
The HttpClient part is still a bit dubious, and could be reduced without declaration.
Alternatives exist like using annotations, Spring and some more declarative techniques. But this is short enough.

NetworkOnMainThreadException sometimes thrown

I try to get response from POST request. The problem is that sometimes I get NetworkOnMainThreadException although I'm using AsyncTask for the network communication. That means that sometimes I get the response successfully, and sometimes I get this exception.
Here is my HTTP POST request AsyncTask:
static class HTTPPostRequest extends AsyncTask<PostRequestParams, Void, AsyncResponse> {
#Override
protected AsyncResponse doInBackground(PostRequestParams... params) {
AsyncResponse retVal = new AsyncResponse();
HttpClient client = getHttpClient();
UrlEncodedFormEntity formEntity = null;
HttpPost request = new HttpPost();
try {
request.setURI(new URI(params[0].URL));
formEntity = new UrlEncodedFormEntity(params[0].params);
request.setEntity(formEntity);
HttpResponse response = client.execute(request);
retVal.setOutput(response);
} catch (ClientProtocolException e) {
retVal.setException(e);
} catch (IOException e) {
retVal.setException(e);
} catch (URISyntaxException e) {
retVal.setException(e);
}
return retVal;
}
}
And the code that actually call it:
AsyncResponse response = new AsyncResponse();
PostRequestParams postParams = new PostRequestParams();
postParams.URL = URL + "login.php";
postParams.params.add(new BasicNameValuePair("username", username));
postParams.params.add(new BasicNameValuePair("password", password));
try {
response = new HTTPPostRequest().execute(postParams).get();
if (response.getException() != null) {
return "Error";
}
HttpResponse httpResponse = (HttpResponse) response.getOutput();
if (httpResponse.getStatusLine().getStatusCode() != 200) {
return "Error " + httpResponse.getStatusLine().getStatusCode();
}
return (String) formatResponse(new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent())));
} catch (InterruptedException | ExecutionException | IllegalStateException | IOException e) {
response.setException(e);
return null;
}
You should move the code that handles the InputStream, like:
return (String) formatResponse(new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent())));
to your AsyncTask as well. Handling InputStreams is nothing that you want to do in your UI Thread.

Android Unable to Retrieve JSON response [SC_406]

I have the code which basically retrieving a list of search result based on given keyword from TMDB (API ver.3, new API).
public String getPersonSearchResult(String keywords){
String query = URLEncoder.encode(keywords);
String TMDB_API_URL = "http://api.themoviedb.org/3/search/person?";
String TMDB_LIMIT_LIST = "&page=1";
String TMDB_QUERY = "&query=" + query;
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response;
String responseString = null;
try
{
// ATTEMPT HTTP REQUEST
String fullUrl = TMDB_API_URL + TMDB_API_KEY + TMDB_QUERY + TMDB_LIMIT_LIST;
Log.w(APP_TAG, "TRYING [" + fullUrl + "]");
response = httpclient.execute(new HttpGet(fullUrl));
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() == HttpStatus.SC_OK)
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
responseString = out.toString();
}else{
// FAILED REQUEST - CLOSE THE CONNECTION
response.getEntity().getContent().close();
throw new IOException(statusLine.getReasonPhrase());
}
}catch(Exception e){
Log.w(APP_TAG, e.getLocalizedMessage());
Log.w(APP_TAG, "FAILED TO RETRIEVE JSON DATA");
}
return responseString;
}
The problem is that i always get 406 Status Code (Not Acceptable). When i tried to run the URL myself
http://api.themoviedb.org/3/search/person?api_key=<MY_API_KEY_HERE>&query=jennifer&page=1
It displays the JSON result correctly.
I am not sure why is this happening. Similar function is used to retrieve JSON value from other source and and it works perfectly.
this is their API docs regarding search: http://docs.themoviedb.apiary.io/#search
Can anyone points me to the right direction? Any help is appreciated.
I figure it out, by adding this:
HttpGet getObj = new HttpGet(fullUrl);
getObj.addHeader("Accept", "application/json");
Perhaps this is API specific requirement. Not sure though...
One way to do it
Try using builder.scheme
URIBuilder builder = new URIBuilder();
builder.setScheme("http").setHost("api.themoviedb.org").setPath("/3/search/person")
.setParameter("api_key", YOURAPIKEY)
.setParameter("page", 1)
.setParameter("query", query)
URI uri = builder.build();
HttpGet httpget = new HttpGet(uri);
.....
response = httpclient.execute(new HttpGet(httpget ));
I think its nothing to do with your code.. your code is perfect. The only problem might be with the API request method. Maybe they require some specific headers to be requested for in the request. Give a try with requesting headers like "("Accept", "application/json")" It might work..
try this
String ret = null; try {
response = httpClient.execute(httpGet);
} catch (Exception e) {
e.printStackTrace();
}
try {
ret = EntityUtils.toString(response.getEntity());
} catch (IOException e) {
Log.e("HttpRequest", "" + e.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
return ret;

Java HTTP Request Stuck

I've never really used http requests in Java, I'm trying to make a request that would basically recreate this http://supersecretserver.net:8080/http://whateverwebsite.com
This server takes whatever website and returns only the text of the page in the body of the response.
The code is as follows:
public String getText(String webPage) throws ParseException, IOException{
HttpResponse response = null;
try {
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet();
request.setURI(new URI("http://supersecretserver.net:8080/" + "http://www.androidhive.info/2012/01/android-text-to-speech-tutorial/"));
response = client.execute(request);
} catch (URISyntaxException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String responseBody = "No text found on webpage.";
int responseCode = response.getStatusLine().getStatusCode();
switch(responseCode) {
case 200:
HttpEntity entity = response.getEntity();
if(entity != null) {
responseBody = EntityUtils.toString(entity);
}
}
System.out.println("Returning Response..");
System.out.println(responseBody);
return responseBody;
}
It seems to get stuck on
response = client.execute(request);
I'm not sure what the problems is, any insight would be helpful.
Seems likely that your HttpClient is not timing out, you can set a timeout value by following this example (from http://www.jayway.com/2009/03/17/configuring-timeout-with-apache-httpclient-40/)
You just to have to consider a timeout value that makes sense for you.
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpParams params = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, connectionTimeoutMillis);
HttpConnectionParams.setSoTimeout(httpParams, socketTimeoutMillis);
Also as your HttpClient is not connecting (since it's getting stuck) you should also take into consideration why is that happening (maybe you need to configure a proxy?)

How to send simple http post request with post parameters in java

I need a simple code example of sending http post request with post parameters that I get from form inputs.
I have found Apache HTTPClient, it has very reach API and lots of sophisticated examples, but I couldn't find a simple example of sending http post request with input parameters and getting text response.
Update: I'm interested in Apache HTTPClient v.4.x, as 3.x is deprecated.
Here's the sample code for Http POST, using Apache HTTPClient API.
import java.io.InputStream;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
public class PostExample {
public static void main(String[] args){
String url = "http://www.google.com";
InputStream in = null;
try {
HttpClient client = new HttpClient();
PostMethod method = new PostMethod(url);
//Add any parameter if u want to send it with Post req.
method.addParameter("p", "apple");
int statusCode = client.executeMethod(method);
if (statusCode != -1) {
in = method.getResponseBodyAsStream();
}
System.out.println(in);
} catch (Exception e) {
e.printStackTrace();
}
}
}
I pulled this code from an Android project by Andrew Gertig that I have used in my application. It allows you to do an HTTPost. If I had time, I would create an POJO example, but hopefully, you can dissect the code and find what you need.
Arshak
https://github.com/AndrewGertig/RubyDroid/blob/master/src/com/gertig/rubydroid/AddEventView.java
private void postEvents()
{
DefaultHttpClient client = new DefaultHttpClient();
/** FOR LOCAL DEV HttpPost post = new HttpPost("http://192.168.0.186:3000/events"); //works with and without "/create" on the end */
HttpPost post = new HttpPost("http://cold-leaf-59.heroku.com/myevents");
JSONObject holder = new JSONObject();
JSONObject eventObj = new JSONObject();
Double budgetVal = 99.9;
budgetVal = Double.parseDouble(eventBudgetView.getText().toString());
try {
eventObj.put("budget", budgetVal);
eventObj.put("name", eventNameView.getText().toString());
holder.put("myevent", eventObj);
Log.e("Event JSON", "Event JSON = "+ holder.toString());
StringEntity se = new StringEntity(holder.toString());
post.setEntity(se);
post.setHeader("Content-Type","application/json");
} catch (UnsupportedEncodingException e) {
Log.e("Error",""+e);
e.printStackTrace();
} catch (JSONException js) {
js.printStackTrace();
}
HttpResponse response = null;
try {
response = client.execute(post);
} catch (ClientProtocolException e) {
e.printStackTrace();
Log.e("ClientProtocol",""+e);
} catch (IOException e) {
e.printStackTrace();
Log.e("IO",""+e);
}
HttpEntity entity = response.getEntity();
if (entity != null) {
try {
entity.consumeContent();
} catch (IOException e) {
Log.e("IO E",""+e);
e.printStackTrace();
}
}
Toast.makeText(this, "Your post was successfully uploaded", Toast.LENGTH_LONG).show();
}
HTTP POST request example using Apache HttpClient v.4.x
HttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("param1", param1Value, ContentType.TEXT_PLAIN);
builder.addTextBody("param2", param2Value, ContentType.TEXT_PLAIN);
HttpEntity multipart = builder.build();
httpPost.setEntity(multipart);
HttpResponse response = httpClient.execute(httpMethod);
http://httpunit.sourceforge.net/doc/cookbook.html
use PostMethodWebRequest and setParameter method
shows a very simple exapmle where you do post from Html page, servlet processes it and sends a text response..
http://java.sun.com/developer/onlineTraining/Programming/BasicJava1/servlet.html

Categories

Resources