Apache Camel throttling with a SOAP endpoint -> TransformerException - soap

We have an Apache Camel application providing SOAP service. The "initial route" starts from a Apache CFX -provided endpoint.
We need a simple mechanism to prevent the messages from being handled "too fast" (and don't have massive scalability needs).
Thus we ended up trying Throttler. Now, the problem is that after adding throttle to our route, something goes wrong.
The initial route, somewhat cleaned:
from("cxf:bean:sapEndpoint").routeId(SOAP_ENDPOINT)
.throttle(1)
.onException(Exception.class)
.to("direct:emailFaultNotification").handled(false)
.end()
.transacted(joinJpaTx)
.to(xsltRemoveEmptyElements) // Cleaning done with XSLT endpoint
.to("direct:inboundWorkOrderXml"); // Forward to actual processing
// direct:inboundWorkOrderXml contains various validation, persistance & response
Error in our log:
2013-02-18 16:50:16,257 [tp1636587648-50] ERROR DefaultErrorHandler - Failed delivery for exchangeId: ID-...-4. Exhausted after delivery attempt: 1 caught: javax.xml.transform.TransformerException: javax.xml.transform.TransformerException: com.sun.org.apache.xml.internal.utils.WrappedRuntimeException: Content is not allowed in prolog.
javax.xml.transform.TransformerException: javax.xml.transform.TransformerException: com.sun.org.apache.xml.internal.utils.WrappedRuntimeException: Content is not allowed in prolog.
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:735)[:1.6.0_37]
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:336)[:1.6.0_37]
at org.apache.camel.builder.xml.XsltBuilder.process(XsltBuilder.java:98)[camel-core-2.7.0.jar:2.7.0]
at org.apache.camel.impl.ProcessorEndpoint.onExchange(ProcessorEndpoint.java:102)[camel-core-2.7.0.jar:2.7.0]
at org.apache.camel.impl.ProcessorEndpoint$1.process(ProcessorEndpoint.java:72)[camel-core-2.7.0.jar:2.7.0]
...
I suppose that throttler doesn't work straight the way I supposed.
It seems that with throttling enabled, the XSLT endpoint receives empty or invalid XML? Without throttle definition everything works fine. With short try, the message body still seems to contain XML string?
Some ideas?

When using Camel error handling for redelivery then mind about streaming payloads. See about stream-caching at: http://camel.apache.org/stream-caching.html
There is also a tip in the top of the Camel CXF documentation page at: http://camel.apache.org/cxf about this

Finally the solution was more simple than I thought. Instead of using throttle in the route starting from "cxf:bean:sapEndpoint", I added throttle to route handling "direct:inboundWorkOrderXml".
Don't know the exact reason, could be somehow related to that some parts of throttle functionality might vary related on the from-endpoint of the route. (So problem with cxf-endpoint not encountered with direct-endpoint)

Related

I need simple proxy between 2 rest APIs

My code is working ok for GET/POST/PUT to/from restApi1 and restApi2.
However, my problem I need to implement HEAD/OPTIONS (no body!) and GET uri1
HEAD/OPTIONS could return 204 or 200 depends on a process status. I am getting error "Stream closed". Sounds like Camel want body bytes, but I don't indend to have it. Even I set ExchangePattern.InOnly or optional etc error occur...
What is correct way to see responses and handle requests WITHOUT body, just statuses exchange?
How to see response from restApi2 on Camel rest("/restApi1").head().route().routeId("id1")
.to("direct:restApi2").routeId("/id1").setHeader(Exchange.HTTP_METHOD,constant("HEAD"))
setExchanggePattern(ExchangePattern.OutOptionalIn).recepientList(simple(restApi2));
I figured it out. Need to set '.convertBodyTo(String.class)' even I don't have a body.

SOAP Web Service Client error, While consuming the service

