PostMethod setRequestBody(String) deprecated - why? - java

I am using Apache Commons HttpClient PostMethod 3.1.
In the PostMethod class there are also three methods for setting POST method's request body:
setRequestBody(InputStream body)
setRequestBody(String body)
setRequestBody(NameValuePair[] parametersBody);
NameValuePair API
First two methods are deprecated. Does anybody knows why? Because if I want to put an XML to request body, NameValuePair does not help me.
Does anybody knows an workaround or a solution?

The javadoc says:
Deprecated. use setRequestEntity(RequestEntity)
RequestEntity has a lot of implementors, namely:
ByteArrayRequestEntity, FileRequestEntity, InputStreamRequestEntity, MultipartRequestEntity, StringRequestEntity
Use the one that suits you:
if your xml is in a String, use the StringRequestEntity
if it is in a file, use the FileRequestEntity
and so on.

Yes, so for example,
post.setRequestEntity( new StringRequestEntity( xml ) );
instead of
post.setRequestBody( xml );

Related

Java - RestTemplate 405 Method Not Allowed Although Postman Call Works

I am experiencing a weird issue when working with RestTemplate. I'm using a certain REST API and there I want to update something using PUT.
Thus, in e.g. Postman I am sending this request:
PUT http://fake/foobar/c/123 with a certain body
This update via Postman is successful. If I now execute the same call in Java via a RestTemplate, I am getting a 405 Method Not Allowed:
HttpHeaders headers = createHeader();
HttpEntity<Offer> httpEntity = new HttpEntity<>(bodyEntity, headers);
String url = "http://fake/foobar/c/123"; //Created dynamically, but here pasted for sake of simplicity
RestTemplate restTemplate = new RestTemplate(...);
ResponseEntity<OfferResponse> response = restTemplate.exchange(url, HttpMethod.PUT, httpEntity, OfferResponse.class);
...
I compared the URL again and again. If I copy the URL logged in the console and copy it to Postman, I can do the update successfully. I also compared the headers and everything. Everything is equal to how it is done via Postman.
Is there any potential other reason for such a behavior (another reason than I am too stupid comparing the headers etc. and missing something)? Other PUT, POST calls etc. against this API are working fine, otherwise I would have assumed that there is a general problem with my usage of RestTemplate
Code 405 Method Not Allowed means the HTTP verb (GET, POST, PUT, etc.) you use against this end-point is known but not accepted by the API.
If you can't post the details of your API as #Dinesh Singh Shekhawat suggested, I will first try to use Postman Code feature and get an automatically generated code for Java (OkHTTP or UniRest) of the request. You can find this option on the right part below the Send button. Copy this code and try to perform the request.
Then compare this request with yours.
You can always use HttpPut instead of RestTemplate if it's not a requirement:
HttpClient client = HttpClientBuilder.create().build();
String url = "http://fake/foobar/c/123";
HttpHeaders headers = createHeader();
HttpEntity<Offer> httpEntity = new HttpEntity<>(bodyEntity, headers);
HttpPut httpPut = new HttpPut(url);
httpPut.setEntity(httpEntity);
HttpResponse response = client.execute(httpPut);
I was facing the same problem. Later I printed the request and URL in the logs.
I found that I was using a wrong endpoint.
Can you please try to print the URL and the request in the logs and check if those are expected and correct?
Just in case it helps someone else: I was encountering the same issue and for me it was just the issue of a trailing slash / on the URL. In insomnia (similar to postman) I had a trailing slash, in code I didn't. When I added the slash to my code everything worked.
failure: http://localhost:8080/api/files
success: http://localhost:8080/api/files/
Of course it could also be the other way around, so just double check the actual api definition.

How to use fluent of Apache Components

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`.

Post XML in Java and Get the response code

I need to send XML data to a URL. The XML data is contained in a stringbuffer.
I need to post it and get the response code.
Can anyone tell me how to do it?
I have a piece of code, but eclipse says its deprecated
PostMethod postMethod = new PostMethod(URL);
InputStream stream = new StringBufferInputStream(command);
postMethod.setRequestBody(stream);
Javadoc says to use setRequestEntity(RequestEntity) instead.

Wrapper class for HttpGet / Post in Java?

Sorry, I'm quite new to Java.
I've stumbled across HttpGet and HttpPost which seem to be perfect for my needs, but a little long winded. I have written a rather bad wrapper class, but does anyone know of where to get a better one?
Ideally, I'd be able to do
String response = fetchContent("http://url/", postdata);
where postdata is optional.
Thanks!
HttpClient sounds like what you want. You certainly can't do stuff like the above in one line, but it's a fully-fledged HTTP library that wraps up Get/Post requests (and the rest).
I would consider using the HttpClient library. From their documentation, you can generate a POST like this:
PostMethod post = new PostMethod("http://jakarata.apache.org/");
NameValuePair[] data = {
new NameValuePair("user", "joe"),
new NameValuePair("password", "bloggs")
};
post.setRequestBody(data);
// execute method and handle any error responses.
...
InputStream in = post.getResponseBodyAsStream();
// handle response.
There are a number of advanced options for configuring the client should you eventually required those.

Apache Commons HttpClient PostMethod support?

I am curios about how one can set the request properties for a PostMethod in Apache Commons HttpClient?
I am refactoring some code written using HttpURLConnection class to post which looks like the following:
conn1.setRequestProperty(
"Content-Type", "multipart/related; type=\"application/xml\"; boundary="
+ boundary);
conn1.setRequestProperty("Authorization", auth);
... ...
To use:
PostMethod method = new PostMethod(_Server);
method.setRequestBody(...); or
method.setRequestHeader(...);
But i am not sure if / how this will map to what i want to do with the original URL class... can anyone help clarify how to set request properties with PostMethod class?
Thanks a lot!
-alex
Those are both request headers, so you would need to call setRequestHeader() to establish those values on the connection. HttpClient also supports handling basic authentication so the "Authorization" header can be refactored out, depending on how deep your changes go.

Categories