unable to de-queue previous messages from a queue - java

I am creating an chat app with android and spring using stomp over websocket. when i send more than one message to a specific client, it shows only the last message from the queue not all the previous messages. I want to see all the messages will from the queue.
Client side:
mStompClient =Stomp.over(WebSocket.class, "url");
mStompClient.connect();
mStompClient.topic("/topic/queue"+clientid).subscribe(topicMessage -> {
textView.setText(topicMessage.getPayload());
});
Server side:
#MessageMapping("/chat")
#SendTo("/topic/queue")
public String sendMessage(String msg) {
simpMessagingTemplate.convertAndSend("/topic/queue"+clientid,msg );
return "";
}

In my vision, you should persist the data which sent before, then append the new incoming messages from the queue and feed data store asynchronously.
Step: User opens chat windows, then get data from database.
Step: Send message to queue and consumers should listen the queue and feed new message to chat window and data store.
Step: If user exit from application, No matter what happened. You can present data from data store.

Related

JMS send same message back to SQS

I am working on an approach where i am required to send a message back to SQS.
I don't want it to go as a new message as that will reset the approximateRecieveCount parameter which is required by the code.
Please note that
I cannot send a NACK to the queue as i am reading it as a batch of 10 messages, I want to manually post it back in certain cases for individual message and not as a batch.
The code I am trying to use
I tried setting the JMSMessageId but it is not possible as according to the documentation -
After you send messages, Amazon SQS sets the following headers and properties for each message:
JMSMessageID
JMS_SQS_SequenceNumber (only for FIFO queues)
The code i am using right now is
defaultJmsTemplate.send(destinationName, new MessageCreator() {
#Override
public Message createMessage(Session session) throws JMSException {
Message message = session.createTextMessage(errorMessage);
message.setJMSCorrelationID(transactionId);
if (destinationName.endsWith(".fifo")) {
message.setStringProperty("JMSXGroupID", property.getMessageGroup());
message.setStringProperty("JMS_SQS_DeduplicationId", java.util.UUID.randomUUID().toString());
}
return message;
}
});
}
Is there anything that i can set/use to make sure the message is not treated as a new message and the approximate receive count is maintained?
Yes. This can be done. As you are using JMS for SQS while setting up your consumer you can define an UNORDERED_ACKNOWLEDGE mode in your consumer session. By doing so if you do not acknowledge a particular message it will be redelivered after its visibility timeout expires and the approximateRecieveCount will be incremented. This will not impact your other messages in the same batch. One downside of this is if you are using the fifo queue and the all your messages have same group id then you next message will only be processed after this unacknowledged message ends up in dead letter queue. This will only happen after your message is retried for the Maximum Receives that you have set up in fifo queue configuration. Note : The key here is to not acknowledge a particular message.

How to send multiple emails using Amazon SQS and SNS?

In my JAVA application, I'm using Amazon SQS and SNS; I did the below steps:
Step 1: I pushed the message to SQS like,
SendMessageResult aSendMessageStatus = Amazon_SQS_Client.sendMessage(new SendMessageRequest().withQueueUrl(AWS_SQS_URL).withMessageBody(theRequestString));
Step 2: Created topic in SNS like,
CreateTopicResult createRes = Amazon_SNS_Client.createTopic(createReq);
Step 3: Now I am trying to send email by receiving the messages from SQS to 100 of customer.
Can someone advice me on how to subscribe the topic in SNS and send the emails to multiple email addresses.
For SNS to deliver the message, the 100 email address would have to subscribe to the topic. The email address will get confirmation message which they will have to respond to.
For your scenario, another option could be to use the queue service. It can be done in multiple ways. I have a setup as follows:
An application component sends a message to a queue
Another application component polls the queue, retrieves the message
From the message an email is composed and use SES service to deliver emails.
Another option is to use SNS -> SQS -> SES setup, where initial notification goes to SNS, and SNS delivers the notification to SQS.
The notification message itself need not be the complete email message. It could be just a reference to the content and people to which the content is to be delivered. Your application could take care of forming the complete message.
For a scenario where email is delivered to a general application user, I think SES is the right solution rather than SNS.

