Getting the Queue name from within the MDB - jms

I have 2 Websphere application Server(WAS) applications, one sending a message and the other reading and processing it . I need the queue name to be known in the reading application for my downstream processing.
I am trying to get the queue name (in the reading application) by using the following code . But however I get NullPointerException since the getJMSDestination is returning null.
Queue queue = (Queue)message.getJMSDestination();
logger.info("Queue ID: "+queue.getQueueName());
Note that the queue name is set via the destination object in the sending application.
Is there any other parameters that I am missing to set in the sending application ?

The message should have the destination stored in its JMSDestination property, you can try fetch that instead of using getJMSDestination()

I've using Spring with ActiveMQ, and this appears to work for me:
public void processMessage( Message msg )
{
// Get the queue name from the supplied Message.
String sourceQueueName = "UNKNOWN";
try
{
ActiveMQDestination sourceQueue = (ActiveMQDestination) msg.getJMSDestination();
sourceQueueName = sourceQueue.getPhysicalName();
}
catch ( JMSException e )
{
LOGGER.error( "Cannot get JMSDestination from Message: " + msg, e );
}
....
Does WAS have a Queue object you can cast to that exposes similar methods?

Related

Ibm Wmq - Xms .Net - Read and delete message from Queue

Greetings of the day.
Please help on the below requirement:
Requirement:
We want to delete message from MQ only after it is processed successfully.
Use event based message detection technique and avoid loop
So, to achieve above:
I have created message listener and consumer class below:
{
sessionIn = connectionIn.CreateSession(false, AcknowledgeMode.ClientAcknowledge);
// Create message listener and assign it to consumer
messageListener = new MessageListener(OnMessageCallback);
consumerAsync.MessageListener = messageListener;
Console.WriteLine("Message Listener set. Starting the connection now.");
// Start the connection to receive messages.
connectionWMQ.Start();
}
Reading the message from the call back event and push the message into other system:
OnMessageCallback(Message) {
if (xmsMessage is IBytesMessage)
{
IBytesMessage bytesMessage = (IBytesMessage)xmsMessage;
byte[] arrayMessage = new byte[bytesMessage.BodyLength];
bytesMessage.ReadBytes(arrayMessage);
string message = System.Text.Encoding.Default.GetString(arrayMessage);
}
}
Once the message processed, external system will fire the below over ride method:
Response method override:
protected override Task OnResponse(ReponseMessage message)
{
 //Read the message and get the message id and correlation id.
//Delete the message from the queue.
//I am trying to do like this, but Its not working:
messageConsumerDelete = sessionDelete.CreateConsumer(destinationDelete, query);
if (messageConsumerDelete != null)
{
IMessage m = messageConsumerDelete.Receive(1000);
LogWrite("Receive Message=" + m);
m.Acknowledge();
}
}
Please suggest a best solution for this requirement.
I am trying to find a solution for this since weeks, but no breakthrough. 
Thanks,
Balaji

Listen to another message only when I am done with my current message in Kafka

I am building a Springboot application using Spring Kafka where I am getting messages from a topic. I have to modify those messages and then produce them to another topic. I don't want to consume any other message till I have processed my current one. How can I achieve this?
#KafkaListener(
topics = "${event.topic.name}",
groupId = "${event.topic.group.id}",
containerFactory = "eventKafkaListenerContainerFactory"
)
public void consume(Event event) {
logger.info(String.format("Event created(from consumer)-> %s", event));
}
"event" is a json object which I am receiving as a message.
See https://docs.confluent.io/platform/current/installation/configuration/consumer-configs.html#consumerconfigs_max.poll.records:
max.poll.records
The maximum number of records returned in a single call to poll().
Type: int
Default: 500
With Spring Boot you can configure it as this property:
spring.kafka.consumer.maxPollRecords
So, you set it to 1 and no more records are going to be polled from this consumer until you return from your #KafkaListener method.

WebFlux/Reactive Spring RabbitmMq Message is acknowledged even the save failed

I've started working recently with spring webflux and Rabbitmq along with cassandra reactive repository. What I've noticed is that the message is acknowledged even saving in cassandra didn't succued for some element. I propagete exception thrown during saving but even though the message is take down from queue. I'm wondering what I should do to let Rabbitmq know that this message should be consider as failed (I want to reject message to send it to dead letter queue )
#RabbitListener(queues = Constants.SOME_QUEUE, returnExceptions = "true")
public void receiveMessage(final List<ItemList> itemList) {
log.info("Received message from queue: {}", Constants.SOME_QUEUE);
itemService.saveAll(itemList)
.subscribe(
item-> log.info("Saving item with {}", item.getId()),
error -> {
log.error("Error during saving item", error);
throw new AmqpRejectAndDontRequeueException(error.getMessage());
},
() -> log.info(Constants.SOME_QUEUE+
" queue - {} items saved", itemList.size())
);
}
Reactive is non-blocking; the message will be acked as soon as the listener thread returns to the container. You need to somehow block the listener thread (e.g. with a Future<?>) and wake it up when the cassandra operation completes, exiting normally if successful, or throwing an exception on failure so the message will be redelivered.
I solved my problem by sending explicitly acknowledge/reject message to rabbitmq. It caused that I was forced to wrote a little more code but now at least it works and I have full controll what's happening.

