I need to implement "ActiveMq request response" like described at http://activemq.apache.org/how-should-i-implement-request-response-with-jms.html. The sender is written in ruby and using STOMP, the receiver is written in java and using JMS (camel).
The sender subscribes to a temporary queue and sends a message to another (static) queue with the JMSReplyTo header set to the name of the temporary queue (/temp-queue/fdc68b92-efe2-4d6f-b239-0539c4705e57, see https://activemq.apache.org/apollo/documentation/stomp-manual.html#Temporary_Destinations).
The receiver gets this message (with header JMSReplyTo=queue:///temp-queue/fdc68b92-efe2-4d6f-b239-0539c4705e57), processes it and puts the result into the reply-to queue. However the STOMP client doesn't receive anything. If I use a "normal" queue everything works fine.
How to get it working?
Ok, after lots of debugging it turns out the problem was setting the "JMSReplyTo" header directly and not the "reply-to" header.
It seems that activemq is rewriting the "reply-to" header internally as desired (to something like JMSReplyTo=temp-queue://ID:mybroker.local-42798-1516183213738-5:128503:1), but would pass "JMSReplyTo" unchanged.
Related
I'm currently writing some CAPL code that is executed when clicking a button. It shall send multiple Diagnostic Requests. But CANoe is always telling me, that it can only send one request at a time. So I need to delay the requests. The diagSetRequestInterval function did not work. And since it is NOT a testcase, the testWaitForDiagResponse doesn't work either.
You have to wait until the request has been handled (either by a response from the target or by a timeout).
Since you are not in a test node you have to give back the control to the system, i.e. your function which did diagSendRequest shall end and you wait for some events on the bus to occur before you continue (otherwise the simulation would stall).
Once the request has been handled on diagRequest ... is called. Inside this event procedure, you could send the next request and so on.
Example:
Instead of:
myFunction()
{
diagRequest ECU.ProgrammingSession req1;
diagRequest ECU.SecuritySeed req2:
diagSendRequest(req1);
diagSendRequest(req2);
}
You would do something like this:
myFunction()
{
diagRequest ECU.ProgrammingSession req1;
diagSendRequest(req1);
}
on diagResponse ECU.ProgrammingSession
{
diagRequest ECU.SecuritySeed req2:
diagSendRequest(req2);
}
Timeout handling is a different topic, and left as an exercise :-)
You practically want to implement multiple TP connection simultaneously in CANoe. I presume you have only one Diagnostic Description in the Diagnostic/ISO TP configuration, which lets you to use only 1 TP connection at a time.
You can implement multiple diag layers in Diagnostic ISO/TP on the same Communication channel, as much as you want, but with different namings.
In simulation node, you will only have to declare the request you want with a different namespace, corresponding to one of the diag layer name you earlier created.
This way you can virtualize the multiple TP connection in UDS for the CANoe environment.
OR, you do not use diagnostic layer support by CANoe, and you construct the whole message with UDS payload on your data link layer (CAN, FR).
Depends what kind of Data link layer (CAN,FR) and how many comm channels with diag layer you have set.
In Flexray, for example ,you can send multiple diag requests in the same frcycle, if your frschedule provides multiple frslots in dynamic segment which the Diaglayer (or you) can use.
I have a really simple route that GETs an URL and prints the content using Camel HTTP4 component:
from("timer://foo?fixedRate=true&delay=0&period=10000")
.to("http4://www.google.com")
.process(e -> System.out.println("Out body: " + e.getOut().getBody()));
Note that I'm using out.body because, as stated in Camel documentation:
Camel will store the HTTP response from the external server on the OUT
body. All headers from the IN message will be copied to the OUT
message, so headers are preserved during routing.
But I get null values from OUT (both body and headers). Everything is being filled only in the IN message.
Am I missing anything or is it a bug?
In Camel a route consists of nodes. Each node takes the Exchange. Exchange has an IN and OUT message. So in your case, node with http4 component took the Exchange, called google.com and wrote body and headers to OUT message. Next, node with your proccesor took the Exchange. Now IN message has the response from the previous node(http4), but you are printing OUT which is empty! So IN and OUT message are per node not per route!
You are getting the Out body from the processor without setting it up first. That’s why you get null. To make this work you first need explicitly copy the incoming message, headers and attachments to Out Body and then print it. Or more easily take the In message as you mentioned.
Next part is from “Camel in Action” book which is a great book and I think it is very helpful.
in practice there’s a common pitfall when using getOut: the incoming
message headers and attachments will be lost. This is often not what
you want, so you must copy the headers and attachments from the
incoming message to the outgoing message, which can be tedious.
I am attempting to construct a route which will do the following:
Consume a message from jms:sender-in. I am using a INOUTrequest reply pattern. The JMSReplyTo = sender-out
The above message will be routed to multiple recipients like jms:consumer1-in, jms:consumer2-in and jms:consumer3-in. All are using a request reply pattern. The JMSReplyTo is specified per consumer ( in this case, the JMSReplyTo are in this order jms:consumer1-out, jms:consumer2-out, jms:consumer3-out
I need to aggregate all the replies together and send the result back to jms:sender-out.
I constructed a route which will resemble this:
from("jms:sender-in")
.to("jms:consumer1-in?exchangePattern=InOut&replyTo=queue:consumer1-out&preserveMessageQos=true")
.to("jms:consumer2-in?exchangePattern=InOut&replyTo=queue:consumer2-out&preserveMessageQos=true")
.to("jms:consumer3-in?exchangePattern=InOut&replyTo=queue:consumer3-out&preserveMessageQos=true");
I then send the replies back to some queue to gather and aggreagte:
from("jms:consumer1-out?preserveMessageQos=true").to("jms:gather");
from("jms:consumer1-out?preserveMessageQos=true").to("jms:gather");
from("jms:consumer1-out?preserveMessageQos=true").to("jms:gather");
from("jms:gather").aggregate(header("TransactionID"), new GatherResponses()).completionSize(3).to("jms:sender-out");
To emulate the behavior of my consumers, I added the following route:
from("jms:consumer1-in").setBody(body());
from("jms:consumer2-in").setBody(body());
from("jms:consumer3-in").setBody(body());
I am getting a couple off issues:
I am getting a timeout error on the replies. If I comment out the gather part, then no issues. Why is there a timeout even though the replies are coming back to the queue and then forwarded to another queue.
How can I store the original JMSReplyTo value so Camel is able to send the aggregated result back to the sender's reply queue.
I have a feeling that I am struggling with some basic concepts. Any help is appreciated.
Thanks.
A good question!
There are two things you need to consider
Don't mix the exchange patterns, Request Reply (InOut) vs Event
message (InOnly). (Unless you have a good reason).
If you do a scatter-gather, you need to make the requests
multicast, otherwise they will be pipelined which is not
really scatter-gather.
I've made two examples which are similar to your case - one with Request Reply and one with (one way) Event messages.
Feel free to replace the activemq component with jms - it's the same thing in these examples.
Example one, using event messages - InOnly:
from("activemq:amq.in")
.multicast()
.to("activemq:amq.q1")
.to("activemq:amq.q2")
.to("activemq:amq.q3");
from("activemq:amq.q1").setBody(constant("q1")).to("activemq:amq.gather");
from("activemq:amq.q2").setBody(constant("q2")).to("activemq:amq.gather");
from("activemq:amq.q3").setBody(constant("q3")).to("activemq:amq.gather");
from("activemq:amq.gather")
.aggregate(new ConcatAggregationStrategy())
.header("breadcrumbId")
.completionSize(3)
.to("activemq:amq.out");
from("activemq:amq.out")
.log("${body}"); // logs "q1q2q3"
Example two, using Request reply - note that the scattering route has to gather the responses as they come in. The result is the same as the first example, but with less routes and less configuration.
from("activemq:amq.in2")
.multicast(new ConcatAggregationStrategy())
.inOut("activemq:amq.q4")
.inOut("activemq:amq.q5")
.inOut("activemq:amq.q6")
.end()
.log("Received replies: ${body}"); // logs "q4q5q6"
from("activemq:amq.q4").setBody(constant("q4"));
from("activemq:amq.q5").setBody(constant("q5"));
from("activemq:amq.q6").setBody(constant("q6"));
As for your question two - of course, it's possible to pass around JMSReplyTo headers and force exchange patterns along the road - but you will create hard to debug code. Keep your exchange patterns simple and clean - it keep bugs away.
Currently I'm receiving messages over tcp in a self written component that allows me to use Netty as a TCP server producer.
the messages i receive are formatted in XML style, for example:
<customheader>
<someattribute></someattribute>
</customheader>
<custombody>
</custombody>
The messages I receive are stored in a byte[] and to send it to another endpoint I create a new exchange via:
Exchange exchange = new DefaultExchange(endpoint);
exchange.getContext().createProducerTemplate().sendBody("someendpointuri", receivedbytes);
now my questions:
Is my approach with the new exchange correct?
If want to for example get rid of the header or use other camel components, do I need to convert the receivedbytes from byte[] to a different datatype or is byte[] okay?
If i want to remove the custom header can i use the remove header component from camel?
Thanks for your help
You're creating an new Exchange, but you're not actually using it. Instead, you only use it to access CamelContext. The method sendBody is creating a new Exchange for you and it is this Exchange that is actually being sent to endpoint specified by someendpointuri. Note that you should not create a new producer template every time you want to send a message.
When you say that you store messages as byte[], I assume you're storing it inside Message body. In this case you store both customheaders and custombody as byte[] and Camel treats them both as Message body, not headers.
If you want to use Camel header-related components or language constructs, you need to parse your customheaders and then set them on the Message as headers by using Exchange.getIn().setHeaders() (see API with a note about this). If you do that, you would probably only want to set content of custombody in the Exchange.getIn().setBody().
If you do these changes in your custom component, your component will now be handling this specific XML format only. If you want to keep your component generic, you can instead implement a custom DataFormat and call marshal() and unmarshal() in your routes. I think SOAP DataFormat does something very similar.
everyone, I am porting the WinPcap from NDIS6 protocol to NDIS6 filter. It is nearly finished, but I still have a bit of questions:
The comment of ndislwf said "A filter that doesn't provide a FilerSendNetBufferList handler can not originate a send on its own." Does it mean if I used the NdisFSendNetBufferLists function, I have to provide the FilerSendNetBufferList handler? My driver will send self-constructed packets by NdisFSendNetBufferLists, but I don't want to filter other programs' sent packets.
The same as the FilterReturnNetBufferLists, it said "A filter that doesn't provide a FilterReturnNetBufferLists handler cannot originate a receive indication on its own.". What does "originate a receive indication" mean? NdisFIndicateReceiveNetBufferLists or NdisFReturnNetBufferLists or both? Also, for my driver, I only want to capture received packets instead of the returned packets. So if possible, I don't want to provide the FilterReturnNetBufferLists function for performance purpose.
Another ressembled case is FilterOidRequestComplete and NdisFOidRequest, in fact my filter driver only want to send Oid requests itself by NdisFOidRequest instead of filtering Oid requests sent by others. Can I leave the FilterOidRequest, FilterCancelOidRequest and FilterOidRequestComplete to NULL? Or which one is a must to use NdisFOidRequest?
Thx.
Send and Receive
A LWF can either be:
completely excluded from the send path, unable to see other protocols' send traffic, and unable to send any of its own traffic; or
integrated into the send path, able to see and filter other protocols' send and send-complete traffic, and able to inject its own traffic
It's an all-or-nothing model. Since you want to send your own self-constructed packets, you must install a FilterSendNetBufferLists handler and a FilterSendNetBufferListsComplete handler. If you're not interested in other protocols' traffic, then your send handler can be as simple as the sample's send handler — just dump everything into NdisFSendNetBufferLists without looking at it.
The FilterSendNetBufferListsComplete handler needs to be a little more careful. Iterate over all the completed NBLs and pick out the ones that you sent. You can identify the packets you sent by looking at NET_BUFFER_LIST::SourceHandle. Remove those from the stream (possibly reusing them, or just NdisFreeNetBufferList them). All the other packets then go up the stack via NdisFSendNetBufferListsComplete.
The above discussion also applies to the receive path. The only difference between send and receive is that on the receive path, you must pay close attention to the NDIS_RECEIVE_FLAGS_RESOURCES flag.
OID requests
Like the datapath, if you want to participate in OID requests at all (either filtering or issuing your own), you must be integrated into the entire OID stack. That means that you provide FilterOidRequest, FilterOidRequestComplete, and FilterCancelOidRequest handlers. You don't need to do anything special in these handlers beyond what the sample does, except again detecting OID requests that your filter originated in the oid-complete handler, and removing those from the stream (call NdisFreeCloneOidRequest on them).
Performance
Do not worry about performance here. The first step is to get it working. Even though the sample filter inserts itself into the send, receive, and OID paths; it's almost impossible to come up with any sort of benchmark that can detect the presence of the sample filter. It's extremely cheap to have do-nothing handlers in a filter.
If you feel very strongly about this, you can selectively remove your filter from the datapath with calls to NdisFRestartFilter and NdisSetOptionalHandlers(NDIS_FILTER_PARTIAL_CHARACTERISTICS). But I absolutely don't think you need the complexity. If you're coming from an NDIS 5 protocol that was capturing in promiscuous mode, you've already gotten a big perf improvement by switching to the native networking data structures (NDIS_PACKET->NBL) and eliminating the loopback path. You can leave additional fine-tuning to the next version.