Camel Apache: can I use a retryWhile to re-send a request? - apache-camel

I would like to achieve the following kind of orchestration with CAMEL:
Client sends a HTTP POST request to CAMEL
CAMEL sends HTTP POST request to external endpoint (server)
External server replies with a 200 OK
CAMEL sends HTTP GET request to external endpoint (server)
External server replies
After step 5, I want to check the reply: if the reply is a 200 OK and state = INPROGRESS (this state can be retrieved from the received XML body), I want to re-transmit the HTTP GET to the external endpoint until the state is different from INPROGRESS.
I was thinking to use the retryWhile statement, but I am not sure how to build the routine within the route.
Eg, for checking whether the reply is a 200 OK and state = INPROGRESS, I can easily introduce a Predicate. So the retryWhile already becomes like:
.retryWhile(Is200OKandINPROGRESS)
but where should I place it in the route so that the HTTP GET will be re-transmitted ?
Eg: (only taking step 4 and 5 into account)
from("...")
// here format the message to be sent out
.to("external_server")
// what code should I write here ??
// something like:
// .onException(alwaysDo.class)
// .retryWhile(Is200OKandINPROGRESS)
// .delay(2000)
// .end ()
// or maybe it should not be here ??
I am also a bit confused how the "alwaysDo.class" should look like ??
Or ... should I use something completely different to solve this orchestration ?
(I just want to re-transmit as long as I get a 200 OK with INPROGRESS state ...)
Thanks in advance for your help.

