In QuickFix/J we can send a ResendRequest message to the Acceptor to request messages to be resent to the Initiator, within a given MsgSeq number range. For example:
Session session = Session.lookupSession(new SessionID("FIXT.1.1:SENDER->TARGET"));
session.send(new ResendRequest(new BeginSeqNo(1), new EndSeqNo(0)));
This message will request all existing Execution Reports for any open orders in the Acceptor.
The issue we have is that these messages come with PossDupFlag set to Y in the header. QuickFix/J by default ignores these messages and doesn't call the fromApp callback. I found that the callback is called if we set
ValidateSequenceNumbers=Y
but, as per the documentation, it has a drawback
If not enabled and a mismatch is detected, nothing is done.
I was wondering:
is there a different way for these messages to be processed by the callback?
if there is no other way what are the consequences of setting ValidateSequenceNumbers=Y? Is it just detect the sequence number mismatch ourselves?
Thanks
After some digging around I found a solution for this problem. Basically, we need to tell QuickFix/J that our target MsgSeqNum is 1. The logic will detect that the actual target's MsgSeqNum is higher than the one we have set and it will send a ResendRequest to the Acceptor:
Session session = Session.lookupSession(new SessionID("FIXT.1.1:SENDER->TARGET"));
session.setNextTargetMsgSeqNum(1);
In this case, the fromApp callback is called even though the PosDupFlag is set in the messages.
Related
Our system has configured to consume and send reply to the same queue, i.e., JMSDestination and JMSReplyTo are the same. I cannot change that right now.
In my integration test, if I set replyToSameDestinationAllowed=true, Camel continues to consume the reply I sent to the queue, i.e., it "captures" the source and never stop and enters a loop.
But, if I don't set it, Camel refuses to send the reply to the queue, saying this:
JMSDestination and JMSReplyTo is the same, will skip sending a reply message to itself
That causes problem for my integration test. I want to consume the message in a separate method and assert against it.
How can I stop Camel from capturing this queue, i.e., consuming only once and ignore the rest?
At the end of my route I call stop() to send reply automatically.
When receiving the second message(the reply), I see this line:
2023-01-10 14:37:22,186 DEBUG [org.apa.cam.com.jms.EndpointMessageListener]-{Camel (camel-1) thread #19 - JmsConsumer[my.queue]}-Received Message has JMSCorrelationID [ID:hostname-1673354133272-4:1:1:10:1]
Can I use this to ignore the reply? Should I stop the route? Rollback? Or what should I do?
At last I filtered out messages based on the presence of JMSCorrelationID header.
from("activemq:xxx")
.filter(simple("${header.JMSCorrelationID} == null")) // ignore reply
.to("direct:main");
Even that I don't set it in my client side code, seems that Camel will use message id to set JMSCorrelationID when sending reply if the incoming message hasn't it. If incoming message already has JMSCorrelationID, Camel will not change it, and will copy that value to the reply.(I guess that if you manually set JMSCorrelationID in client side, Camel will stop setting it for you).
So basically, message without JMSCorrelationID means it's new message which hasn't passed through my client application. I think only client side should set it, especially in my case where original message and replies are put into the same queue, where client needs a mean to filter out replies.
Also, I find that receiving can specify a message collector stating the field you want to filter. For example:
QueueReceiver receiver = jmsSession.createReceiver(myQueue, "JMSCorrelationID='" + correlationId + "'");
This is useful when you know the correlationId. But in my case (#QuarkusIntegrationTest which is a black box test), this cannot be used.
But after doing that, in my integration test Camel still "captures" the consuming and will not let another method to consume the message properly(the other method never receives anything) when I run the whole test class(with other test cases); when running individually, this test case passes. So at last I disabled the test case.
Seems that after filtering out the message, Camel behaves exactly same as if I called .stop(), executing the callback (sending reply); and will send the original message to reply queue, in my case, the original queue, so it's looping and never let go. Even I enable duplicate check, it still captures.
At the very last, we separate the queues so even capturing is happening, it does not matter any more.
I have a problem concerning receiving messages (I use #ManagedService). I use the same connection to send and receive messages between browser and my Java program. I can see that all the messages pass through ManagedAtmosphereHandler.message(AtmosphereResource resource, Object o) method.
If it is an incoming message, Atmosphere iterates through all methods marked #Message. Then it tries to find a decoder and eventually invokes correct method.
For outgoing messages, Atmosphere retrieves invoked method. It does so by getting localAttribute named "ManagedAtmosphereHandler" (name of current class). It is present only for outgoing messages. Then the message is encoded and send to browser.
The problem is, sometimes invokedMethod is set for incoming messages. It results in treating my incoming messages as outgoing. Does anybody know why it happens? My outgoing messages are scheduled and I suppose that's the reason why it happens, but I'm not sure. When are these localAttributes set and what are they for?
I updated Atmosphere 2.3.0-RC6 to 2.3.0 and it works like a charm now.
I'm trying to build a custom mq exit to archive messages that hit a queue. I have the following code.
class MyMqExits implements WMQSendExit, WMQReceiveExit{
#Override
public ByteBuffer channelReceiveExit(MQCXP arg0, MQCD arg1, ByteBuffer arg2) {
// TODO Auto-generated method stub
if ( arg2){
def _bytes = arg2.array()
def results = new String(_bytes)
println results;
}
return arg2;
}
...
The content of the message (header/body) is in the byte buffer, along with some unreadable binary information. How can I parse the message (including the body and the queue name) from arg2? We've gone through IBM's documentation, but haven't found an object or anything that makes this easy.
Assuming the following two points:
1) Your sender application has not hard coded the queue name where it puts messages. So you can change the application configuration to send messages to a different object.
2) MessageId of the archived message is not important, only message body is important.
Then one alternative I can think of is to create an Alias queue that resolves to a Topic and use two subscribers to receive messages.
1) Subscriber 1: An administratively defined durable subscriber with a queue provided to receive messages. Provide the same queue name from which your existing consumer application is receiving messages.
2) Subscriber 2: Another administratively defined durable subscriber with queue provided. You can write a simple java application to get messages from this queue and archive.
3) Both subscribers subscribe to the same topic.
Here are steps:
// Create a topic
define topic(ANY.TOPIC) TOPICSTR('/ANY_TOPIC')
// Create an alias queue that points to above created topic
define qalias(QA.APP) target(ANY.TOPIC) targtype(TOPIC)
// Create a queue for your application that does business logic. If one is available already then no need to create.
define ql(Q.BUSLOGIC)
// Create a durable subscription with destination queue as created in previous step.
define sub(SB.BUSLOGIC) topicstr('/ANY_TOPIC') dest(Q.BUSLOGIC)
// Create a queue for application that archives messages.
define ql(Q.ARCHIVE)
// Create another subscription with destination queue as created in previous step.
define sub(SB.ARCHIVE) topicstr('/ANY_TOPIC') dest(Q.ARCHIVE)
Write a simple MQ Java/JMS application to get messages from Q.ARCHIVE and archive messages.
A receive exit is not going to give you the whole message. Send and receive exits operate on the transmission buffers sent/received by channels. These will contain various protocol flows which are not documented because the protocol is not public, and part of those protocol flows will be chunks of the messages broken down to fit into 32Kb chunks.
You don't give enough information in your question for me to know what type of channel you are using, but I'm guessing it's on the client side since you are writing it in Java and that is the only environment where that is applicable.
Writing the exit at the client side, you'll need to be careful you deal with the cases where the message is not successfully put to the target queue, and you'll need to manage syncpoints etc.
If you were using QMgr-QMgr channels, you should use a message exit to capture the MQXR_MSG invocations where the whole message is given to you. If you put any further messages in a channel message exit, the messages you put are included in the channel's Syncpoint and so committed if the original messages were committed.
Since you are using client-QMgr channels, you could look at an API Exit on the QMgr end (currently client side API Exits are only supported for C clients) and catch all the MQPUT calls. This exit would also give you the MQPUT return codes so you could code your exit to look out for, and deal with failed puts.
Of course, writing an exit is a complicated task, so it may be worth finding out if there are any pre-written tools that could do this for you instead of starting from scratch.
I fully agree with Morag & Shashi, wrong approach. There is an open source project called Message Multiplexer (MMX) that will get a message from a queue and output it to one or more queues. Context information is maintained across the message put(s). For more info on MMX go to: http://www.capitalware.com/mmx_overview.html
If you cannot change the source or target queues to insert MMX into the mix then an API Exit may do the trick. Here is a blog posting about message replication via an API Exit: http://www.capitalware.com/rl_blog/?p=3304
This is quite an old question but it's worth replying with an update that's relevant to MQ 9.2.3 or later. There is a new feature called Streaming Queues (see https://www.ibm.com/docs/en/ibm-mq/9.2?topic=scenarios-streaming-queues) and one of the use-cases it is designed to support is putting a copy of every message sent to a given queue, to an alternative queue. Another application can then consume the duplicate messages and archive them separately to the application that is processing the original messages.
Context:
I am working on a piece of Java code where I am reading mails from an array (which works fine). I was wondering if someone can help me with the callback in order to show a fancy message like Your email was sent.
Questions:
How do I implement this?
Is there any way to get any Boolean type return value from javax.mail to check if the message was sent or not?
Maybe I should create a pool? If yes, how do I do that? Is there any signal to kill the pool?
Code:
// addressTo is the array.
Transport t = sesion.getTransport(this.beanMail.getProtocolo());
t.connect(this.beanMail.getUsuario(), this.beanMail.getPassword());
t.sendMessage(mensaje, addressTo);
t.close();
Quoting from the JavaMail API FAQ (in the context of tracking bounced messages):
While there is an Internet standard for reporting such errors (the multipart/report MIME type, see RFC1892), it is not widely implemented yet. RFC1211 discusses this problem in depth, including numerous examples.In Internet email, the existence of a particular mailbox or user name can only be determined by the ultimate server that would deliver the message. The message may pass through several relay servers (that are not able to detect the error) before reaching the end server. Typically, when the end server detects such an error, it will return a message indicating the reason for the failure to the sender of the original message. There are many Internet standards covering such Delivery Status Notifications but a large number of servers don't support these new standards, instead using ad hoc techniques for returning such failure messages. This makes it very difficult to correlate a "bounced" message with the original message that caused the problem. (Note that this problem is completely independent of JavaMail.)
Source
What would be a nice and good way to temporarily disable a message listener? The problem I want to solve is:
A JMS message is received by a message listener
I get an error when trying to process the message.
I wait for my system to get ready again to be able to process the message.
Until my system is ready, I don't want any more messages, so...
...I want to disable the message listener.
My system is ready for processing again.
The failed message gets processed, and the JMS message gets acknowledged.
Enable the message listener again.
Right now, I'm using Sun App Server. I disabled the message listener by setting it to null in the MessageConsumer, and enabled it again using setMessageListener(myOldMessageListener), but after this I don't get any more messages.
How about if you don't return from the onMessage() listener method until your system is ready to process messages again? That'll prevent JMS from delivering another message on that consumer.
That's the async equivalent of not calling receive() in a synchronous case.
There's no multi-threading for a given JMS session, so the pipeline of messages is held up until the onMessage() method returns.
I'm not familiar with the implications of dynamically calling setMessageListener(). The javadoc says there's undefined behavior if called "when messages are being consumed by an existing listener or sync consumer". If you're calling from within onMessage(), it sounds like you're hitting that undefined case.
There are start/stop methods at the Connection level, if that's not too coarse-grained for you.
Problem solved by a workaround replacing the message listener by a receive() loop, but I'm still interested in how to disable a message listener and enable it shortly again.
That looks to me like the messages are being delivered but nothing is happening with them because you have no listener attached. It's been a while since I've done anything with JMS but don't you want to have the message sent to the dead letter queue or something while you fix the system, and then move the messages back onto the original queue once you're ready for processing again?
On WebLogic you can set up max retries, an error queue to handle messages that exceed the max retry limit, and other parameters. I'm not certain off the top of my head, but you also might be able to specify a wait period. All this is available to you in the admin console. I'd look at the admin for the JMS provider you've got and see if it can do something similar.
In JBoss the following code will do the trick:
MBeanServer mbeanServer = MBeanServerLocator.locateJBoss();
ObjectName objName = new ObjectName("jboss.j2ee:ear=MessageGateway.ear,jar=MessageGateway-EJB.jar,name=MessageSenderMDB,service=EJB3");
JMSContainerInvokerMBean invoker = (JMSContainerInvokerMBean) MBeanProxy.get(JMSContainerInvokerMBean.class, objName, mbeanServer);
invoker.stop(); //Stop MDB
invoker.start(); //Start MDB
I think you can call
messageConsumer.setMessageListener(null);
inside your MessageListener implementation and schedule the reestablishment task (for example in ScheduledExecutorService). This task should call
connection.stop();
messageConsumer.setMessageListener(YOUR_NEW_LISTENER);
connection.start();
and it will be working. start() and stop() methods are used for restarting delivery structrues (not TCP connection).
Read the Javadoc https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html#stop--
Temporarily stops a connection's delivery of incoming messages. Delivery can be restarted using the connection's start method. When the connection is stopped, delivery to all the connection's message consumers is inhibited: synchronous receives block, and messages are not delivered to message listeners.
For temporarily stops a connection's delivery of incoming messages you need to use stop() method from Connection interface: https://docs.oracle.com/javaee/7/api/javax/jms/Connection.html#stop--
Just don't call connection.stop() from MessageListener because according to JMS spec. you will get deadlock or exception. Instead you can call connection.stop() from different thread, you just need to synchronize MessageListener and thread that going to suspend connection with function connection.stop()