Jaxrs multipart - jax-rs

I'm trying to perform a request to a jaxrs service which has media type set to multipart/form-data. This request contains a list of entities(xml) and an image(png, binary). I have created the request as described in this thread by BalusC.
The request seems ok after inspecting it in wireshark, except for the ip header checksum being wrong.(says something about "may be caused by IP checksum offload".)
My big issue here is how to handle the multipart request on the service side. I do not wish to include any libraries from apache.cxf, resteasy or anything of the sort. All I want to rely on is the jaxrs api.
The two parts in the request have names deliveries and signature, where the signature is a png image file sent as binary. The list of deliveries should be parsed from an xml(the entity has the xmlrootelement annotation and such, so this part works separately). I've attempted with this way of reading the different parts, but this was really a longshot;
#PUT
#Path("signOff")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public void signOffDeliveries(#FormParam("deliveries") List<Delivery> deliveries, #FormParam("signature")File signature) {
//do something with the signature(image) and the list of deliveries.
}
This does off course not work, and it gives me a 404 http status code if I run the request on Websphere, and a 415 when I run the request towards an embedded openejb (in our integration test framework). If I remove the FormParam annotations the request succeeds.
How can I read the different parts of the multipart request using only the jaxrs api?
EDIT
Ok, so I canged the PUT to POST, and added an #Encoding annotation to the params as so:
#POST
#Path("signOff")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public void signOffDeliveries(
#Encoded #FormParam("deliveries") String deliveries,
#Encoded #FormParam("signature") File signature) {
}
Now I get the xml as a text string, but I am not able to automatically unmarshal it to a list of deliveries even though the Content-Type of this part of the payload is set to application/xml. The other problem is that the file I receive has length==0, and I am not able to read any bytes from it.
Am I missing an essential point here?

Indeed I find it hard to understand why the JAX-RS spec doesn't standardize a support for this (I've just created https://java.net/jira/browse/JAX_RS_SPEC-413 to address this).
However it is nevertheless possible to support multi-part forms in an implementation independent fashion. Either you write your own MessageBodyReader for MultiPart form or you use a library like Apache Clerezza jaxrs.utils which provide a MultiPartBody object which respective MessageBodyReader. This library has no implementation specification dependency so your application will run on any jax-rs implementation.
For an example on how Clerezza jaxrs.utils is used see line 105 in http://svn.apache.org/viewvc/stanbol/trunk/development/archetypes/stateless-webmodule/src/main/resources/archetype-resources/src/main/java/MultiEnhancer.java?revision=1465777&view=markup. If you're not using OSGi (with white-board registration of resources) you will have to add to org.apache.clerezza.jaxrs.utils.form.MultiPartFormMessageBodyReader to your Application.

I have implemented this in Glassfish 4 without coupling with Jersey. #See this post for details

I do not wish to include any libraries from apache.cxf, resteasy or anything of the sort. All I want to rely on is the jaxrs api
You can't "rely on" the API, since it contains only interfaces. Classes that implement that interfaces come from RESTeasy, or Jersey, or CXF.
and a 415 when I run the request towards an embedded openejb
415 means "Method not supported", which happens when you send GET request to a PUT-expecting resource.
I would recommend to use POST instead of PUT in this case. I suspect that #FormParam is not suitable to work with PUT, in your particular case.

Related

How to fix WrongInputException in ASP.NET Core?

