Get Request Attribute using HttpClient - java

I found a couple of questions somewhat related to this:
httpclient-request-set-attribute-question
commons-httpclient-adding-query-string-parameters-to-get-post-request
but I think I am trying to do something different here:
I have a servlet which will set an attribute into the request. In my Java client, I am using HTTP Components library, and I want to read the attribute in my client.
Is this an invalid use case for the HTTP Components library?
If not, one way would be to serialize the object in the servlet and de-serialize it back in the client, but I am not sure if that is the best practice.
Is there an API I am missing here?

Request attributes are not accessible to the client.
You should send them as response somehow (write them as key-value pairs, serialize the object graph with JSON, etc.). So yes, that's the accepted practice

Related

Mapping an HTTP DELETE request entity body to a method parameter

I am building a REST API using JAX-RS. In angular front-end, I am sending the object to be deleted in the body of the HTTP request (JSON format). Now I need a way to map this HTTP DELETE body request which is containing the object that needs to be deleted to a local variable in the REST method.
For instance, on SPRING I did this by simply annotating an object variable with #RequestBody.
I was checking oracle's javaEE7 docs but the examples there are really basic and don't include complex objects, also the different tutorials that I found elsewhere were on the track of simple delete requests mapping a simple id with #PathParam.
Maybe before this question, the first question I should ask is whether sending the object in an HTTP's request body is at all a good approach? I was reading some articles which designated it as not such a good practice, although it is not explicitly forbidden. What would be the disadvantages of this approach?
I remember while I was researching about this method in SPRING, I read somewhere that malicious attacks could be possible by specially crafted user inputs (the persistence framework that I am using is JPA, EclipseLink).
Would it perhaps be better to map the primary key on a series of #Path variables and then map them using #PathParam?
So to sum up, first of all, is this a good approach?
And how can I read the object in the HTTP's request body?
Some pointers would be highly appreciated!
Unlike Spring MVC, JAX-RS does not define any annotation for the request payload.
The JAX-RS approach is slightly different: the value of the parameter not annotated with any #***Param annotations is mapped from the request entity body. Such parameter is called entity parameter.
The first question I should ask is whether sending the object in an HTTP's request body is at all a good approach?
Please refrain from doing that, as it's not how DELETE is supposed to work.
Find below a quote from the RFC 7231, the document that currently defines the semantics and content of the HTTP/1.1 protocol:
A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.
For interoperability, I advise you to stick to the standards as much as you can. And you definitely shouldn't be require to send any payload to identify the resource to be deleted.
Its primary key is 8 fields long.
The URI, which stands for Universal Resource Identifier, is meant to identify a resource.
As you have a bunch of fields that, in conjunction, identify a resource, I advise you to rethink your application design. You could, for example, introduce some sort of unique value to identify your resources. Have a look at UUID.
With JAX-RS you don't need a something like a #RequestBody.
You can simply add the class as parameter and it will be filled with the request body.
In you case passing the data in the body makes sense but how does your URL look like? As with REST you should have resources that are addressable by a URL

How to stream several large files to jetty

