I am trying to build an http POST using the examples of Apache Components (4.3) - http://hc.apache.org/httpcomponents-client-4.3.x/tutorial/html/fluent.html. Unfortunately, I receive an error that I have not been able to find out how to solve.
I have used the former HttpClient before - so this is my first go with components.
Here is a snippet of the code:
String address = "http://1.1.1.1/services/postPositions.php";
String response = Request.Post(address)
.bodyString("Important stuff", ContentType.DEFAULT_TEXT)
.execute().returnContent().asString();
System.out.println(response);
and when I run that code I get an exception:
Exception in thread "main" java.lang.IllegalStateException: POST request cannot enclose an entity
at org.apache.http.client.fluent.Request.body(Request.java:299)
at org.apache.http.client.fluent.Request.bodyString(Request.java:331)
at PostJson.main(PostJson.java:143)
I have tried to build a form element as well and use the bodyForm() method - but I get the same error.
I had the same issue, the fix is to use Apache Client 4.3.1 which works.
It seems that the Request was changed:
in 4.3.1 they use public HttpRequestBase
in the latest release they use the package protected InternalHttpRequest
For the sake of completeness I am going to post the way to do it without using the Fluent API. Even if it doesn't answer the question "How to use fluent of Apache Components", I think it is worth to point out that the below, simplest case, solution works for versions which have the bug:
public void createAndExecuteRequest() throws ClientProtocolException, IOException {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost(host);
httppost.setEntity(new StringEntity("Payload goes here"));
try (CloseableHttpResponse response = httpclient.execute(httppost)) {
// do something with response
}
}
In my case, downgrading was not an option, so this was the best solution.
I did some digging and can't see how it can work (you might have found a bug).
The error stems from line 300 in Request in the latest trunk version. There a check is done to see if this.request instanceof HttpEntityEnclosingRequest but that is never true because this.request is always set to an instance of InternalHttpRequest in the Request constructor at line 130, and InternalHttpRequest does not implement org.apache.http.HttpEntityEnclosingRequest`.
Related
We are making use of this end point - https://www.googleapis.com/oauth2/v4/token
to get the access token.
We make use of apace HTTP classes to make a POST request to this end point in this way -
HttpPost httpPost = new HttpPost(GET_ACCESS_TOKEN_API);
StringBuilder blr = new StringBuilder().append(CLIENT_ID).append("=")
.append((String) accountCredentials.get(CLIENT_ID)).append("&")
.append(CLIENT_SECRET).append("=")
.append((String) accountCredentials.get(CLIENT_SECRET))
.append("&").append(REFRESH_TOKEN).append("=")
.append((String) accountCredentials.get(REFRESH_TOKEN))
.append("&grant_type=refresh_token")
.append("&redirect_uri=urn:ietf:wg:oauth:2.0:oob");
// The message we are going to post
StringEntity requestBody = new StringEntity(blr.toString());
// the default content-type sent to the server is
// application/x-www-form-urlencoded.
requestBody.setContentType("application/x-www-form-urlencoded");
httpPost.setEntity(requestBody);
// Make the request
HttpResponse response = HttpUtils.getHttpClient().execute(httpPost);
There has been a recent intimation from google to migrate from out-of-band as they have plans to deprecate this.
We make use of it this way as you can see in the code above -append("&redirect_uri=urn:ietf:wg:oauth:2.0:oob");
GET_ACCESS_TOKEN_API is https://www.googleapis.com/oauth2/v4/token.
I saw some posts mentioning that we have to replace this redirect_uri to localhost.
Can someone explain exactly how this works and what change needs to be done to migrate this successfully ? I tried searching through the documentation to see if there any sample examples but couldn't find anything that matches our use case.
I am referring to this site -
https://developers.google.com/api-client-library/java/google-oauth-java-client/support
I tried to browse through samples, guides, but it mostly talks about different API's. I didn't find the github links that much useful.
Any help would be much appreciated.
I need my Java application to make a PATCH request to a web server using SSL.
I have tried the following:
public String patchForm(FormDataMultiPart f, Map<String,String> headers) {
Entity<FormDataMultiPart> entity = Entity.entity(f, f.getMediaType());
webTarget.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true);
Builder request = webTarget.request();
if (headers != null){
for (String key : headers.keySet()){
request = request.header(key, headers.get(key));
}
}
Response result = request.method("PATCH", entity);
return result.readEntity(String.class);
}
Where Entity is javax.ws.rs.client.Entity and webTarget is a javax.ws.rs.client.WebTarget.
However, when I make the request, the server interprets it as a POST request and gives me the wrong response.
What could be the cause of the problem? Is there any way to fix it?
Thank you in advance.
For a Patch you need to set which url you are hitting to be secure.
For example
Your webTarget will have
webTarget.path("https://secureUrlWichWillForceSsl.com");
if it starts with http:// it will not be secure and no SSL.
After a lot of trial and error, doing and undoing, adding _HttpMethod=PATCH to the query string and then removing it because it turned out not to be necessary, especially adding a missing break to a switch close which was causing the patchForm function to not be called at all (yes, that was a stupid oversight which cost me hours of work), and then fixing the errors which kept cropping up, I have finally arrived at something which works.
The code which finally worked was the following:
public String patchForm(FormDataMultiPart f, Map<String,String> headers) {
Entity<FormDataMultiPart> entity = Entity.entity(f, f.getMediaType());
webTarget.register(MultiPartFeature.class);
webTarget.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true);
Builder request = webTarget.request();
headers.put("X-HTTP-Method-Override", "PATCH");
if (headers != null){
for (String key : headers.keySet()){
request = request.header(key, headers.get(key));
}
}
Response result = request.patch(entity);
return result.readEntity(String.class);
}
Note that the Builder class has a built-in patch method. I was using an old library which did not have it. And yet, the method workaround is still necessary because otherwise I get an exception since the PATCH method is non-standard.
Also note that, when submitting multipart forms, it is important to register the Multipart feature. I have read that it is possible to register it either on the client by overriding the configureClient method (when writing a custom client) or on the web target. Doing it on the web target suited my needs better, but you can do it in whatever way works best for you.
--Update--
Apologies for those who helped me, it turns out this is just a problem with Eclipse's debugger. After suspecting that it was leading me wrong, I placed down a couple of System.out.println to watch the variables, and according to them they ARE being changed, and that the debugger was just showing me old information for whatever reason. No clue why that's happening, but the important thing is that the code does apparently actually work.
I'm working on a method to share with twitter for an Android application, and I'm having errors when setting up the HttpURLConnection. I create the connection object as per usual, using the openconnection function of a url then casting it to a HttpURLConnection, and when I subsequently run SetRequestMethod("POST") on the connection, it does absolutely nothing. When I run the code in the debugger line by line, as I go through that line the request method just remains as the default ("GET"). Anyone have any idea as to why this may be happening? I'm getting the same problem with setDoOutput(true) also not changing anything. However, adding a request property does still work. I've been searching around and haven't been able to find anything on this problem, not even another person reporting these problems.
I am not sur whether using HttpURLConnection is the best here.
Did you try the following way?
// Building the POST request
final BasicNameValuePair message = new BasicNameValuePair("yourField", "yourContent");
final List<NameValuePair> list = new ArrayList<NameValuePair>(1);
list.add(message);
final HttpPost httppost = createHttpPost(UrlEncodedFormEntity(list));
// Building the HTTP client
final HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, YOUR_CHOSEN_CONN_TIMEOUT);
HttpConnectionParams.setSoTimeout (httpParameters, YOUR_CHOSEN_SO_TIMEOUT);
final HttpClient httpClient = new DefaultHttpClient(httpParameters);
// Execution of the POST request
final HttpResponse response = httpClient.execute(httppost);
This is the way I usually do, with no problems.
[EDIT: 04-25-2014] Apache's HttpClient was the best approach for Froyo and former versions. Now, according to this article from Android Developers Blog (written after this Q&A), it is better to use URLConnection.
I'm currently using HttpURLConnection to stream live content such as a radio broadcast. However it seems that using HttpClient is a better option since it's well supported by Android and it's a better implementation. Also, there seems to be a logic for automatic reconnection from a lost connection.
My problem is that I can't get this to work. It's always hanging when calling httpclient.execute(...).
What am I doing wrong?
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://208.76.243.123:7100");
HttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
Run it in debugger and when it hangs, call break. Then find the thread that is executing your code and see in stack trace where exactly it blocked. You will see if it blocked on IO or something else is happening. With that data it will be easier to identify the problem.
Are you sure your server understands the HTTP protocol? (I assume yes, it sounds like you had a different client working). It is possible the execute method is blocking because it has not seen a valid Response header yet.
You probably want entity.getContent() which will return a handle to a stream. See this question.
I'm using Apache Httpclient for Ajax-calls on a website. In some cases requests to external webservice fail, often with:
I/O exception (java.net.ConnectException) caught when processing request: Connection timed out: connect.
In that case, more often than not, I want to skip retrying the request (something that Httpclient seems to do automatically) .
However, I can't find any method, param, etc. to skip retrying.
anyone?
Thanks Geert-Jan
From httpclient 4.3 use HttpClientBuilder
HttpClientBuilder.create().disableAutomaticRetries().build();
client.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(0, false));
That would do it.
OK. There is issue in the Documentation. Also there has been change in API and methods.
So if you want to use DefaultHttpRequestRetryHandler , here are the ways to do that,
DefaultHttpClient httpClient = new DefaultHttpClient();
DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(0, false);
httpClient.setHttpRequestRetryHandler(retryHandler);
or
HttpClient httpClient = new DefaultHttpClient();
DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(0, false);
((AbstractHttpClient)httpClient).setHttpRequestRetryHandler(retryHandler);
In first one, we use concrete DefaultHttpClient (which is a subclass of AbstractHttpClient and so has the setHttpRequestRetryHandler() method.)
In second one, we are programming to the HttpClient interface (which sadly doesn't expose that method, and this is weird !! ehh), so we have to do that nasty cast.
There's a description in the HttpClient tutorial.
client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler());
See the tutorial for more information, for instance this may be harmful if the request has side effects (i.e. is not idempotent).
The cast to AbstractHttpClient is not necessary. Another way is to use a strategy with AutoRetryHttpClient with DefaultServiceUnavailableRetryStrategy set to 0 for retry parameter. A better way would be to extend the AbstractHttpClient or implement HttpClient to expose the desired method.