How to make a PUT request with Apache Olingo? - java

I am trying to transfer an entity via a HTTP PUT request using following code.
public ClientEntity createEntity(URI absoluteUri,
ClientEntity ce) {
ODataEntityCreateRequest<ClientEntity> request = client
.getCUDRequestFactory().getEntityCreateRequest(absoluteUri, ce);
request.setAccept("application/json;odata.metadata=minimal");
ODataEntityCreateResponse<ClientEntity> response = request.execute();
return response.getBody();
}
The function getEntityCreateRequest, however, only creates a POST request and allows (as far as I know) no alteration of the used HttpMethod.
Unfortunately, ODataEntityUpdateRequest is also not an option, because this request only allows the HttpMethod PATCH or REPLACE.
Within the documentation I have found a function setMethod(HttpMethod method), but this method is only available for the server not the client implementation (https://olingo.apache.org/javadoc/odata4/org/apache/olingo/server/api/ODataRequest.html).
Further I discovered setUseXHTTPMethod(boolean value), which tunnels PUT, MERGE, PATCH, DELETE via POST. I checked my client's configuration to make sure, that isUseXHTTPMethod is false, which it is. (Reference to functions: https://olingo.apache.org/javadoc/odata4/org/apache/olingo/client/api/Configuration.html)
Hence I am wondering how to make a PUT request with Apache Olingo?
Thank you very much for your input.

ODataEntityUpdateRequest with UpdateType.REPLACE should be equivalent to a PUT method.
Notice the source code, line 31.

Implement the updateEntity method.

Related

HTTP Error 411 for startOptimization request of routeoptimization api

I'm trying to send a startOptimization request to https://api.myptv.com/routeoptimization. I generated my java client as described in the tutorial: https://developer.myptv.com/Tutorials/General/clientGeneration.htm
Creating a plan works but when I want to optimize it I get the following error:
HTTP Error 411. The request must be chunked or have a content length.
I noticed that this error is also returned when I send a startEvaluation request. All other requests of the route optimization api and all other APIs seems to work.
Unfortunately this is a bug in the API Managment of Microsoft. We created a ticket for Microsoft but we don't know when it is fixed.
The problem is that the API Managment rejects POST requests with an empty body where no Content-Length header of 0 is passed. The java client does not pass this header for an empty body, therefore either the empty body must be avoided or the header must be added until the bug is fixed.
There are two possible solution to solve this problem:
Just pass a dummy body which is ignored anyway. For this you have to adapt the java client after generation:
replace all occurencies of
localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.noBody());
with
try {
byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes("dummybody");
localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody));
} catch (IOException e) {
throw new ApiException(e);
}
Explicitly send a Content-Length header of 0 by adding
System.setProperty("jdk.httpclient.allowRestrictedHeaders", "Content-Length");
to a setup method of your main and adding
localVarRequestBuilder.header("Content-Length", "0");
to the startEvaluationRequestBuilder and startOptimizationRequestBuilder methods.

How can I make a put request with okhttp3 without multipart body

My web service, which is a java servlet, accepts a put request with url params to take a specific action. The code below gets what I want done, but I would love to know if there is a better way to make a put request without adding a multipart body.
Do all put requests in Java Servlets expect a multipart body?
Do all put requests made using okhttp3 expect a multipart body?
Am I misunderstanding something else?
body = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("", "") // I would love to eliminate this.
.build();
request = new Request.Builder()
.url(url + "?my_param=" + URLEncoder.encode(myParam, "utf-8"))
.put(body)
.build();
response = client.newCall(request).execute();
From a pragmatic point of view, I'd say that you're looking at an implementation restriction of Servlets and/or OkHttp and it can probably be made to work using different libraries.
However,
from a standards view, I think your approach is incorrect and you should use a POST instead of a PUT. This requires reading both RFC-2616 (HTTP/1.1), section 9.6 on the POST request, and RFC-1630 (URL's in WWW), the section on query strings.
From the HTTP spec, section 9.6:
The fundamental difference between the POST and PUT requests is reflected in the different meaning of the Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations. In contrast, the URI in a PUT request identifies the entity enclosed with the request -- the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource.
From the URL's spec, page 6:
QUERY STRINGS
The question mark ("?", ASCII 3F hex) is used to delimit the boundary between the URI of a queryable object, and a set of words used to express a query on that object. When this form is used, the combined URI stands for the object which results from the query being applied to the original object.
These two combine to imply that you cannot use a PUT request in the way that you're trying to.

Java - send HTTP POST request without downloading all the content

Is it possible to send HTTP POST request to a webserver and retrieve just headers of response or read just few bytes of the body, so the rest won't be downloaded at all (so it won't consume traffic)? If yes, how?
I know that there is a HEAD method for this, but I need to achieve it by POST method .. well, I am not sure if I need the POST method, I just need to post the data. Maybe if the webserver isn't secured well enough (it doesn't check what method it's used - it's just directly access the post data), is it possible to send "post data" by HEAD request?
There is no built-in HTTP mechanism for this, and HTTP HEAD requests do not allow content in the body. If however you are the one writing the server code then anything is possible.
If this is the case, I would suggest a URL parameter that triggers this behavior. For example:
POST /myURL - This would return the whole response
POST /myURL?body=minimal - Returns the reduced size response that you are looking for.
And you would have to code your server method to construct and return the appropriate response based on the URL parameter.

