Apache httpclient: tutorial is broken - how to actually use this library? - java

I am using netbeans as an IDE to give you an indication of background.
I am playing around with the Apache httpclient library as in my current app I am having issues with the in built java HTTP connection.
I heard that the apache library was more powerful.
Anyway, the tutorial documentation that comes with the httpclient library on the apache site seems to be flawed:
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://localhost/");
HttpResponse response = httpclient.execute(httpget);
Net beans gives me issues with this code snippet (copied straight from the tutorial). Forget even the rudimentary URI of localhost, problems that arise with this are:
netbeans complains that HttpClient and DefaultHttpClient are incompatible types. The only way I can see around this is to cast with:
(HttpClient) new DefaultHttpClient();
Netbeans complains that the httpclient.execute() would throw an error because "httpget" here is simply a method and not a "HttpUriRequest".
How can a simple 3 line tutorial be so wrong and how would I actually successfully complete a request if there is so many flaws in this example?
I'm lost, can someone help. There seems to be several different ways, all not entirely what I'm looking for.
I want to be able to take a well-formed URL that I already have in the app in String, and then follow-all redirects. I'm not at all interested in the contents of the response, merely the cookies that it will drop.
Thanks,
Gregory

I suggest looking at your imports. I think NetBeans imported your HttpClient 3.x instead of 4.x. Try correcting your imports.

Have you tried using this code, they seem to use different mechanisms than you do. Taken from here. This is for the 3.X version though so it might be that you are using a different version.
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.httpclient.params.HttpMethodParams;
import java.io.*;
public class HttpClientTutorial {
private static String url = "http://www.apache.org/";
public static void main(String[] args) {
// Create an instance of HttpClient.
HttpClient client = new HttpClient();
// Create a method instance.
GetMethod method = new GetMethod(url);
// Provide custom retry handler is necessary
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler(3, false));
try {
// Execute the method.
int statusCode = client.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
System.err.println("Method failed: " + method.getStatusLine());
}
// Read the response body.
byte[] responseBody = method.getResponseBody();
// Deal with the response.
// Use caution: ensure correct character encoding and is not binary data
System.out.println(new String(responseBody));
} catch (HttpException e) {
System.err.println("Fatal protocol violation: " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
System.err.println("Fatal transport error: " + e.getMessage());
e.printStackTrace();
} finally {
// Release the connection.
method.releaseConnection();
}
}
}

When I used this (on Android) I implemented a CustomHttpClient, following the example here

Related

HTTP post request doesn't respond on production environment (war with tomcat server)

I have implemented a PerformHttpPostRequest function which is supposed to send a post request contains a JSON type body and get a JSON response via Apache HttpClient.
public static String PerformHttpPostRequest(String url, String requestBody) throws IOException {
CloseableHttpClient client = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
StringEntity entity = new StringEntity(requestBody);
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
CloseableHttpResponse response = client.execute(httpPost);
HttpEntity httpEntity = response.getEntity();
InputStream is = httpEntity.getContent();
return (new BufferedReader(new InputStreamReader(is, "UTF-8"))).readLine();
}
The problem is, the code works perfect on developing environment, but when running the war file with a tomcat server but the request is not executed.
I've tried adding several catch blocks such as IOException, Exception and the code doesn't get there.
I've added debug prints which demonstrated that the code stops responding at the client.execute(...) command.
The function is called inside a try block, and after executing the .execute(...) command the code does get to the finally block.
I've already searched for a similar problem and didn't find an answer.
Is it a known issue? Does anyone have any idea of what can cause that? Or how can I fix it?
Hi Talor nice to meet you,
Please try to use HttpURLConnection to solve this issue like so:
Java - sending HTTP parameters via POST method easily
Have a nice day.
el profesor
I have tried with RestTemplate.
RequestObject requestObject = new RequestObject();
requestObject.setKey("abcd");
requestObject.setEndpoint(serviceEndPoint);
RestTemplate restTemplate = new RestTemplate();
HttpEntity<RequestObject> requestBody = new HttpEntity<RequestObject>(
requestObject);
ResponseEntity<RequestObject> result = restTemplate.postForEntity(
serviceEndPoint, requestBody, RequestObject.class);
Its very simple and hassle free, hope it helps
Few things you can try out.
- Try to do ping/curl from that box where you are running tomcat.
- Try to have a test method which make a get request to a server which is always reachable. For ex google.com and print the status. That way you could be able to know that you code is actually working or not in server env.
Hope this helps. :)
If the code doesn't pass beyond client.execute(...) but it does execute the finally block in the calling code, then you can find out what caused the aborted execution by adding this catch block to the try block that contains the finally:
catch(Throwable x) {
x.printStackTrace();
}
Throwable is the superclass for all exception and error classes, so catching a Throwable will catch everything.