I would like to send several large files via HTTP using multipart/formdata.
I actually just want to stream them through my service, so I'd like to get the different parts as streams and absolutely would like to avoid that the whole request is buffered in memory before I get a chance to pass the data on.
I get the feeling that with jetty (we're using Dropwizard 0.7.1 which comes with jetty 9.0.7) the whole request gets buffered before my code is executed.
Is there a way to avoid that? Ideally, I'd like to have an event-based system (which fires an event like "next part with name xxx" and gives me a stream I can consume).
A request with multipart/formdata is processed by various internal components to break apart the sections so that HttpServletRequest.getParts() (and various similar methods) can work properly.
Option #1: Handle Multi-part yourself
It can be a bit tricky to subvert this behavior of the Servlet spec, but I'll give it a go.
First, do not declare the #MultipartConfig configuration for the servlet you want to handle this request data.
Next, do not access methods in the HttpServletRequest that need to know about the parameters of the request, or its parts.
Override the HttpServlet.service(HttpServletRequest, HttpServletResponse) method, not the doPost() method, and process the raw Request payload content yourself.
This means you'll be writing a MultiPart InputStream Parser, and handling the parsing of the multi-part yourself. There's plenty of examples of this online, you'll just want to pick one that makes more sense to you.
Option #2: Don't use POST with multi-part
If you are streaming upload a file, don't use POST with multi-part, use PUT with raw payload data, then you'll skip the entire layer of magic that is the multi-part request POST payload.

How bad is it to use #POST to retrieve data?

I am currently using a #POST web service to retrieve data.
My idea, at the beginning, was to pass a map of parameters. Then my function, on the server side, would take care of reading the needed parameters in the map and return the response.
This is to prevent having a big number of function almost identical on the server side.
But if I understood correctly, #POST should be use for creation of content.
So my question: Is it a big programming mistake to use #POST for data retrieval?
Is it better to create 1 web service per use case, even if it is a lot?
Thanks.
Romain.
POST is used to say that you are submitting data.
GET requests can be bookmarked, POST can't. Before there were single page web appliations we used post-redirect-get to accepta data submission and display a bookmakable page.
If you use POST to retrieve data then web-caching doesn't work, because the caching code doesn't cache POSTS, it expects POST to mean it needs to invalidate its cache. If you split your services out use-case-wise and use GET then you can have something like Squid cache the responses.
You may not need to implement caching right now, but it would be good to keep the option open. Making your services act in a compliant way means you can get leverage from existing tools and infrastructure (which is a selling point of REST).
doGet();
Called by the server (via the service method) to allow a servlet to handle a GET request.
doPost()
Called by the server (via the service method) to allow a servlet to handle a POST request.
No issues with them.Both will handle your request.

Java's Jersey, RESTful API, and JSONP

This must have been answered previously, but my Google powers are off today and I have been struggling with this for a bit. We are migrating from an old PHP base to a Jersey-based JVM stack, which will ultimately provide a JSON-based RESTful API that can be consumed from many applications. Things have been really good so far and we love the easy POJO-to-JSON conversion. However, we are dealing with difficulties in Cross-Domain JSON requests. We essentially have all of our responses returning JSON (using #Produces("application/json") and the com.sun.jersey.api.json.POJOMappingFeature set to true) but for JSONP support we need to change our methods to return an instance of JSONWithPadding. This of course also requires us to add a #QueryParam("callback") parameter to each method, which will essentially duplicate our efforts, causing two methods to be needed to respond with the same data depending on whether or not there is a callback parameter in the request. Obviously, this is not what we want.
So we essentially have tried a couple different options. Being relatively new to Jersey, I am sure this problem has been solved. I read from a few places that I could write a request filter or I could extend the JSON Provider. My ideal solution is to have no impact on our data or logic layers and instead have some code that says "if there is a call back parameter, surround the JSON with the callback, otherwise just return the JSON". A solution was found here:
http://jersey.576304.n2.nabble.com/JsonP-without-using-JSONWithPadding-td7015082.html
However, that solution extends the Jackson JSON object, not the default JSON provider.
What are the best practices? If I am on the right track, what is class for the default JSON filter that I can extend? Is there any additional configuration needed? Am I completely off track?
If all your resource methods return JSONWithPadding object, then Jersey automatically figures out if it should return JSON (i.e. just the object wrapped by it) or the callback as well based on the requested media type - i.e. if the media type requested by the client is any of application/javascript, application/x-javascript, text/ecmascript, application/ecmascript or text/jscript, then Jersey returns the object wrapped by the callback. If the requested media type is application/json, Jersey returns the JSON object (i.e. does not wrap it with the callback). So, one way to make this work is to make your resource method produce all the above media types (including application/json), always return JSONWithPadding and let Jersey figure out what to do.
If this does not work for you, let us know why it does not cover your use case (at users at jersey.java.net). Anyway, in that case you can use ContainerRequest/ResponseFilters. In the request filter you can modify the request headers any way you want (e.g. adjust the accept header) to ensure it matches the right resource method. Then in the response filter you can wrap the response entity using the JSONWithPadding depending on whether the callback query param is available and adjust the content type header.
So what I ultimately ended up doing (before Martin's great response came in) was creating a Filter and a ResponseWrapper that intercepted the output. The basis for the code is at http://docs.oracle.com/cd/B31017_01/web.1013/b28959/filters.htm
Essentially, the filter checks to see if the callback parameter exists. If it does, it prepends the callback to the outputted JSON and appends the ) at the end. This works great for us in our testing, although it has not been hardened yet. While I would have loved for Jersey to be able to handle it automatically, I could not get it to work with jQuery correctly (probably something on my side, not a problem with Jersey). We have pre-existing jQuery calls and we are changing the URLs to look at the new Jersey Server and we really didn't want to go into each $.ajax call to change any headers or content types in the calls if we didn't have to.
Aside from the small issue, Jersey has been great to work with!

How can you pass data from a Filter to the endpoint in Jersey

Can you pass some data from a javax.servlet.Filter to a Jersey endpoint without using ThreadLocal or HttpSession?
And because the first question will be "why do you want to do this?": mostly curious. In practice I think I could use this to pass some data generated during authentication to the endpoint. Not using ThreadLocal eliminates the temptation to use that down the chain (hope there's no need to explain why that's evil) and not using HttpSession is more of a quirk :)
Try injecting with #Context. I'm not sure what object you will receive though (somewhere I saw WebServiceContext, which is jax-ws), but it should contain the HttpServletRequest. so you will be a able to set request attributes in the filter and read them in the rest service

Categories

Resources