On CAMEL Nabble, someone replied my question. Check out:
http://camel.465427.n5.nabble.com/Camel-Apache-can-I-use-a-retryWhile-to-re-send-a-request-td5498382.html
By using a loop statement, I could re-transmit the HTTP GET request until I received a state different from INPROGRESS. The check on the state needs to be put inside the loop statement using a choice statement. So something like:
.loop(60)
.choice()
.when(not(Is200OKandINPROGRESS)).stop() // if state is not INPROGRESS, then stop the loop
.end() // choice
.log("Received an INPROGRESS reply on QueryTransaction ... retrying in 5 seconds")
.delay(5000)
.to(httpendpoint")
.end() //loop

I never experimented what you are trying to do but it seems does not seem right.
In the code you are showing, the retry will only occur when an alwaysDo Exception is thrown.
The alwaysDo.class you are refering to should be the name of the Java Exception class you are expecting to handle. See http://camel.apache.org/exception-clause.html for more details.
The idea should be to make the call and inspect the response content then do a CBR based on the state attribute. Either call the GET again or terminate/continue the route.

You probably should write a message to the Apache Camel mailing list (or via Nabble) . Commiters are watching it and are very reactive.

Related

Data not transferring from one endpoint to another endpoint with camel

I'm requesting to https://xx.xx.x.xxx/consumers/ domain and I'm getting some response data as JSON format, and I'm passing it another endpoint direct:consumer, but in direct:consumer endpoint if print body I'm getting empty, could anyone help me how to transfer the data from one endpoint to another endpoint.
from("timer://runOnce?repeatCount=1")
.process(consumerCreate)
.to("https://xx.xx.x.xxx/consumers/").log("response data from create:: ${body}")
.to("direct:consumer");
In the below endpoint, if print the body getting an empty response, not getting JSON data
from("direct:consumer").log("the body is ${body} ");
Can anyone please help me is it expected behaviour or am I missing something?
Take a look at enabling steam caching:
https://camel.apache.org/manual/latest/stream-caching.html
Without it, the stream returned by http producer can only be read once, e.g in the first log message. Hence why nothing is printed in the second direct:consumer route when it comes to log the message body.

Gatling: Cannot print a response from WebSocket server

I'm using the following code in Gatling:
.exec(ws("Open WS connection")
.open("/${session_id}/socket?device=other"))
.pause(2)
.exec(ws("Get client browser id")
.sendText("[]")
.check(wsListen.within(10).until(1).jsonPath("$.[2]").saveAs("clientID")))
It does not report any failure. I assume it means that the JSON value was stored in the clientID variable successfully.
When I add
.exec{
session =>
println("clientID: " + session("clientID").as[String])
session
}
I get error
[ERROR] i.g.c.a.b.SessionHookBuilder$$anon$1 - 'hook-1' crashed with 'java.util.NoSuchElementException: key not found: clientID', forwarding to the next one
This call works in JMeter.
Please help.
I guess you have to reconciliate ws branch and main branch:
https://gatling.io/docs/2.3/http/websocket/#reconciliate
As stated in the ref doc:
As a consequence, main HTTP branch and a WebSocket branch can exist in a Gatling scenario in a dissociated way, in parallel. When doing so, each flow branch has it’s own state, so a user might have to reconcile them, for example when capturing data from a WebSocket check and wanting this data to be available to the HTTP branch.

OSB12c - Rest proxy service throwing Translation error in case of invalid JSON input

We have configured REST proxy service that accepts JSON input. If the input is not a well formed JSON OSB is throwing Translation error with HTTP 500 Staus code. Is that possible we can send Customized error message in this scenario
You need to create a global error handler for your pipeline and set the desired error message using a replace action here, followed by a "Reply" action.
Keep in mind that if you try to "read" the original request body in the global error handler, and if the original request was malformed, it will get thrown up to the system error handler and you will get the system error message again.
Here's a sample OSB 12.2.1.1 project you can use to try this: https://github.com/jvsingh/SOATestingWithCitrus/tree/develop/OSB/Samples/ServiceBusApplication1
The accompanying soapui project contains two requests. The malformed request should return this:
(I have only set the response here. You would also need to set the proper content type and decide whether you want to treat this as "success" or "failure" etc. in the reply action)

AppEngine Error Handling

All,
Is there a way to error out/exit execution out of a handler? For instance, if the incoming request doesn't contain the correct headers we want to send a 400 and exit/close the connection. However, whenever we use self.error(400) or self.response.set_status(400) any other code after it executes anyway So, for example:
class MyPastaHandler(webapp2.Handler):
def get():
if not self.request.headers.get('My-Custom-Header'):
self.error(400)
...
[more code]
self.response.out.write('{"success": "true"}')
When I submit a request w/o the said custom header, I get back a 400, but I also get the success json in the body of the response, which tells me that self.error(400) doesn't stop execution and neither does self.response.set_status(400).
So, the question is, is it possible to literally error out of a handler?
As it turns out, there is a simple way to exit after a 400 (or any custom error). As described by TheFluff in the AppEngine IRC channel, a simple, old-fashioned empty return after the self.error(400) will do the trick.
In webapp2 abort() is a shortcut to raise a HTTP exception: http://webapp-improved.appspot.com/guide/exceptions.html#abort

Apache Camel: can I put multiple statements in the when part of the conditional choice statement?

I would like to obtain the following kind of routing:
HTTP POST message with XML body enters CAMEL
I store some of the parameters of the XML body
The message is routed to an external endpoint
The external endpoint (external server) replies
-> at this moment, I would like to check whether the reply from the external endpoint is a HTTP 200 OK containing a XML parameter equal to SUCCESS.
-> if so, then I would like to use some of the stored parameters to construct a new HTTP message (method = PUT this time) and send it out to an external endpoint
Problem that I am currently having, is the following:
.choice()
.when(simple("${in.headers.CamelHttpResponseCode} == 200"))
// now I want do a few things, eg: check also the XML body via xpath
// and change the message to be sent out (change Method to PUT, ...)
.to("http://myserver.com")
.otherwise()
// if no 200 OK, I want the route to be stopped ... not sure how ?
.end()
Question: any idea how to add those extra statements in case the HTTP response code was 200 OK ? It looks like the when does not allow me to add extra statements ...
(I got an error in my Eclipse IDE).
Thanks in advance.
Note: could it be that I have to route the message in case the 200 OK matches to a 'new endpoint' and then create a new from route with this new endpoint ?
Eg:
.choice()
.when(simple("${in.headers.CamelHttpResponseCode} == 200"))
.to("mynewendpoint")
.otherwise()
// if no 200 OK, I want the route to be stopped ... not sure how ?
.end();
from("mynewendpoint").
.setHeader(etc etc)
.to("http://myserver.com")
In this latter case, how exactly should I define this 'newendpoint' ?
In the programming language DSLs such as Java, you can build predicates together. I posted a blog entry some years ago about this at: http://davsclaus.blogspot.com/2009/02/apache-camel-and-using-compound.html
For example having two predicates
Predicate p1 = header("hl7.msh.messageType").isEqualTo("ORM"):
Predicate p2 = header("hl7.msh.triggerEvent").isEqualTo("001");
You can chain them together, using and or or.
Predicate isOrm = PredicateBuilder.and(p1, p2);
And then you can use isOrm in the route
from("hl7listener")
.unmarshal(hl7format)
.choice()
.when(isOrm).beanRef("hl7handler", "handleORM")
.otherwise().beanRef("hl7handler", "badMessage")
.end()
.marshal(hl7format);
yep, you can have multiple statements between the .when() and .otherwise() and you can always call .endChoice() to explicitly end each conditional block...
to your other question, you can use camel-direct to chain together multiple routes, etc...

Resources