I'm getting an intermittent exception org.apache.commons.httpclient.ProtocolException: Unbuffered entity enclosing request can not be repeated. when using Apache HTTP client library 4.x with Restlet 1.1. The request entity is of type InputRepresentation, which is associated with ByteArrayInputStream of known size, with size specified at the time of instantiation.
The exception is thrown in method writeRequestBody in class org.apache.commons.httpclient.methods.EntityEnclosingMethod
if ((this.repeatCount > 0) && !requestEntity.isRepeatable()) {
throw new ProtocolException(
"Unbuffered entity enclosing request can not be repeated.");
}
To be honest, the cause of this exception is not clear (especially due to its intermittent nature). However, some research suggests that using Apache BufferedHttpEntity to wrap the request entity should help.
Is there a way to inform Restlet to use BufferedHttpEntity when passing its request to the Apache library for handling? What could be the cause of the problem?
If the entity content stream can be reproduced (repeated), which is certainly the case with ByteArrayInputStream, there is no need for BufferedHttpEntity. One just needs to make sure that the original request entity returns a new instance of InputStream from HttpEntity#getContent() method and HttpEntity#isRepeatable() returns true.
Please note though that org.apache.commons.httpclient.ProtocolException is from an older (EOL-ed) version 3.x. Please make sure you do not have some kind of version mix-up in your application
This is a limitation of the Restlet Framework connector integrating with Apache HTTP Client.
In version 2.0 of RF, there is a new ClientResource class with "retryAttempts" and "retryDelay" property that provides the same behavior, but based on the Restlet abstractions.
Related
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.
I am working on a prototype logging solution using Serilog in ASP.NET Core 3.1 and one of my requirements is the ability to log the entire HTTP request and response payload. To do this, I am writing my own middleware and instead of creating a whole new log entry for this data, I would like to associate the request and response payload with the current log context via Serilog's IDiagnosticContext / DiagnosticContext in https://github.com/serilog/serilog-extensions-hosting
I've been studying the code a bit and it appears it is thread-safe by way of the AmbientDiagnosticContextCollector class and the System.Threading.AsyncLocal that it utilizes.
Is my understanding of this correct or am I missing something that I should be accounting for?
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.
Long story as brief as possible...
I have an existing application that I'm trying to get ServiceStack into to create our new API. This app is currently an MVC3 app and uses the UnitOfWork pattern using Attribute Injection on MVC routes to create/finalize a transaction where the attribute is applied.
Trying to accomplish something similar using ServiceStack
This gist
shows the relevant ServiceStack configuration settings. What I am curious about is the global request/response filters -- these will create a new unit of work for each request and close it before sending the response to the client (there is a check in there so if an error occurs writing to the db, we return an appropriate response to the client, and not a false "success" message)
My questions are:
Is this a good idea or not, or is there a better way to do
this with ServiceStack.
In the MVC site we only create a new unit
of work on an action that will add/update/delete data - should we do
something similar here or is it fine to create a transaction only to retrieve data?
As mentioned in ServiceStack's IOC wiki the Funq IOC registers dependencies as a singleton by default. So to register it with RequestScope you need to specify it as done here:
container.RegisterAutoWiredAs<NHibernateUnitOfWork, IUnitOfWork()
.ReusedWithin(ReuseScope.Request);
Although this is not likely what you want as it registers as a singleton, i.e. the same instance returned for every request:
container.Register<ISession>((c) => {
var uow = (INHibernateUnitOfWork) c.Resolve<IUnitOfWork>();
return uow.Session;
});
You probably want to make this:
.ReusedWithin(ReuseScope.Request); //per request
.ReusedWithin(ReuseScope.None); //Executed each time its injected
Using a RequestScope also works for Global Request/Response filters which will get the same instance as used in the Service.
1) Whether you are using ServiceStack, MVC, WCF, Nancy, or any other web framework, the most common method to use is the session-per-request pattern. In web terms, this means creating a new unit of work in the beginning of the request and disposing of the unit of work at the end of the request. Almost all web frameworks have hooks for these events.
Resources:
https://stackoverflow.com/a/13206256/670028
https://stackoverflow.com/search?q=servicestack+session+per+request
2) You should always interact with NHibernate within a transaction.
Please see any of the following for an explanation of why:
http://ayende.com/blog/3775/nh-prof-alerts-use-of-implicit-transactions-is-discouraged
http://www.hibernatingrhinos.com/products/nhprof/learn/alert/DoNotUseImplicitTransactions
Note that when switching to using transactions with reads, be sure to make yourself aware of NULL behavior: http://www.zvolkov.com/clog/2009/07/09/why-nhibernate-updates-db-on-commit-of-read-only-transaction/#comments
I have run into a problem when calling web service on a SAP PI bus from my WCF client.
The operation is defined as one-way, and the method on my proxy operation contract is decorated accordingly when the service reference is added.
However, the service client gets an exception when calling the according operation:
The one-way operation returned a non-null message with Action=''
Using SoapUI, the method on the bus can be called successfully, and it returns a SOAP envelope with an empty body. The bus people told me, this is according to the SOAP specs:
(SOAP specs, chapter 4.7.9, One-way operations):
There are differing interpretations of how HTTP is to be used when performing one-way operations.
R2714 For one-way operations, an INSTANCE MUST NOT return a HTTP response that contains an envelope. Specifically, the HTTP response entity-body must be empty.
R2750 A CONSUMER MUST ignore an envelope carried in a HTTP response message in a one-way operation.
R2727 For one-way operations, a CONSUMER MUST NOT interpret a successful HTTP response status code (i.e., 2xx) to mean the message is valid or that the receiver would process it.
So it seems, my WCF client doesn't comply with R2750.
I have found out that when I force the operation contract on the proxy to be IsOneWay = false, everything works.
Is there anything wrong with the way WCF handles one way operations or do I do something wrong (more likely)?
Is there anything else I should do, it just doesn't seem right to override the generated WCF proxy client.
Thanks for any suggestions.
It looks like SAP PI incorrectly sends an empty SOAP envelope and .NET incorrectly interprets that envelope.
Some options from this thread:
alter the generated proxy and remove OneWay=true (or add OneWay=false) to the method definition
catch the Protocol Violation in an exception handler and ignore it
use a 2.0 style webreference to call the service
apply SAP patch Note 1459995 - Soap Sender Adapter HTTP 202 and add &responsecode202=true to the url
The first and last options both worked for me. Further discussion on this sap.com thread.
I would take a look at this article as well by Gerben van Loon here. One way operation might not really be one way according to the standards.
Check this SAP thread out for the complete discussion:
http://scn.sap.com/thread/1627368
#Brian Low has answered this question correctly and very thoroughly (is should get marked as the answer).
I would also like to add that this is a known error in which the SOAP Adapter does not comply with the aforementioned WS-I Basic Profile 1.1 (R2750) and WCF does not comply with (R2750). The result... Hours of wasted time and teeth gnashing....
I believe that this particular problem can be fixed by adding the following attribute declaration to the operation in the client porxy:
[WebInvoke(BodyStyle = WebMessageBodyStyle.Wrapped)]
Without seeing what the signature of the method looks like, my best guess is that your method defined to return something other than "void". Since the operation is one-way, the method can only be defined using "void" (has no return). Anything else, and the operation is NOT one-way.