I want to use a SOAP web service prepared by another team, used internally in my new REST API prepared in ASP.NET Core. My web service client code was scaffolded with WCF Web Service Reference Provider Tool. I cleaned up code (e.g. I changed property and method names) according to my team's naming convention.
When I send requests by my new REST API, I received WrongInputException. I checked all the parameters from an example request, all of them are in the same place in my C# code consuming scaffolded client.
I don't know what message exactly is sent by my new REST API.
In my case, the main cause of the described behavior and WrongInputException was premature refactoring. I changed the names of properties in the web service client without knowledge of the consequences.
E.g. if the element in the request body is objectRefNum, then I cannot simply change the related property in the scaffolded service reference class, because - without extra configuration - that name is copied with the same letter case to the request body of the SOAP envelope. The SOAP envelope should be encoded in the case-sensitive mode.
To trace the raw request body send by my new REST API in ASP.NET Core, I followed instructions from this excellent answer.
(Note, BTW, that kind of error (applying inappropriate letter case) could be handled by IDE, at least as a warning, but it is not, so: we need to be careful when we make refactoring, even if we have unit tests covering all the paths, and even if we use semantic renaming supported by IDE.)

How to access to request body using WebFlux and Netty HttpClient

I need to calculate some kind of digest of the request body using the WebClient of Webflux and this digest must be set into a HTTP header. Using the good old Spring MVC ClientHttpRequestInterceptor is easy because the request body is provided as an array of bytes.
The ExchangeFilterFunction does not provide access to the request body.
The body is sent as JSon and Spring uses Jackson in order to serialize Java objects, so an option could be serialize my Object into Json and calculate the digest on it, but this strategy has two drawbacks:
my code would repeat what Spring will do when the request is actually sent
there's no guarantee that the acutal bytes sent by Spring as a request are equal to what I've passed to the digest function
I suppose that I should use some low level API of Netty, but I can't find any example.
I implemented the solution proposed by #rewolf and it worked, but I encountered an issue because of the multi-threading nature of WebFlux.
In fact, it's possible that the client request is saved into the thread-local map by one thread, but a different thread tries to get it, so a null value is returned.
For example, it happens if the request to be signed is created inside a Rest controller method which has a Mono as a request body parameter:
#PostMapping
public String execute(#RequestBody Mono<MyBody> body){
Mono<OtherBody> otherBody = body.map(this::transformBodyIntoOtherBody);
...
webClient.post()
.body(otherBody)
.exchange();
...
}
According to Reactor specs, the Reactor Context should be used instead of Thread Local.
I forked #rewolf project and implemented a solution based on Reactor Context: https://github.com/taxone/blog-hmac-auth-webclient
This is not currently easy to do with WebClient. But there are ways to do so by intercepting the body post-serialization. This can be done by registering a custom encoder that intercepts the data after encoding, and the passes it to a custom HttpConnector to inject it as a header.
This blog post explains one way to achieve it: https://andrew-flower.com/blog/Custom-HMAC-Auth-with-Spring-WebClient
Edit: Currently this blog post doesn't take into account concurrent requests. See the accepted answer by Claodio for the modified approach.

Does CXF's behavior of treating #FormParams like #QueryParams on a #GET request violate the JAX-RS specification?

My company just wasted some serious engineering time tracking down a problem related to #FormParams on a JAX-RS #GET method. My thinking was that this should – by definition – not work at all, as form parameters are supposed to be transmitted in a x-www-form--urlencoded request body and, per RFC 7231 section 4.3.1, a request body "within a GET request message has no defined semantics" and is supposed to be ignored by the server.
However, we discovered that – at least in CXF – #FormParams on a #GET behave the same way as #QueryParams! After much discussion and research, I came across this paragraph in the CXF documentation:
Note that the parameters, marked with #FormParam annotation, can take the values from the query parameters in case, if request body is already consumed. This is defined in JAX-RS specification due to the filters (Spring security, etc) consuming the body and thus JAX-RS form parameters becoming empty. User can optionally deactivate standard behavior through setting "set.form.parameters.from.http.parameters" message property to false.
I assume that the reference to JAX-RS is pointing to section 11.1 in the specification, where it states:
Servlet filters may trigger consumption of a request body by accessing request parameters. In a servlet
container the #FormParam annotation and the standard entity provider for application/x-www-form--urlencoded MUST obtain their values from the servlet request parameters if the request body has already
been consumed. Servlet APIs do not differentiate between parameters in the URI and body of a request so
URI-based query parameters may be included in the entity parameter.
Now my question is: Does CXF's behavior of treating #FormParams like #QueryParams on a #GET request violate the JAX-RS specification?
The JAX-RS spec mandates obtaining #FormParam values from the request parameters, "if the request body has already been consumed". In a GET request there is no request body to be consumed in the first place, so I would say that this statement does not apply to GET requests at all.
As a minor follow-up question, I'm also curious if someone could clarify what is meant when the spec states that "Servlet APIs do not differentiate between parameters in the URI and body of a request so
URI-based query parameters may be included in the entity parameter" – the servlet APIs that I know can very well distinguish between information in the URI (i.e., HttpServletRequest.getQueryString()) from information in the body (i.e., ServletRequest.getReader()).

