Jersey Client doesn't set Content-Length - java

I am using dropwizard for writing a webapp and also using Jersey Client as mentioned at
http://dropwizard.codahale.com/manual/client/#man-client-jersey
But it seems that whenever i try to do a post using the jersey client the remote webservice complains that Content-Length header is missing and fails.
public JobResponse createJob(JobRequest job) {
return jerseyClient.resource(URI.create(JOBS_URL))
.type(MediaType.APPLICATION_JSON_TYPE)
.header("Api-Key", job.getApiKey())
.post(JobResponse.class, job);
}
I have confirmed that the request does not contain the header and despite my best efforts I haven't been able to figure out why this is happening. Does anyone know if there is something that I am missing?
PS: The service that i am trying to hit is https://app.zencoder.com/docs/api/jobs/create

This is known "issue" and actually intended behavior.
Problem here is that entity is processed AFTER headers are written out to "the wire", thus Content-Length header value is not know when headers are serialized. If you need to have it, you have several options (with various complexity):
serialize entity by yourself; if you provide entity as string (or byte[]), Content-Length should be set.
create your own MessageBodyWriter, which would compute size of entity in getSize() method call.
there might be some other way how to do it, but I can't think of another right now.. hope it helps.

I was facing the same problem and the answer from Pavel didn't work out for me (I was using a FormMutiPart object).
I was using ApacheHttpClient4 instead of the regular com.sun.jersey.api.client.Client. Changing back to the Jersey Client, the Content-Lenght is calculated (at least in the case of FormMultiPart entity).

Related

Dynamic Cookies For Retrofit 2 Requests

I've been using retrofit for quite a long time and haven't faced any serious usability issue before now. So my use case is very simple, I've to fetch an entity from another API that we're using to process a few data. Now the only issue is the service is using Cookies to accept entity id.
So this means that each request needs to have dynamic set of cookie associated with it. But currently I cannot see anything such that in Retrofit. I can see a old PR, but it was rejected for unknown reason.
Can anyone from Retrofit team can help in this matter. I think it will be very helpful. If you need code examples I can provide that in an edit.
TIA
Implement a custom CookieJar and set on the OkHttpClient
https://square.github.io/okhttp/4.x/okhttp/okhttp3/-cookie-jar/
abstract fun loadForRequest(url: HttpUrl): List<Cookie>
Load cookies from the jar for an HTTP request to url. This method returns a possibly empty list of cookies for the network request.

Rest api - update single field of resource

Lets say I have rest endpoint for my Driver resource.
I have PUT method like this
myapi/drivers/{id}
{body of put method}
I need to add functionality which will allow to 'enable' and 'disable' driver
Is it good idea to create new endpoint for that like this?
PUT myapi/drivers/{id}/enable/false
or it is better to use existing endpoint ? One problem with using existing endpoint is that driver has lot's of fields(almost 30) and sending all those fields just for updating only 'enabled' or 'disable' driver is something overkill.
What do you think?
This is exactly what the HTTP method PATCH is made for. It is used in cases where the resource has many fields but you only want to update a few.
Just like with PUT, you send a request to myapi/drivers/{id}. However, unlike with PUT, you only send the fields you want to change in the request body.
Creating endpoints like myapi/drivers/{id}/enable is not very RESTful, as "enable" can't really be called a resource on its own.
For an example implementation of a Spring PATCH endpoint, please see this link.
Use PATCH Http metod to update one field
PATCH myapi/drivers/{id}/enable

Changing HTTP method in RequestDispatcher

How do I change HTTP method in javax,servlet.RequestDispatcher?
I have some old service APIs that support GET and POST, The new version supports DELETE method for removing a record which used to happen through POST earlier.
We are decommissioning old version APIs by setting RequestDispatcher.forward() for old end points (stop gap arrangement until clients change). everything was cool except this POST to DELETE mapping.
Any solution there for this problem without adding POST end point for delete operation in new API?>
Although I agree using the next layer after your servlets would be a better choice, this is interesting. It use to be common to wrap an incoming request to add request based functionality (IE: auth state, etc). The HttpServletRequestWrapper was used to accomplish this. You could do the following if you just need to change the method:
class PostDeleteAdapter extends HttpServletRequestWrapper {
public String getMethod(){ return "POST"; }
}
You may also change other aspects of the incoming request if you need to further adapt the request. This may play well with your servlet containers RequestDispatcher, however it's dependent upon the container entirely.
I think you can't do it using servlet API. You can do what you want creating a new request, processing it's response and sending it back through the original response (in the servlet).
Some http clientes might help you. See Apache HTTP client:
http://hc.apache.org/httpclient-3.x/methods/delete.html)

Grizzly HttpServer: Set permanent header for every response

I am using a Grizzly HttpServer and i want to add a specific header in every response. Specifically, i want to avoid CORS problems by adding an 'Access-Control-Allow-Origin' header.
So, ideally, i want something like this:
HttpServer server = GrizzlyServerFactory.createHttpServer(uri, crc);
server.setHeader("Access-Control-Allow-Origin" , "*");
Generally, i am looking for a solution that does not require that i have to manually insert this header in every request-response action.
Is there any way to do this?
As #alexey said, there is no way (from the current Grizzly Server version) to do this. If anyone finds something else that works, i will gladly confirm it as an accepted answer.
The best alternative that works quite well is to extend the 'ContainerResponseFilter' class and override the 'filter' method.
Here is an example for 1.x API
Here is an example for 2.x API (minor changes)

Put Rest webservices with just one parameter

I am using Java and Jersey for my REST web services. I want to have a put method that takes just one integer value. From this integer value I can then use business logic to update my database. Usually I am passing a custom DTO from my PUT as they often contain more than one piece of information. It seems a bit wasteful creating a custom DTO for just one value. Is it possible to pass this variable as a #PathParam with a PUT
I have tried
#PUT
#Path("apple/{pearId}")
public void doStuff(#PathParam("pearId") Integer pearId) {...}
but this does not work if I pass in
http://myurl/apple/123
I tried using REST client to PUT this but end up with a HTTP Status 403
Can I pass a variable as a PUT #PathParam?
Thanks
UPDATE: more details on error
The error is from REST Client
HTTP Status 403 -
type Status report
message
descriptionAccess to the specified resource () has been forbidden
I will add logging now to see if I actually get into the method
You can definitely use #PathParam with a PUT. HTTP 403 means Forbidden. This error is probably not coming from Jersey. Where is that error coming from? Does your code throw that error?

Categories