Does the server send response only when its HTTP 200?

im writing a java application that sends a post request to a server and expect a json from the server. Now when i need to get the response from the server do i only need to get it from the inputStream when the http code is 200 (HTTP OK) or is there any other cases ? , example :
//...
if (urlConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
// only here try to get the response
}
//...
It depends on how the server is implemented. Check the API, if the server has one. If it's internal, ask your server guy.
Generally speaking, if your response code is either 2xx or 3xx, I would check the response anyway...
If the server your communicating with is following the spec then either 200 or 201 responses are valid to contain an entity. A 204 response is successful but has no data in the response.
See section 9.5 here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5 for details of acceptable responses to a POST. Extract below:
The action performed by the POST method might not result in a resource
that can be identified by a URI. In this case, either 200 (OK) or 204
(No Content) is the appropriate response status, depending on whether
or not the response includes an entity that describes the result.
If a resource has been created on the origin server, the response
SHOULD be 201 (Created) and contain an entity which describes the
status of the request and refers to the new resource, and a Location
header (see section 14.30).
There are three things to consider:
All 2xx codes denote success of some sort. But depending on the exact code, your reading code might be different. (204 for example means success but no content.)
There are redirecting codes (3xx). These are usually automatically followed by the http client library but you can also set them not to, in which case you need to have custom code that handles these cases.
There can be valuable information returned in the stream even if you get a code that denotes an error. Whether you want to process it depends on your exact needs.

Is it ok by REST to return content after POST?

I am using RESTlet and I have created a resource. I handle POST by overriding acceptRepresentation method.
The client should send me some data, then I store it to DB, set response to 201 (SUCCESS_CREATED) and I need to return some data to the client, but return type of acceptRepresentation is void.
In my case, I need to return some identificator so that client can access that resource.
For example, if I had a resource with URL /resource and the client sends POST request I add a new row in DB and its address should be /resource/{id}. I need to send {id}.
Am I doing something wrong? Does REST principles allow to return something after POST? If yes, how can I do it, and if no what is the way to handle this situation?
REST just says that you should conform to the uniform interface. In other words, it says you should do what POST is supposed to do as per the HTTP spec. Here is the quote from that spec that is relevant,
If a resource has been created on the
origin server, the response SHOULD
be 201 (Created) and contain an entity
which describes the status of the
request and refers to the new
resource, and a Location header
(see section 14.30).
As you can see from this, you have two places where you can indicate to the client where the newly created resource resides. The Location header should have an URL that points to the new resource and you can return an entity with the details also.
I'm not sure what the difference between overriding acceptRepresentation() and overriding post() but this example shows how to return a response from a POST.
I'd forgo sending anything in the body of the response. Just set Location: to the (full) URL of the newly created resource.
Your description suggests that this is exactly the semantics you:
POST a thing to create it
Respond with enough to know two things:
That the creation happened (the 201)
Where to find the new thing (the Location header)
Anything else is superfluous.
Two different questions:
Does the REST application pattern support returning data in a POST?
I don't think REST explicitly disallows it, but the preferred treatment is spelled out in Darrel's answer.
Does the RESTlet framework allow returning data in a POST?
Yes, even though it returns void, in a class which extends Resource, you have full access to the Response object object via the getResponse() method. So you can call getResponse().setEntity() with whatever data you want.
Output it in whatever format is requested. That might be:
<success>
<id>5483</id>
</success>
Or:
{ "type": "success", "id": 5483 }
It depends on what you usually do. If they're not expecting the data, they should just ignore it, but any client that wants to handle it properly should be able to.
If you respond 201 Created with an entity body, rather than a Location redirect, then it's a good idea to include a Content-Location header pointing to the resource that is being represented in the response.
This will avoid potential confusion - in which a client could (justifiably) assume that the response entity actually represents a new state of the 'creator', and not the created resource.
> POST /collection
> ..new item..
< 201 Created
< Location: /collection/1354
< Content-Location: /collection/1354
< <div class="item">This is the new item that was created</div>

Categories

Resources