How is data sent in REST web services

I am learning about web services. I now have good understanding of SOAP. I have few questions regarding REST web services.
1) DO GET, PUT & POST methods in REST web services work exactly the same way as they work with a simple website.
2) GET , PUT & POST methods in REST web services allows us to send/Receive data(say: tweet in Twitter) between client & the web service. Is this message sent(PUT & POST) & Received(GET) in the Body of the POST/PUT method in XML/JSON/other formats or is the file(in a specific format) sent separately.
3) Are there any Browser tools available to see what is Sent & Received in REST web services.
First of all, clarifying a few things. REST is an architectural style, a set of constraints to guide your structural design decisions. REST is not coupled to any particular underlying protocol, so it's not dependent on HTTP, although it's very common.
Second, keep in mind that REST became a buzzword to refer to almost any HTTP API that isn't SOAP, and most of the so called REST APIs aren't REST at all. Most of them are simple RPC over HTTP. I recommend reading this answer for some clarification on that.
Now, to your questions:
1) DO GET, PUT & POST methods in REST web services work exactly the
same way as they work with a simple website.
The problem with your question is that the only exact definition of how those methods work is the one defined by the RFCs, and a simple website might implement it differently. For instance, PUT isn't allowed to be used for partial updates, but many websites and HTTP APIs do that.
As I said above, REST is protocol independent, but respecting the uniform interface constraint and applying the principle of generality, you should stick to the standard semantics of the underlying protocol as much as possible, which means that if you're using HTTP 1.1, you should stick to the behavior determined in the RFCs 7230 to 7235.
2) GET , PUT & POST methods in REST web services allows us to
send/Receive data(say: tweet in Twitter) between client & the web
service. Is this message sent(PUT & POST) & Received(GET) in the Body
of the POST/PUT method in XML/JSON/other formats or is the file(in a
specific format) sent separately.
The format is established in a previous contract between the client and server -- usually in the documentation -- and it's handled during the request using the Accept and Content-Type headers. For instance, if a client wants JSON response, it sends the Accept: application/json header. If the server can't respond with JSON, it should fail with 406 Not Acceptable.
Keep in mind that in an actual REST webservice, you don't use a generic media-type like application/json since that says absolutely nothing about the content other than how to parse it. You should have more specific media-types for your resources, and focus your documentation on those. For instance, an User resource in JSON format can have a custom media-type like application/vnd.mycompany.user.v1+json.
3) Are there any Browser tools available to see what is Sent &
Received in REST web services
In Google Chrome you can use the developer tools, or some client like this or this. You can also use a command line client like curl.
Also, keep in mind that it should be pretty easy to drop-in a generic html+javascript client into a real REST API to make it navigable with a browser. Here is an example of a REST API using HAL+JSON and a generic client.
https://api-sandbox.foxycart.com/hal-browser/browser.html#/
1) Yes, REST functions pretty much exactly the same as a normal HTTP website, for example, GET would retrieve data without changing the state of the server and POST would send data to the web service as a new 'Object', and PUT would modify an existing 'Object'
2) You would enclose the data to be sent inside the body of the request for POST and it would return data back in the body. GET does not accept any data in the body (and you would specify it as part of the path/query parameters ie http://service.com/rest/directory/user1?param=something) but would return the results of the query inside the body. POST would require a message to be posted in one of the forms specified as accepted, most usually JSON. Specifying the Content-Type would indicate to the web server what type of data you are sending and the Accept header would indicate what type you wish your response to be in.
3) In Google Chrome you can use the Developer Tools (Ctrl+Shift+I in Windows) and go on the Network tab to see what is sent and received as a page is loading/performing tasks. You can use DHC or RestEasy to send your own custom requests to REST Services through a GUI, or cURL to do this through a command line
DO GET, PUT & POST methods in REST web services work exactly the same way as they work with a simple website?
yes. they are same anywhere we are using http. read this article specially Request Method section
GET , PUT & POST methods in REST web services allows us to send/Receive data(say: tweet in Twitter) between client & the web service. Is this message sent(PUT & POST) & Received(GET) in the Body of the POST/PUT method in XML/JSON/other formats.
yes they are generally in these formats but can be in any depending on ur requirement.
read this ans for better understanding of content-type and headers in general
Are there any Browser tools available to see what is Sent & Received in REST web services.
as mentioned in one of the comments. Postman is an awesome chrome extension. I generally preffer fiddler over Postman but it is not a in browser tool.