Smack chats creating two threads

I'm having trouble establishing a proper chat in the Smack messaging library for Java. It works just fine if the chat was started locally, but if the chat is started from another client then two different chat threads are created, instead of just the one that is needed. My code for sending a message is below:
public void sendMessage(String input) throws XMPPException
{
Chat chat = connection.getChatManager().getThreadChat("test#server");
if(chat != null)
{
System.out.println("Chat exists!");
chat.addMessageListener(messageListener);
}
else
{
System.out.println("Create new chat");
chat = connection.getChatManager().createChat("test#server", "test#server", messageListener);
System.out.println(chat.getThreadID());
}
chat.sendMessage(input);
}
Below I have my listener class which processes incoming messages. It is originally set up when the program is initialized so that messages can be recieved straight after log in, and chats established. It is also called by the messageListener variable in the sendMessage function you can see above.
class MyMessageListener implements MessageListener {
#Override
public void processMessage(Chat chat, Message message) {
String from = message.getFrom();
String body = message.getBody();
System.out.println(chat.getThreadID());
System.out.println(String.format("Received message '%1$s' from %2$s", body, from));
}
}
I'm very new to the Smack library and finding the available documentation and examples a bit vague. Anyone have any pointers as to how I could check if a chat was created on another client and somehow fetch the thread ID of this chat or find a chat object from the ChatManager by knowing the name of the user that sent the message?
You need to register a ChatManagerListener to listen for incoming chats, as described in the Incoming Chats section in documentation. A listener on a chat created this way will receive the incoming messages, assuming they are responding with the same thread id (not all clients use a thread id).
By the way, you are looking up an existing chat by thread, but that is not a the thread id of an incoming chat. The code snippet you have shown will only match on the chat that you have created yourself, so there is no point in setting the message listener every time you are going to send a message, you may as well just hold a reference to it once it is create.
You will have to retrieve the thread id from the incoming chat to have this work properly, and that is assuming that the incoming chat actually has a chat id.

WebSphere MQ Acknowledgement and Reply-To Queue