How to use Servlet together with Apache Solr service

I'm using Java EE technology for my web application. And I use Apache Solr for my search engine. AFAIK, after I config Solr successfully, Solr is running as a Restful service.
So, under my servlet, I try to call this service as another console application I do before. Here is a sample code is used to get json data from an url:
/** Get Data Fom URL Using GET Method */
public static String getResponseFromGetRequest(String url) {
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
/** after prepare for data. prepare for sending */
try {
/**
* HttpResponse is an interface just like HttpGet
* therefore we can't initialize them
*/
HttpResponse httpResponse = httpClient.execute(httpGet);
return parseHttpResponse(httpResponse);
} catch (ClientProtocolException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
return null;
}
But the package org.apache.http.impl.client.DefaultHttpClient is not available (under tomcat server at least). So, I think maybe there are some problems here. That we cannot call another service in servlet, right? If my guess is true, how can I fix this problem?
A brief code on using an API available in java to interact with solr(you don't need to know or care about servlets, httpclients, nothing).
HttpSolrServer server = new HttpSolrServer("your restful url goes here");
SolrQuery query = new SolrQuery();
QueryResponse response = server.query(query);
List<MyClass> beans = response.getBeans(MyClass.class);
server should probably be a spring bean, it's the java representation (proxy object) of your running solr server.
query is a query to run against the server, configure this to specify what you want from solr.
response is the answer to the request.
beans are objects which are straight from solr itself (as far as i remember, your solr fields get mapped to the java object's fields by field name, no restrictions at all).
note that server has a lot of ways to do simple operations without anything explicit, like server.addBean(myBean);
Here is how to get Solrj in maven:
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>4.5.1</version>
</dependency>
If you don't have maven:
http://mvnrepository.com/artifact/org.apache.solr/solr-solrj/4.10.3
click on "Download ( JAR )".

What's the difference between using SoapUI and java code?

I'm using soap to request some information from server.
so, In order to test whether my soap way is the correct way or not, I tested soapUI Pro 4.6.3 program and java code.
when I use soapUI program , I got the response of my request from server. But, when I use java code I couldn't get response of my request from server..
I can see the error code 500. As I know, 500 Error code is Internal Error. so Isn't this problem of server?
I want to know what's the difference between them.
My java code is below.. and The XML code is the same what I use by SoapUI Program and what I use java code.
HttpClient client = new HttpClient();
PostMethod method = new PostMethod("My URL");
int status = 0;
String result = "";
try {
method.setRequestBody(MySoapXML);
method.getParams().setParameter("http.socket.timeout", new Integer(5000));
method.getParams().setParameter("http.protocol.content-charset", "UTF-8");
method.getParams().setParameter("SOAPAction", "My Soap Action URL");
method.getParams().setParameter("Content-Type", MySoapXML.length());
status = client.executeMethod(method);
BufferedReader br = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream()));
String readLine;
while ((readLine=br.readLine())!=null) {
System.out.println(readLine);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
method.releaseConnection();
}
and I already did URLConnection Class, and HttpClient Class.. but The result was the same..
If you know the way to solve this problem or have the same experience as me. please let me know how to solve this problem.. thank you for reading ^_^
Soap - UI will parse poorly defined webservices(for eg. Not Well Defined WSDL). From my experience working with SoapUI is not a proof that your webservice is well-defined.

How to make all network traffic go via a proxy?

I have an app that makes http requests to a remote server. I do this with the following code:
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("myURL");
try {
ArrayList<BasicNameValuePair> postVariables = new ArrayList<BasicNameValuePair>(2);
postVariables.add(new BasicNameValuePair("key","value"));
httpPost.setEntity(new UrlEncodedFormEntity(postVariables));
HttpResponse response = httpClient.execute(httpPost);
String responseString = EntityUtils.toString(response.getEntity());
if (responseString.contains("\"success\":true")){
//this means the request succeeded
} else {
//failed
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
This goes really well, but one of our customers has set up an APN that requires requests to go via a certain proxy server. If I add the following to the request this works, the request gets rerouted via the proxy to the server:
HttpHost httpHost = new HttpHost("proxyURL",8080);
httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, httpHost);
So far so good, however, I use a library that makes some http requests as well. The library's code is not accesible for me, so I can't add those two lines to the code. I contacted the creators of that library, and they told me it should be possible to set up the android environment so that all requests will automatically go through the proxy. Is there something like that? I didn't find anything on google.
I'm basically looking for a way to set the above two lines as a standard for all http requests. Please note that the APN does not set the proxy as a default for the entire phone, so apps will have to do this manually (and yes that means the majority of the apps don't work on that customer's phone).
It's been a year or two since I've needed to use it, but if I remember correctly, you can use the System.setProperty(String, String) in order to set an environment-wide setting for your application to route all HTTP traffic through a proxy. The properties that you should need to set are "http.proxyHost" and "http.proxyPort" and then use your HttpClient normally without specifying a proxy because the VM will handle routing requests.
Docs for more information about what I'm talking about can be found here: ProxySelector (just so you know what keys to use) and here for documentation about the actual System.setProperty(String, String) function
If that doesn't work for you, let me know and I'll try to dig out my old code that set a system-level proxy. BTW, it's really only "system-level" since each app runs in it's own Dalvik so you won't impact other app's network communications.

How can I forcefully cache all my HTTP responses?

I'm using the DefaultHTTPClient to make some HTTP GET requests. I'd like to forcefully cache all the HTTP responses for a week. After going through the docs and some SO answers, I've done this:
I installed an HttpResponseCache via the onCreate method of my main activity.
try {
File httpCacheDir = new File(getApplicationContext().getCacheDir(), "http");
long httpCacheSize = 10 * 1024 * 1024; // 10 MiB
HttpResponseCache.install(httpCacheDir, httpCacheSize);
} catch (IOException e) {
Log.i("dd", "HTTP response cache installation failed:" + e);
}
I added a custom HttpResponseInterceptor for my HTTP client, but I still don't get a cache hit. Here's my response interceptor that decompresses GZIPped content, strips caching headers and adds a custom one:
class Decompressor implements HttpResponseInterceptor {
public void process(HttpResponse hreResponse, HttpContext hctContext) throws HttpException, IOException {
hreResponse.removeHeaders("Expires");
hreResponse.removeHeaders("Pragma");
hreResponse.removeHeaders("Cache-Control");
hreResponse.addHeader("Cache-Control", "max-age=604800");
HttpEntity entity = hreResponse.getEntity();
if (entity != null) {
Header ceheader = entity.getContentEncoding();
if (ceheader != null) {
HeaderElement[] codecs = ceheader.getElements();
for (int i = 0; i < codecs.length; i++) {
if (codecs[i].getName().equalsIgnoreCase("gzip")) {
hreResponse.setEntity(new HttpEntityWrapper(entity) {
#Override
public InputStream getContent() throws IOException, IllegalStateException {
return new GZIPInputStream(wrappedEntity.getContent());
}
#Override
public long getContentLength() {
return -1;
}
});
return;
}
}
}
}
}
}
Here's how I make my request:
String strResponse = null;
HttpGet htpGet = new HttpGet(strUrl);
htpGet.addHeader("Accept-Encoding", "gzip");
htpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20100101 Firefox/15.0.1");
DefaultHttpClient dhcClient = new DefaultHttpClient();
dhcClient.addResponseInterceptor(new Decompressor(), 0);
HttpResponse resResponse = dhcClient.execute(htpGet);
Log.d("helpers.network", String.format("Cache hit count: %d", HttpResponseCache.getInstalled().getHitCount()));
strResponse = EntityUtils.toString(resResponse.getEntity());
return strResponse;
I can't seem to pinpoint what I'm doing wrong. Would any of you know?
Not sure if this answers your question, but instead of relying on an HTTP server interpreting your cache control headers, have you thought about simply adding a client-side cache using Android's own cache directories?
What we did in ignition is simply write server responses to disk as byte streams, thus having full control over caching (and expiring caches.)
There's a sample app here, but it would require you to use the library's HTTP API (which, however, is merely a thin wrapper around HttpClient.) Or simply look at how the cache works and go from there.
I failed miserably with this. According to the Android documentation, it specifically says about the HttpResponseCache — "Caches HTTP and HTTPS responses to the filesystem so they may be reused, saving time and bandwidth. This class supports HttpURLConnection and HttpsURLConnection; there is no platform-provided cache for DefaultHttpClient or AndroidHttpClient."
So that was out.
Now Apache's HTTP client has a CachingHttpClient and this new version of HTTP client has been back ported to Android through this project. Of course, I could use this.
I didn't want to use the hackish version of the Apache HTTP Client libraries so one idea was to cannibalise the caching related bits from the HTTP Client and reoll my own but it was too much work.
I even considered moving to the recommended HttpURLConnection class as recommended but I've run into other issues. There doesn't seem to be good cookie-persistence implementation for that class.
Anyway, I skipped everything and though. I'm reducing the loading time by caching, why not got go a step further and since I was using jSoup to scrape records from the page and create an ArrayList of a custom structure, I might as well serialize the whole ArrayList by implementing the Serializable method on my structure. Now I don't have to wait for the page request, not do I have to wait for the jSoup parsing slowness. Win.

Categories

Resources