Implementing versioning a RESTful API with WCF or ASP.Net Web Api

Assume i've read a lot about versioning a restful api, and I decided to not version the the service through the uri, but using mediatypes (format and schema in the request accept header):
What would be the best way to implement a wcf service or a web api service to serve requests defining the requested resource in the uri, the format (eg. application/json) and the schema/version (eg player-v2) in the accept header?
WCF allows me to route based on the uri, but not based on headers. So I cannot route properly.
Web Api allows me to define custom mediatypeformatters, routing for the requested format, but not the schema (eg. return type PlayerV1 or PlayerV2).
I would like to implement a service(either with WCF or Web Api) which, for this request (Pseudo code):
api.myservice.com/players/123 Accept format=application/json; schema=player-v1
returns a PlayerV1 entity, in json format
and for this request:
api.myservice.com/players/123 Accept format=application/json; schema=player-v2
returns a PlayerV2 entity, in json format.
Any tips on how to implement this?
EDIT: To clarify why I want to use content negotiation to deal with versions, see here: REST API Design: Put the “Type” in “Content-Type”.
What you are bringing here does not look to me as versioning but it is is more of content negotiation. Accept header expresses wishes of the client on the format of the resource. Server should grant the wishes or return 406. So if we need more of a concept of Contract (although Web API unline RPC does not define one) then using resource is more solid.
The best practices for versioning have yet to be discussed fully but most REST enthusiast believe using the version in the URL is the way to go (e.g. http://server/api/1.0.3/...). This also makes more sense to me since in your approach using content negotiation server has to keep backward compatibility and I can only imagine the code at the server will get more and more complex. With using URL approach, you can make a clean break: old clients can happily use previous while new clients can enjoy the benefits of new API.
UPDATE
OK, now the question has changed to "Implementing content-negotiation in a RESTful AP".
Type 1: Controller-oblivious
Basically, if content negotiation involves only the format of the resource, implementing or using the right media type formatter is enough. For example, if content negotiation involves returning JSON or XML. In these cases, controller is oblivious to content negotiations.
Type 2: Controller-aware
Controller needs to be aware of the request negotiation. In this case, parameters from the request needs to be extracted from the request and passed in as parameter. For example, let's imagine this action on a controller:
public Player Get(string schemaVersion)
{
...
}
In this case, I would use classic MVC style value providers (See Brad Wilson's post on ValueProviders - this is on MVC but Web API's value provider looks similar):
public Player Get([ValueProvider(typeof(RequestHeadersSchemaValueProviderFactory))]string schemaVersion)
{
...
}