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.
Related
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)
Usecase: I would like to pick messages from an http end point and route them to a jms endpoint.
My route configuration looks like:
from("jetty:http://0.0.0.0:9080/quote")
.convertBodyTo(String.class)
.to("stream:out")
.to(InOut, "wmq:queue:" + requestQueue +
"?replyTo=" + responseQueue +
"&replyToType=" + replyToType +
"&useMessageIDAsCorrelationID=true");
My understanding is that this way I will get a request-response pattern for the JMS endpoint and correlationId would be the unique identifier to make the response to the corresponding request.
This works well when I have only 1 instance of the application running however when I have more than 1 instances running simultaneously, responses are picked up randomly and not only by the producer.
For example, A and B are 2 instances of the route (and listener) with exact same configuration listening for responses on a shared queue. At times A gets its response but at times it also picks up response for the message produced by B.
Appreciate any help/pointers on this. Thanks!
Basically the issue was with the use of replyToType which was set to Exclusive - this resulted in listener picking up everything instead of using jms selectors to match correlation ids.
I changed the value of replyToType to Shared and its all working fine now.
This is well defined in section "Request-Reply over JMS" at http://camel.apache.org/jms.html
When I run a fetch command UID FETCH 170930:170930 BODY[] I get the response 88924 FETCH (UID 170920 FLAGS (\Seen)). I wasn't expecting to retrieve a message with a UID out of the range specified. Is this normal IMAP behaviour? The 170930 UID came from watching the folder with an IdleManager only moments earlier, so I have no reason to believe that a message with that UID doesn't exist on the server.
The fetch request I've posted here is a guess based on the Java code I'm using to execute it. At the very least it should still be requesting only messages within that range:
Argument args = new Argument();
args.writeString(Long.toString(start) + ":" + Long.toString(end));
args.writeString("BODY[]");
Response[] r = protocol.command("UID FETCH", args);
Response response = r[r.length - 1];
An IMAP server is required to send you FETCH responses in certain cases. Sometimes the server is required to wait with responses, but it's never required not to send you any.
If you send a command that requires two response, and someone else does something that requires one response to you, then you get three responses. That something might be to change the flag on a message (requires FETCH ... FLAGS ... to you, although there's no promptness requirement) or send you some mail (requires EXISTS to you).
Solution:
int session = (int)get_env(argv, SESSION_ID); to get identifier unique to connection
US_VHOST_DATA (vhost) or US_HANDLER_DATA (listener) or US_SERVER_DATA (server) for data persistent > current connection
Missing pieces:
either persistent data for connection only
or some way to execute code when current connection is closed by client (econnreset etc.) or server (e.g. kalive_tmo reached)
This should be solvable as soon as a new HDL_BEFORE_CLOSE state for handlers is added, which makes this question answered for me.
Original Question:
Is it possible in a G-WAN handler to store information persistent to a request/connection (don't really know if "request" applies here)?
To better illustrate what I mean, this is what I got now:
Client (browser, javascript) sends websocket handshake
Handler starts, gets into:
HDL_AFTER_ACCEPT - here i call gc_init for US_REQUEST_DATA, and get no error
HDL_AFTER_READ - here i check for US_REQUEST_DATA which is not yet set, so I do websocket handshake and gc_malloc + set US_REQUEST_DATA, increase KALIVE_TMO, and then return 2 to send data
Client sees websocket connection as being established, so I (manually triggered some seconds afterwards) send a message
Handler goes to HDL_AFTER_READ again, BUT US_REQUEST_DATA is not set
What I've also tried:
returning 1 instead of 2 in HDL_AFTER_READ -> client gets 404 and handshake does not work
At the moment I'm only using US_REQUEST_DATA to identify if websocket connection is already established and next incoming data should be in websocket message format, so if there is a different (maybe better?) solution, I'm open to that as well of course.
Thanks!
Edit: Added clarification about request/connection
I am not sure why US_REQUEST_DATA does not seem to keep your allocated block of memory.
Can you try the persistence.c example to see if it works as expected for you?
Other than G-WAN persistent pointers, you can use OS services like the Linux shared memory API, etc.
But the G-WAN API should work fine once you copy & paste the example above.
Other values have different scopes:
US_VHOST_DATA (scope:vhost)
US_HANDLER_DATA (scope:listener)
US_SERVER_DATA (scope:server)
Use the session ID below which is unique to each CONNECTION:
int session = (int)get_env(argv, SESSION_ID);
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.