JMS Broker receives the message as null

I have a C++ component which passes message to JMS broker via tcp using ActiveMQ. My broker is written in JAVA. I want these two to communicate; to C++ component send messages to the JAVA broker.
On C++ side what I am doing is creating a message (using protocol buffer), converting that to vector of bytes and passing it to the broker. On JAVA side (broker), I am constantly listening and acting upon a received message.
Now, I can tell that the system somehow works, since when I execute my C++ component (and when it passes the messages), I see my JAVA broker printing an error message: unexpected error:null per each message that I am sending from my C++ component. This means that at least my messages do reach to the broker, but somehow they cannot be decrypted, hence the null issue.
I am using the following for composing the message from C++ side:
// convert pointmsg to byte
int size = pointmsg.ByteSize();
char* byteArray = new char[size];
pointmsg.SerializeToArray(byteArray, size);
// convert bytearray to vector
vector<unsigned char> v(byteArray, byteArray + sizeof byteArray / sizeof byteArray[0]);
// pass as a vector
BytesMessage *message = session->createBytesMessage();
message->writeBytes(v);
producer->send(message);
printf("Sent message #%d from thread %s\n", ix + 1, threadIdStr.c_str());
pointmsg is just an object that I create and fill in, and it is not null, I tested it already and it has data in it. I am converting pointmsg to byte array since this is the way to pass an object as far as I read in the documantation. And since the writeBytes() function expects a vector, I am converting the byte array into a vector. I suspect there might be some problem in this part.
On JMS side I am simply listening the upcoming messages with:
public void onMessage(final javax.jms.Message message) {
final Timer traceTimer = new Timer();
final long messageReceived = System.currentTimeMillis();
try {
if (message instanceof ActiveMQBytesMessage) {
final ActiveMQBytesMessage amqBytesMsg = (ActiveMQBytesMessage) message;
final byte[] buffer = amqBytesMsg.getContent().data;
final String msgType = amqBytesMsg.getStringProperty(LLCom.MSG_PROP_CLASS_NAME);
final String topic = amqBytesMsg.getStringProperty(LLCom.MSG_PROP_TOPIC_NAME);
String msgLookUpType;
if (topic == null || topic.isEmpty()) {
// get message class name: foo.bar$MessageMsg
msgLookUpType = msgType.split("\\$")[1];
} else {
// it's a topic we assume, that all subscribers have the
// correct type
msgLookUpType = topic;
}
if (logger.isDebugEnabled())
logger.debug("Router(" + name + ") received message ( " + buffer.length + "bytes)of type or topic " + msgLookUpType);
final Message req = parsers.createMessage(buffer, msgType);
// process explicit topic/queue subscriber
processServiceMessage(msgLookUpType, messageReceived, amqBytesMsg, req, traceTimer);
} else {
logger.error("Not supported JMS MessageType: " + message);
}
} catch (final Exception e) {
logger.error("Unexpected error: " + e.getMessage());
// e.printStackTrace();
}
}
When I debug it I can see that msgType and topic variables (on JMS side) are coming as null, which means that activemq message is somehow not decrypted. What could be the reason for that? I can see the message is being sent, received but not understood.
Any thoughts?
Update: I noticed that I am expecting to get stringProperties on JMS side, which I am not setting on C++ side, but I am not sure whether it causes the problem or not.
Ok, It seems the error was related to set properties, msgType and topic, I gave them the expected strings with using setStringProperty() on C++ side with the required methods, and now that initial error is gone.
message->setStringProperty();

Receive method in JMS waiting for messages

I want a method to browse all messages from a messsage queue and can send it to another queue using jmstemplate with using Websphere queues(NOT MQ). I have tried using receive and it is able to retrieve all the messages from the queue but it is still waiting for another message. And the messages are being lost. It must be in a transaction
The Code I have Tried:
**String message = (String) jmsTemplate.receiveAndConvert();
System.out.print(message);
while ((message = (String) jmsTemplate.receiveAndConvert()) != null) {
messages.add(message);
}
return messages;
}**
The JMStemplate should be used for only synchronous read or sending message. For asychronous read use one of the listener implementation. Read here

Resources