I am getting this error while using SOAP web service client with axis 1. I had created stub from the wsdl file and tried to consume it then I got this error. wsdl is given to me by someone else.
error in msg parsing: xml was empty, did't parse!
below is the error message and stack trace for the same. Anyone can help.?
In order to fix the javax.activation.DataHandler issue you must add the JavaBeans Activation Framework activation.jar in your classpath.
In order to fix the javax.mail.internet.mimeMultipart issue you must add the Java Mail API mail.jar in your classpath.
The warning messages printed in your console shows that the above jars are not in the classpath.
There are several common reasons to receive the message:
error in msg parsing: xml was empty, did't parse!
The most obvious is that no message was sent. If you have some way of inspecting your transport channel, that would be worth looking at.
Also, the xml message could have been sent in an unexpected character set, e.g. A header declares it to be "Utf-8" but it is really "Win-1252", sometimes you can get away with that if you only use 7-bit ASCII characters, but anything in the 8-bit plane will cause it to bomb.
Also, the xml message could have had a byte order mark unexpectedly inserted at the beginning of the message.
Also, the xml message might not have the document declaration ( starting in the first byte of the message, that violates the specification, and often causes parsers to puke and claim that no message was found.
All things considered with this error message, the parser was not able to find a valid xml message that it could parse, so it didn't. You need to grab the data on the transport channel and figure out what exactly is wrong to resolve the issue.

mirth connect stop message propagation through destinations

I am using Mirth Connect 3.5.0.8232.
I have a Database Reader as source connector and a JavaScript writer as destination connector. I decided to put some fancy code in the destination, doing four separate things, which should follow one after the other. Basically I just wrote the code and it seemed to me that it was too long and too clumsy, so I decided to split it into 4 destinations that would be daisy-chained, via the "Wait for previous destination" option.
The question is : How do I interrupt this chain of execution if an error occurs on one of the destinations?
I found a JIRA issue from 2013 saying that actually the errors that would occur in the body of the Destination Connector would not prevent the message from going to all other Destinations. And it states that the 2.X version behavior is still current, i.e. an error that would occur in the Destination Transformer, will actually stop the message from propagating.
I tried throwing errors in both the Destination body, and in Destination Response Transformer, and in both cases the message would continue to other Destinations. I also tried returning ResponseFactory.getErrorResponse from the Destination body with no luck. I also tried setting responseStatus to ERROR in Destination Response Transformer to no avail. Did they mean the normal Transformer/Filter?
Also - maybe my particular solution of splitting a task into 4 distinct destinations was NOT the reason why the destinations were created in the first place? I think that the documentation states that destinations are basically what the actual word Destination stands for.
If the above case is true, maybe there are better ways of organizing the code functionally in Mirth? I think including external JS files is not allowed in JavaScript writer - even if it were, i would prefer everything to sit inside the Channel itself and be exportable/importable as a single file.
Thank you.
Yep, when an error is thrown from a filter/transformer, it's considered truly "exceptional" and so message flow is stopped (subsequent destinations in the same chain are not executed).
If an error is thrown from the actual destination dispatcher or from the response transformer, that destination is marked as ERROR, but subsequent destinations will still be executed.
You can still stop the message flow if you want though. Use filters on your subsequent destinations:

Camel does not set 'Transfer-Encoding chunked' in case response is prepared by exception handler processor

I am implementing REST services using Apache-CXF running on servicemix and for that I have a camel route that does some processing, sends the message over queue, process some more and send back the reply. Something like this:
from("direct:start")
.process(A)
.process("activemq:abc")
.process(B);
On this route I have applied some basic validation and exception handler and when I have to stop the route in both cases, I use something like this:
exchange.getOut().setBody(response);
exchange.setProperty(Exchange.ROUTE_STOP, Boolean.TRUE);
I use soap UI, restclient-UI and putty to make http requests and I get proper response body displayed in all of them. Now I wanted to preserve request headers so I made a little change everywhere in the code so that response bodies are set in exchange.getIn() only. For example: in case of validation failure I do:
exchange.getIn().setBody(response);
exchange.setProperty(Exchange.ROUTE_STOP, Boolean.TRUE);
Just with this little change, the rest clients I am using to make request stopped displaying the response body. As per the server logs, response is being generated and also as per the logs in rest client, I am getting the proper response but they are unable to display the response body only in case when I stop the route in between. Normal response is displaying just fine. Only the restclient-UI was considerate enough to show the error as to why they are not displaying body and the error is:
Byte array conversion from response body stream failed.
Diggin deeper, I found the only response header which was there in success response but missing in error response:
Transfer-Encoding chunked
Error response is around 1000 characters long and contains a header called content-length. I am not sure but I think the problem has something to do with this itself. I would really like to play with exchange.getIn but these different kind of responses prepared by camel are confusing me. How can I make sure my camel responses are always displayed properly?
The Content-Length header will be preserved from the original request so you need to remove it so that camel cxf can work out the new body length on the response and set Content-Length with that.

Proper way to convey error messages during calls to a REST service?

I'm writing a REST based web service, and I'm trying to figure out the best way to handle error conditions.
Currently the service is returning HTTP Errors, such as Bad Request, but how can I return extra information to give developers using the web service an idea what they're doing wrong?
For example: creating a user with a null username returns an error of Bad Request. How can I add that the error was caused by a null username parameter?
According to the HTTP spec, the text that comes after the three digit response code, the "Reason-Phrase", can only be replaced with a logical equivalent. So you can't respond with 400 null user and expect anything useful to happen. Indeed, The client is not required to examine or display the Reason- Phrase.
In general, the HTTP response entity (typically the page that accompanies the response) should contain information useful to the client to guide them forward, even when the response is an error. On the web, most such errors are HTML, and are devoid of machine readable information, but most browsers do show the error to the user (and SO's error page is pretty good!).
So for a primarily machine readable resource you have two options:
Pass a human readable message anyway. Return 400 Bad Request with a HTML response, which the client may opt to show to the user. It's dead easy but it's a bit like throwing an unchecked exception, it passes all the hard work to the client, or indeed the end user.
Allow clients to recover. Return 400 Bad Request with a machine readable response which is part of your API, so clients can recover from known error conditions. This is harder, like throwing a checked exception, it becomes part of the API, and it allows clients to recover gracefully if they want to.
You could even make the server support both scenarios by defining a media type for the machie readable error recovery document, and allow clients to "accept" them: Accept: application/atom+xml, application/my.proprietary.errors+json
Clients that forget the mandatory field can opt in to getting machine readable errors or human readable errors by choosing to Accepting the error media type.
It's stated in the HTTP spec that most error codes should return some basic text that gives a clarification of why the error is being returned. The basic Java Servlet Spec defines the HttpServletResponse.sendError(int Code, String message) for this purpose.
String desc = "my Description";
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(desc).type("text/plain").build());