We are sending XML text messages via a remote queue definition CLIENT.DATA (transmit queue, send/recv channels etc.) from our queue manager QM_MINE queue manager QM_CLIENT and queue CLIENT.DATA. The message reaches the destination (CLIENT.DATA queue at the client's). The problem at hand is to able to receive acknowledgement messages (exact copy of the message sent) on a local queue CLIENT.DATA.ACK in QM_MINE as soon as messages reaches CLIENT.DATA in QM_CLIENT automatically.
I found couple of resources at WebSphere v7.1 infocenter on reply-to queue and message acknowledgement however they were not really helpful to me.
So far I tried to use the reply to queue way. I created a transmit queue QM_MCT on QM.OCC. Every message I send to the CLIENT.DATA queue, I specified the reply-queue using setJMSReplyTo() method. However I am sure that is not it, there is more I am missing.
MQ Objects Summary:
QM_MINE: CLIENT_DATA (remoteQ), QM_CLIENT (transmitQ), CLIENT_DATA_ACK(localQ)
QM_CLIENT: CLIENT_DATA (localQ), QM_MINE (transmitQ),
And, sender/receiver channels at both ends.
Source Code Fragements:
Client Data Sender (under transaction):
public class ClientServiceImpl extends JmsGatewaySupport implements ClientService {
#Override
public void sendClientData(String dataXML) {
getJmsTemplate().convertAndSend(dataXML);
}
}
Message Converter :
public Message toMessage(Object o, Session session) throws JMSException, MessageConversionException {
String dataXML = (String) o;
TextMessage message = session.createTextMessage();
message.setJMSReplyTo(replyToQueue);
message.setText(dataXML);
return message;
}
Note:
Current I don't have any MDP or MDB to listen and consume messages from CLIENT_DATA queue in QM_CLIENT. I merely send it from QM_MINE and it gets moved to QM_CLIENT by MQ. Do I need to consume the messages to get this working?
I use java, JMS , Spring and WebShere MQ v7.1 on Linux. Any more information will be provided upon request.
Please see the section on the MQMD.Report field. Yes, you do need to set the reply-to fields so that the acknowledgement can find its way back to you. However you also need to tell WMQ that you want it to generate the report message. For what you want, set the field to MQRO_COA_WITH_FULL_DATA.

Sending messages to specific Smack domains after initial broadcast message

I'm creating an instant messaging client using Smack 3.1.0 and Java. The problem I'm running in to has to do with sending messages to the user on a specific domain.
For example, I have two users, 1#gmail.com and 2#gmail.com. 1#gmail.com logs in to XMPP through my IM client. 2#gmail.com logs in to GChat through gmail.com AND a second time through pidgin. So now I have one instance of 1#gmail.com and 2 instances of 2#gmail.com.
The way gmail works, if 1#gmail.com sends a message to 2#gmail.com, the gmail and the pidgin client both get the initial message. But then if the gmail instance responds to the message, every message from then on only goes between 1#gmail.com and the gmail instance of 2#gmail.com.
I would like to mimic this behavior with my IM client. I would think the way to do it would be to set up a Chat, send the initial IM to all instances of the recipient. Then I'd set up a MessageListener to listen for a response. When I get the response, I'd have to create a new chat, specifying the 2#gmail.com/resource. But then I'd have to write the MessageListener twice. Any ideas? Here's some sample code that I'm using (the method AddText() simply appends the message to my conversation pane):
recipient = buddy;
setTitle("Instant Message - "+recipient);
chat = com.andreaslekas.pim.PIM.connection.getChatManager().createChat(recipient.getUser(), new MessageListener() {
public void processMessage(Chat chat, Message msg) {
//if(chat.getParticipant().indexOf('/')!=-1)
addText(msg.getBody(), chat.getParticipant(), true);
}
});
UPDATE
I wanted to supplement the answer below with actual code that I used to make this work:
chat = com.andreaslekas.pim.PIM.connection.getChatManager().createChat(recipient.getUser(), new MessageListener() {
public void processMessage(Chat new_chat, Message msg) {
if(msg.getFrom().replaceFirst("/.*", "").equals(recipient.getUser()))
{
if(buddy_resource==null || !msg.getFrom().replaceFirst(".*?/", "").equals(buddy_resource.getResource()))
{
buddy_resource = recipient.getResource(msg.getFrom().replaceFirst(".*?/", ""));
chat = null;
chat = com.andreaslekas.pim.PIM.connection.getChatManager().createChat(recipient.getUser()+"/"+buddy_resource.getResource(), new MessageListener(){
public void processMessage(Chat new_chat2, Message msg) {
addText(msg.getBody(), new_chat2.getParticipant(), true);
}
});
}
addText(msg.getBody(), chat.getParticipant(), true);
}
}
});
To summarize, I send the first message to all resources of the recipient's address and wait for a response. When I get the response, I replace the current Chat object with a new one that specifies the individual resource that responded to the initial message. The code is a little messy with two different MessageListener objects that could probably be combined into a new class. But it works.
So far I understood Message Carbon (XEP - 0280) will solve your problem.
If you enable carbon it will distribute messages to all logged resources of a user. In your case if 1#gmail.com send message to 2#gmail.com it will be distributed to all logged resources of 2#gmail.com.
Here's a code sample using smack,
CarbonManager cm = CarbonManager.getInstanceFor(connection);
cm.enableCarbons();
cm.sendCarbonsEnabled();
First make sure that your server is supported Message Carbon.
Then send message as usual.
In your MessageListener why not always respond to the sender? I think you get it by calling something like msg.getSender() or getFrom() (I'm on mobile right now, cannot check)

Categories