I want to delay message delivery by certain time which will be different for each message.
I referred weblogic 10.3 WLMessage documentation which recommends using javax.jms.Message.getIntProperty("JMS_BEA_DeliveryTime").
However I'm unable to figure out how do I set JMS_BEA_DeliveryTime as INTEGER. I was expecting it to be long.
I'm unable to find out any documentation about this attribute JMS_BEA_DeliveryTime to undesratand how to set and use it. Can anybody give example about how to set the desired delivery time or link to documenation of use of this attribute.
My code looks like typical use of Spring JMS template:
jmsTemplate.send(destination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
TextMessage message = session.createTextMessage(textMessage);
return message;
}
});
I was wondering if it is possible to set header for delivery time before returning message.
Good article with examples of delaying delivery for different JMS providers, include WL.
Well there is this page which states
JMS Delivery Time: The earliest absolute time at which
a message can be delivered to a consumer.
It should be trivial to set with Message.setIntProperty(...), there is not much mention as to what the time actually constitutes though, although I did find this article which suggests milliseconds from now.
Hope that helps.
Related
Using spring-camel, I have built a route that consumes from a JMS topic (with JMSReplyTo expected to be set for each input message), splits the message into smaller chunks, sends them to a REST processsor, then aggregates the answers and should produce an output message to the destination pointed by JMSReplyTo. Unfortunately, camel implicitly utilises the JMSReplyTo destination in one of the intermediate steps (producing an unmarshalled POJO).
We have a functional requirement to adapt JMSReplyTo in order to provide a request-reply messaging service.
I am able to read the JMSReplyTo header before ending the route and I am explicitly converting it to CamelJmsDestinationName, which successfully overrides the destination for JMS component and produces the message on the output topic. I am not sure if this is the best approach and the problem is that camel still utilises the JMSReplyTo on its own.
My RouteBuilder configuration is as follows:
from("jms:topic:T.INPUT")
.process(requestProcessor)
.unmarshal().json(JsonLibrary.Jackson, MyRequest.class)
.split(messageSplitter)
.process(restProcessor)
.aggregate(messagesAggregator)
.unmarshal().json(JsonLibrary.Jackson, BulkResponses.class)
.process(responseProcessor)
.to("jms:topic:recipientTopic");
T.INPUT is the name of the input topic, while recipientTopic is just a placeholder that will be replaced by CamelJmsDestinationName.
I'm not keen on using CamelJmsDestinationName and a sort of a mocked up topic name in route configuration so I'm open to find a better solution. It would be great if camel utilised the JMSReplyTo automatically to produce the output message to the output topic.
Currently, the problem is that camel produces an intermediate output on the JMSReplyTo topic BUT the output is an unmarshalled MyRequest object, which results in an exception saying "ClassNotFoundException: (package name).MyRequest", which is obvious since this is only a class used in my internal processing - I don't want to produce this to the output topic. It seems like Camel does implicitly use the JMSReplyTo destination between requestProcessor and messageSplitter processing... Why? What am I doing wrong? What are the best practices?
Use "disableReplyTo=true" in Endpoint. Camel will not try to use any reply option.
Refer: https://camel.apache.org/jms.html for more details
I have found the answer... this is absurdly easy but I haven't seen it anywhere in the documentation.
You just need to call .stop() to mark the route as completed, and Camel will reply the body you configured in the last step to the destination configured in ${header.JMSReplyTo}. It's that simple.
So you can do:
from("jms:my-queue")
.unmarshall().json(JsonLibrary.Jsonb, InboundMessage.class)
.bean(SomeProcessingBean.class)
....
.log(LoggingLevel.INFO, "Sending reply to: " + simple("${header.JMSReplyTo}").getExpression().toString())
.marshall().json(JsonLibrary.Jsonb, ReplyMessage.class)
.stop();
And you will receive reply.
I wonder why no one has found this before... Nothing when I search the doc or here.... I must be dumb, or the doc is incomplete...but I am not dumb, so.
I have different problems with a Camel Producer that I tried to solved but I've fallen into other problems.
1) The first implementation I did was to create a producer template each time we needed to communicate with an ActiveMQ topic. That resulted with poor memory results leading to server crashing after sometime.
The solution for the memory problem was to stop() producer template after each request. That fix has corrected the memory issue but cause some latency problem.
2) I read somewhere that it's not necessary to create each time a producer template. So I decide to fix the latency problem and declared only one producer template in my class and use it for each request. It seem to work fine, no memory leak, fix the latency problem...
BUT, when we send multiple queries that take a lot of time (20 sec each), it looks like we hit a timeout and the component crash with something like «javax.jms.IllegalStateException: The Session is closed».
Is there a way to do multi threading? Is this cause by using InOut exchange pattern? How the MAXIMUM_CACHE_POOL_SIZE works? Is my implementation is right?
I've put a sample of the code of my component:
public void process(Exchange exchange) throws Exception
{
Message in = exchange.getIn();
if (producerTemplate == null) {
CamelContext camelContext = exchange.getContext();
//camelContext.getProperties().put(Exchange.MAXIMUM_CACHE_POOL_SIZE, "50");
producerTemplate = camelContext.createProducerTemplate();
}
...
result = producerTemplate.sendBody(String.format("activemq:%s", camelContext.resolvePropertyPlaceholders("{{channel1}}")), ExchangePattern.InOut, messageToSend).toString();
...
finalResult = producerTemplate.sendBody(String.format("activemq:%s", camelContext.resolvePropertyPlaceholders("{{channel2}}")), ExchangePattern.InOut, result).toString();
...
in.setBody(finalResult );
}
Yes it is because you use InOut pattern.
Your route expects a response to the specified reply queue, which is never received, and therefore results in the default 20 sec. timeout.
Change the Exchange pattern to InOnly to resolve your issue.
Apart from that, your posted code seems to be fine.
The MAXIMUM_CACHE_POOL_SIZE is used internally in Camel, and thus does not effect the ActiveMQ endpoint settings.
I'm building a client for trading with a remote server using FIX protocol and QuickFix/J API.
I can send order, receive price updates, cancel orders etc...
I'm asked now to "query API for current position of an instrument".
So let's say I can submit an order for buying an instrument, and it doesn't get executed, I would like to receive from the server some information like "you are LONG on intrument X with quantity Y etc".
Is it possible using QuickFix/J API?
I have written a method like this
static void positionReport() throws SessionNotFound{
quickfix.fix50.PositionReport order = new quickfix.fix50.PositionReport();
SessionID sessionId = (SessionID) initiator.getSessions().get(0);
order.set(new Account("1005390"));
order.set(new SecurityID("4663789"));
order.set(new SecurityExchange("XETR"));
order.set(new Symbol("SAP"));
Session.sendToTarget(order, sessionId);
}
which sends FIX messages like this
8=FIX.4.29=9835=AP34=4949=HIQ6_ORDER52=20140324-
15:54:10.14256=HIQFIX1=100539048=466378955=SAP207=XETR10=199
and receives messages like this:
8=FIX.4.29=9935=334=6949=HIQFIX52=20140324-15:54:10.89156=HIQ6_ORDER45=4958=Invalid
MsgType372=AP373=1110=242
As you can see I get "Invalid message" error
Check your counterparty's documentation.
FIX is a fairly "dumb" protocol. It just provides a communication infrastructure. The default message definitions are best thought of as a list of suggested messages that you can use. Even if one message type is supported by two counterparties, it's possible that each of the two counterparties could use it in totally different ways.
Most connection providers only use a subset of these messages. You should check their documentation to see if they support the PositionRequest message, and to see how they want you to set the fields in it.
No you cannot do that using Quickfix, unless and until the counterparty is modelled to give you FIX acknowledgements to your specific liking. That is why you can add your customized FIX fields to the FIX XML config file.
373 tag says 11 -> 11 = Invalid MsgType
58 confirms it for you again.
Check your FIX XML config and check if your message is complete and if your counterparty allows the messages of type AP.
We are using Camel fluent builders to set up a series of complex routes, in which we are using dynamic routing using the RecipientList functionality.
We've encountered issues where in some cases, the recipient list contains a messaging endpoint that doesn't exist (for example, something like seda:notThere).
A simple example is something like this:
from("seda:SomeSource")....to("seda:notThere");
How can I configure the route so that if the exchange tries to route to an endpoint that doesn't already exist, an error is thrown?
I'm using Camel 2.9.x, and I've already experimented with the Dead Letter Channel and various Error Handler implementations, with (seemingly) no errors or warnings logged.
The only logging I see indicates that Camel is (attempting to) send to the endpoint which doesn't exist:
2013-07-03 16:07:08,030|main|DEBUG|o.a.c.p.SendProcessor|>>>> Endpoint[seda://notThere] Exchange[Message: x.y.Z#293b9fae]
Thanks in advance!
All endpoints behave differently in this case.
If you attempt to write to a ftp server that does not exist, you certainly get an error (connection refused or otherwise)..
This is also true for a number of endpoints.
SEDA queues gets created if the do not exist and the message will be left there. So your route actually sends to "notThere" and the message will still be there until the application restarts or someone starts to consume messages from seda:notThere. This is the way seda queues are designed. If you set the size of the seda queue by to("seda:notThere?size=100"), then if there is noone reading (or reading slowly) you will get exceptions on message 101 and forward.
If you need to be sure some route is consuming your messages, use "direct" instead of "seda". You can even have some middle layer to use the features of seda with respect to staging and the features of direct knowing there is a consumer active (if sent from recipient list with perhaps user input (god forbid).
from("whatever").recipentList( ... ); // "direct:ep1" work, "direct:ep2" throws exception
from("direct:ep1").to("seda:ep1");
from("seda:ep1").doRealStagedStuffHere();
Is there a way to get notified when a JMS Message is consumed from a JMS queue? Like a listener or notification?
Thanks
I assume you are using ActiveMQ since you tagged the question with it.
You can register for an advisory notification when a message is consumed by a client. See the docs for advisories and the one you're looking for is ActiveMQ.Advisory.MessageConsumed.Queue.
===== Update =====
Oh, errr.. you're using Joram, not ActiveMQ. It's not as simple, but you could use a client side interceptor which will return an acknowledgement message back to a queue or a topic which you would then listen on. The interface looks like this:
public interface MessageInterceptor {
public void handle(javax.jms.Message pMessage, javax.jms.Session pSession);
}
See chapter 3.5. Message interceptors of the latest Joram doc PDF.
You could also use a interceptor_out server side interceptor.
No the JMS API doesnt provide any way to message delivery notification options. This will have to be done at the application level.