Spring boot create a topic and publish so APPS can receive it - java

I'm creating an app that there's a button that says "Join the room" and when you click on it you join an imaginary room where you can see more users entering.
My idea is to create a topic for instance nameRoom and every time a user joins the room it automatically subscribe to them, so if there's another update he/she'll receive the update for instance one joined or one left.
The thing where I'm stuck is:
The "Administrator" can create a "Room" so every time the Administrator creates a Room should it be a new topic, right? So, my question is once I'm inside a room, I'd like to create like a countdown let's say 30 seconds, and when those 30 seconds are done, it starts to ask me questions and everyone can answer the question and I need to see how many users have answered and how many does not, this is another topic?
The flow is :
Administrator creates a room --> Room1
User1 joins the Room1 and sees only you are in this room
User2 joins the Room and sees there are 2 guys in this room (And so on until user 5)
Then the timer goes down 30 to 0
Then as a User1 I see "How old is Michael Jordan" and 4 checkbox and everyone can answer
Also there's a field saying how many answers already have been posted so if the time of the question is 30 seconds and they are 5 users and they answer in less than 30 seconds the question has to be moved to the next screen that is
Top 3 who answered faster and score
To be clear :
I'd like to know how to create topic and then publish to them using Spring. For example to create the room is not necessary MQTT but to check who joins and this stuff it is, so I'm asking this, how could I create this with MQTT?
Also, MQTT would be responsible to say all of the info? I mean every room has some questions so it's necessary to via MQTT know the ranking etc?

1) You need to create database that suits your application needs
Database name : ChatRoom
Tables:
Topics(To store all mqtt room topic names)
Room (Each room is associated with a topic)
User (Each user is associated with a room)
2) Setup an mqtt server which allows connection both on mqtt and websockets (To support javascript application)
3) Now create a spring boot application with following api and web pages
Web pages:
chatroom.html
chatroom.js
Api:
create chatroom (for admin)
list chatroom
join chatroom (for new users)
Steps:
The admin uses the chatroom.html web page to create new chatroom.On creation it calls create chatroom api to create new chatroom. In the api it will subscribe to a new topic for new chatroom.
When normal users visit chatroom.html it will list available chatrooms (use list chatroom api). Once you click on chatroom it will call join chatroom api to update the details in database. The javascript from browser can connect to mqtt topic for the specific chatroom.
For managing questions you need to have your own logic in backend as well as frontend side. You can use Mqtt topic for transferring messages
Refer the following links
For javascript
http://www.steves-internet-guide.com/using-javascript-mqtt-client-websockets/
For java
https://www.eclipse.org/paho/clients/java/
public final class MessageQueueClient implements MqttCallback
{
private MqttClient mqttClient;
private MessageQueueClient()
{
}
public static MessageQueueClient getInstance()
{
return messageQueueClient;
}
#Override
public void connectionLost(Throwable cause)
{
}
#Override
public void messageArrived(String topic, MqttMessage message)
{
}
#Override
public void deliveryComplete(IMqttDeliveryToken token)
{
}
//Call this method on server startup to connect to mqtt server(spring boot app start)
public boolean connect(String hostname, String clientuniqueid)
{
try
{
if (mqttCredentialsDTO != null)
{
MqttConnectOptions options = new MqttConnectOptions();
options.setAutomaticReconnect(true);
options.setCleanSession(true);
mqttClient = new MqttClient(hostname, clientuniqueid);
mqttClient.connect(options);
return true;
}
}
catch (Exception e)
{
e.printStacktrace();
}
return false;
}
//Call this method on server shutdown to disconnect from mqtt server
public boolean disconnect()
{
try
{
if (mqttClient != null)
{
mqttClient.disconnect();
mqttClient.close();
return true;
}
}
catch (MqttException e)
{
e.printStacktrace();
}
return false;
}
//call this method after mqtt connection established to subscribe to any topic
public boolean subscribe(String topicName, int qos)
{
try
{
if (topicName != null)
{
mqttClient.subscribe(topicName, qos);
return true;
}
}
catch (MqttException e)
{
e.printStacktrace();
}
return false;
}
//call this method after mqtt connection established to publish to any topic
public boolean publish(String topicName, String message, int qos)
{
try
{
if (topicName != null)
{
MqttMessage mqttMessage = new MqttMessage();
mqttMessage.setPayload(message.getBytes());
mqttMessage.setQos(qos);
mqttClient.publish(topicName, mqttMessage);
return true;
}
}
catch (MqttException e)
{
e.printStacktrace();
}
return false;
}
}

In my old project I created something similar to what you need.
I'm still sure Google (and Apple) notification systems are better. In any case here what you need.
You can use Eclipse Paho in order to produce and consume MQTT messages.
In my android app build.gradle file I added:
compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.0.2'
Now there is a newer version of the library
This library offers to you all the needed API in order to consume and produce MQTT messages in and from an Android device.
In the documentation section you can find a sample application. You can start from there
On server side I used Apache ActiveMQ as broker. It offers an embedded implementation of MQTT handler and you can create topics and queues in order to handle MQTT messages.
I hope it's useful
Angelo
EDIT SECTION
Let's suppose you want to use ActiveMQ on server side.
You must download and install activemq. In the activemq.xml file inside the directory ${activemq_home}/conf you'll find the mqtt configuration. It's this line:
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
This means that activemq handles mqtt protocol messages on port 1883 (the mqtt default TCP/IP port).
On the admin console of activemq you can create topic or queue you want to use for your messages. In the app you must connect the paho service to the created topic or queue.
Please note that by default activemq uses in memory DB. I suggest to yuo to configure it in order to use normal RDBMS or even NoSQL DB. The most important thing is that you configure it in order to store all messages not in memory otherwise you can risk messages will be lost.
Moreover if you expose on internet activemq I strongly suggest to you to protect it by secure credentials or by using SSL certificates.

Related

Print Mqtt topics and Choose one to subscribe to one of them

I was struggling an issue , the issue was about showing available mqtt topics from broker server in multiple textviews in android, and choose one of them to subscribe to topics
final MqttAndroidClient client =new MqttAndroidClient(getApplicationContext(),"tcp://iot.eclipse.org:1883","12d45454");
try {
client.connect(mqttConnectOptions, null, new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken mqttToken) {
DisconnectedBufferOptions disconnectedBufferOptions = new DisconnectedBufferOptions();
disconnectedBufferOptions.setBufferEnabled(true);
disconnectedBufferOptions.setBufferSize(100);
disconnectedBufferOptions.setPersistBuffer(false);
disconnectedBufferOptions.setDeleteOldestMessages(false);
Log.i("ERROR ","Topic="+mqttToken.getTopics());
textview1.setText(mqttToken.getTopics()[0]);
}
Firstly lets talk about the purpose of the method used by you to fetch the topic list (according to your code):
Log.i("ERROR ","Topic="+mqttToken.getTopics());
The purpose of the above method getTopics() is not to provide you the exhaustive list of topic's available on your MQTT Broker. This method returns the name of the topics associated with your token. And if you go through this Link you will see that the method gets called on the succesfull completion of an operation. Additionally you can have a look over the java doc of the IMqttToken.
May be you can elaborate your use case so that audience can help you with that, fetching all active topics should not be a solution ideally.

JMS 2.0 - MQ 9 - Topic Shared subscription doesn't work

I'm facing problem when developing an application that subscribe a MQ Topic (MQ version 9).
I need to do a shared topic connection because the application will be ran in multiple instances (cluster).
The specs and the documentation says :
"A non-durable shared subscription is used by a client which needs to be able to share the work of receiving messages from a topic subscription amongst multiple consumers. A non-durable shared subscription may therefore have more than one consumer. Each message from the subscription will be delivered to only one of the consumers on that subscription."
For me, all the clients using the same subscription name are in the same "cluster", only one client will receive a message at one time.
In my code, inspired by this article, I've got an exception when the second client try to create the shared subscription. I really don't understand if this is a bug in MQ client libraries implementation or in my code.
Here my sample code :
import javax.jms.Connection;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.Topic;
import com.ibm.mq.jms.MQTopicConnectionFactory;
import com.ibm.msg.client.wmq.WMQConstants;
public class TestGB2 {
public static void main(final String[] args) throws Exception {
for (int i = 0; i < 10; i++) {
new Thread(new MyThread("THREAD" + i, "TESTSUB/#", "myClient", "SUBTEST")).start();
}
}
public static class MyThread implements Runnable {
private final String topicString;
private final String clientId;
private final String subscriptionName;
public MyThread(final String threadName, final String topicString, final String clientId, final String subscriptionName) {
Thread.currentThread().setName(threadName);
this.topicString = topicString;
this.clientId = clientId;
this.subscriptionName = subscriptionName;
}
#Override
public void run() {
try {
System.out.println(String.format("%s : Connecting...", Thread.currentThread().getName()));
MQTopicConnectionFactory cf = new MQTopicConnectionFactory();
cf.setHostName("xxxx");
cf.setPort(1416);
cf.setQueueManager("xxxx");
cf.setTransportType(WMQConstants.WMQ_CM_CLIENT);
cf.setChannel("xxx");
cf.setClientID(clientId);
Connection con = cf.createConnection();
Session session = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
con.start();
Topic topic = session.createTopic(topicString);
MessageConsumer messageConsumer = session.createSharedConsumer(topic, subscriptionName); // fail here
System.out.println(String.format("%s : Waiting for a message...", Thread.currentThread().getName()));
Message msg = messageConsumer.receive();
System.out.println(String.format("%s : Received :\n%s", Thread.currentThread().getName(), msg));
}
catch (Exception ex) {
System.out.println(String.format("%s : FAILED", Thread.currentThread().getName()));
ex.printStackTrace();
}
}
}
}
The code below tries to create 10 threads consuming messages on the same topic. Only the first thread is able to connect, all the others fail with following exception :
com.ibm.msg.client.jms.DetailedIllegalStateException: JMSWMQ0026: Failed to subscribe to topic 'TESTSUB' with selector 'none' using MQSUB.
There may have been a problem creating the subscription due to it being used by another message consumer.
Make sure any message consumers using this subscription are closed before trying to create a new subscription under the same name. Please see the linked exception for more information.
at com.ibm.msg.client.wmq.common.internal.Reason.reasonToException(Reason.java:472)
at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:214)
at com.ibm.msg.client.wmq.internal.WMQMessageConsumer.checkJmqiCallSuccess(WMQMessageConsumer.java:212)
at com.ibm.msg.client.wmq.internal.WMQMessageConsumer.checkJmqiCallSuccess(WMQMessageConsumer.java:112)
at com.ibm.msg.client.wmq.internal.WMQConsumerShadow.initialize(WMQConsumerShadow.java:1038)
at com.ibm.msg.client.wmq.internal.WMQSyncConsumerShadow.initialize(WMQSyncConsumerShadow.java:134)
at com.ibm.msg.client.wmq.internal.WMQMessageConsumer.<init>(WMQMessageConsumer.java:470)
at com.ibm.msg.client.wmq.internal.WMQSession.createSharedConsumer(WMQSession.java:938)
at com.ibm.msg.client.jms.internal.JmsSessionImpl.createSharedConsumer(JmsSessionImpl.java:4228)
at com.ibm.msg.client.jms.internal.JmsSessionImpl.createSharedConsumer(JmsSessionImpl.java:4125)
at com.ibm.mq.jms.MQSession.createSharedConsumer(MQSession.java:1319)
at TestGB.lambda$0(TestGB.java:33)
at java.lang.Thread.run(Thread.java:748)
Caused by: com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2042' ('MQRC_OBJECT_IN_USE').
at com.ibm.msg.client.wmq.common.internal.Reason.createException(Reason.java:202)
... 11 more
Tried with the last lib :
<dependency>
<groupId>com.ibm.mq</groupId>
<artifactId>com.ibm.mq.allclient</artifactId>
<version>9.1.1.0</version>
</dependency>
Summary of the issue
The issue is not with your program, the issue is with the model queue associated to the topic you are subscribing to.
On the queue manager if you look at the topic object that your subscription will match, it will have a parameter MNDURMDL that points to a model queue.
If you look at the model queue you will note two parameters where either or both can cause the error you are receiving:
[ DEFSOPT( EXCL | SHARED ) ]
[ SHARE | NOSHARE ]
These must be set to DEFSOPT(SHARED) and SHARE. If either one is set to the other value you will only be able to have one subscriber on the shared subscription.
Additional details of the cause of the issue
With IBM MQ Pub/Sub, when you create a JMS subscription MQ treats this as a managed subscription, in the background IBM MQ will create a temporary queue to subscribe to the topic string. If it is a non-durable subscription the queue is a temporary dynamic queue.
The reason for the failure is that the first thread will open the temporary dynamic queue in an exclusive mode, any other threads then cannot open the temporary dynamic queue and you receive the MQRC_OBJECT_IN_USE error.
Possible cause where an application specific MNDURMDL model queue was created
I suspect the cause of this is that IBM comes with a few different default model queues.
The default for a non-durable subscriber has these settings:
QUEUE(SYSTEM.NDURABLE.MODEL.QUEUE) TYPE(QMODEL)
DEFSOPT(SHARED) SHARE
There is another default queue that is not pub/sub specific that has these settings:
QUEUE(SYSTEM.DEFAULT.MODEL.QUEUE) TYPE(QMODEL)
DEFSOPT(EXCL) NOSHARE
It is likely that the model queue created for use by your topic object was created with a command like the following that will default to use the setting of the SYSTEM.DEFAULT.MODEL.QUEUE.:
DEFINE QMODEL(xxx)
In the future you could either specifically set those two parameters, or define it with the LIKE keyword to force it to use a different queue to model settings from, both commands are below:
DEFINE QMODEL(xxx) DEFSOPT(SHARED) SHARE
DEFINE QMODEL(xxx) LIKE(SYSTEM.NDURABLE.MODEL.QUEUE)
Additional details on creation and usage of application specific TOPIC objects and MODEL queues
By default the root node of the tree is represented by the standard TOPIC object named SYSTEM.BASE.TOPIC, the default model queues associated to this TOPIC are shown below:
TOPIC(SYSTEM.BASE.TOPIC) TYPE(LOCAL)
TOPICSTR() MDURMDL(SYSTEM.DURABLE.MODEL.QUEUE)
MNDURMDL(SYSTEM.NDURABLE.MODEL.QUEUE)
If you do not define any further administrative TOPIC objects, then all topics match against SYSTEM.BASE.TOPIC. Additionally if you do not define any further administrative TOPIC objects and you want to give an application permission to a specific subset of the topic tree (for example topic strings beginning with TESTSUB) you must grant the permissions via SYSTEM.BASE.TOPIC, this in turn grants the application access for any arbitrary topic string with no restrictions.
Best practice would be to create a TOPIC object with a topic string that matches the portion of the topic tree an an application should have access to. Specific to your example of TESTSUB/# if your admin defined a new TOPIC object and specified the TOPICSTR(TESTSUB), the defaults would create it like this:
TOPIC(TESTSUB.TOPIC) TYPE(LOCAL)
TOPICSTR(TESTSUB) MDURMDL( )
MNDURMDL( )
the blank MDURMDL and MNDURMDL values tell MQ to use the value from the next closest higher topic object in the tree, if nothing else is defined this would be the SYSTEM.BASE.TOPIC and the model queues would still default to using the SYSTEM.DURABLE.MODEL.QUEUE and SYSTEM.NDURABLE.MODEL.QUEUE model queues.
The admin can instead create the TOPIC object and specify different model queues for example:
TOPIC(TESTSUB.TOPIC) TYPE(LOCAL)
TOPICSTR(TESTSUB) MDURMDL(TESTSUB.DURABLE.MODEL.QUEUE)
MNDURMDL(TESTSUB.NDURABLE.MODEL.QUEUE)
By doing this they can define application specific model queues that have the settings required for shared subscriptions and not impact the SYSTEM model queues. The other benefit is they can provide the application permissions for only topic strings that start with TESTSUB, for example TESTSUB/A or TESTSUB/B or TESTSUB/X/Y/Z.

Firestore admin "listens" to all documents again on reboot

TL;DR
Every time my Fiestore admin server reboots my document listener is triggered for all documents even if I have already listened to the document and processed it. How do I get around this?
End TL;DR
I'm working on building a backend for my Firestore chat application. The basic idea is that whenever a users enters a chat message through a client app the backend server listens for new messages and processes them.
The problem I'm running into is that whenever I reboot my app server the listener is triggered for all of the existing already processed chats. So, it will respond to each chat even though it has already responded previously. I would like the app server to only respond to new chats that it hasn't already responded to.
One idea I have for a work around is to put a boolean flag on each chat document. When the backend processes the chat document it will set the flag. The listener will then only reply to chats that don't have the flag set.
Is this a sound approach or is there a better method? One concern I have is that every time I reboot my app server I will be charged heavily to re-query all of the previous chats. Another concern I have is that listening seems memory bound? If my app scales massively will I have to store all chat documents in memory? That doesn't seem like it will scale well...
//Example listener that processes chats based on whether or not the "hasBeenRepliedTo" flag is set
public void startFirestoreListener() {
CollectionReference docRef = db.collection("chats");
docRef.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#javax.annotation.Nullable QuerySnapshot queryDocumentSnapshots, #javax.annotation.Nullable FirestoreException e) {
if(e != null) {
logger.error("There was an error listening to changes in the firestore chats collection. E: "+e.getLocalizedMessage());
e.printStackTrace();
}
else if(queryDocumentSnapshots != null && !queryDocumentSnapshots.isEmpty()) {
for(ChatDocument chatDoc : queryDocumentSnapshots.toObjects(ChatDocument.class)) {
if(!chatDoc.getHasBeenRepliedTo() {
//Do some processing
chatDoc.setHasBeenRepliedTo(true); //Set replied to flag
}
else {
//No-op, we've already replied to this chat
}
}
}
}
});
}
Yes, to avoid getting each document all the time, you will have to construct a query that yields only the documents that you know have been processed.
No, you are not charged to query documents. You are charged only to read them, which will happen if your query yields documents.
Yes, you will have to be able to hold all the results of a query in memory.
Your problem will be much easier to solve if you use Cloud Functions to receive events for each new document in a collection. You won't have to worry about any of the above things, and instead just worry about writing a Firestore trigger that does what you want with each new document, and paying for those invocations.

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.

How to initiate chatting between two clients and two clients only, using applets and servlets?

I first need to apologize for my earlier questions. (You can check my profile for them)They seemed to ask more questions than give answers. Hence, I am laying down the actual question that started all them absurd questions.
I am trying to design a chat applet. Till now, I have coded the applet, servlet and communication between the applet and the servlet. The code in the servlet side is such that I was able to establish chatting between clients using the applets, but the code was more like a broadcast all feature, i.e. all clients would be chatting with each other. That was my first objective when I started designing the chat applet. The second step is chatting between only two specific users, much like any other chat application we have. So this was my idea for it:
I create an instance of the servlet that has the 'broadcast-all' code.
I then pass the address of this instance to the respective clients.
2 client applets use the address to then chat. Technically the code is 'broadcast-all', but since only 2 clients are connected to it, it gives the chatting between two clients feature. Thus, groups of 2 clients have different instances of the same servlet, and each instance handles chatting between two clients at a max.
However, as predicted, the idea didn't materialize!
I tried to create an instance of the servlet but the only solution for that was using sessions on the servlet side, and I don't know how to use this session for later communications.
I now know how to use the request.getSession(). So I set the session for an applet in its param tag and use it for further communications with the servlet. But how do I use this data to establish chatting between two clients? As I wrote earlier, I have the code for broadcast_all chatting as follows:
public class CustomerServlet extends HttpServlet {
public String getNextMessage() {
// Create a message sink to wait for a new message from the
// message source.
return new MessageSink().getNextMessage(source);
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ObjectOutputStream dout = new ObjectOutputStream(response.getOutputStream());
String recMSG = getNextMessage();
dout.writeObject(recMSG);
dout.flush();
}
public void broadcastMessage(String message) {
// Send the message to all the HTTP-connected clients by giving the
// message to the message source
source.sendMessage(message);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
ObjectInputStream din= new ObjectInputStream(request.getInputStream());
String message = (String)din.readObject();
ObjectOutputStream dout = new ObjectOutputStream(response.getOutputStream());
dout.writeObject("1");
dout.flush();
if (message != null) {
broadcastMessage(message);
}
// Set the status code to indicate there will be no response
response.setStatus(response.SC_NO_CONTENT);
} catch (Exception e) {
e.printStackTrace();
}
}
MessageSource source = new MessageSource();
}
class MessageSource extends Observable {
public void sendMessage(String message) {
setChanged();
notifyObservers(message);
}
}
class MessageSink implements Observer {
String message = null; // set by update() and read by getNextMessage()
// Called by the message source when it gets a new message
synchronized public void update(Observable o, Object arg) {
// Get the new message
message = (String)arg;
// Wake up our waiting thread
notify();
}
// Gets the next message sent out from the message source
synchronized public String getNextMessage(MessageSource source) {
// Tell source we want to be told about new messages
source.addObserver(this);
// Wait until our update() method receives a message
while (message == null) {
try {
wait();
} catch (Exception e) {
System.out.println("Exception has occured! ERR ERR ERR");
}
}
// Tell source to stop telling us about new messages
source.deleteObserver(this);
// Now return the message we received
// But first set the message instance variable to null
// so update() and getNextMessage() can be called again.
String messageCopy = message;
message = null;
return messageCopy;
}
}
On the applet side, I have a thread that will connect to the servlet above using GET method to get new messages. It uses a while loop, and blocks until it gets a message from the servlet. The main thread communicates with the servlet using POST method whenever the client has entered the message. Currently all clients chat with everyone. I want to use the same methods used above (or if possible any other way) to establish chatting between two clients and two clients only. I could possibly have another thread in the applet to check if any other user wishes to chat with it and then exchange some data so that only those two user chat...
I then tried to modify my broadcast-all code. In that code, I was using classes that implemented Observer and Observable interfaces. So the next idea that I got was:
Create a new object of the Observable class(say class_1). This object be common to 2 clients.
2 clients that wish to chat will use same object of the class_1.
2 other clients will use a different object of class_1.
But the problem here lies with the class that implements the Observer interface(say class_2). Since this has observers monitoring the same type of class, namely class_1, how do I establish an observer monitoring one object of class_1 and another observer monitoring another object of the same class class_1 (Because notifyObservers() would notify all the observers and I can't assign a particular observer to a particular object)?
I first decided to ask individual problems, like how to create instances of servlets, using objects of observable and observer and so on in stackoverflow... but I got confused even more. Can anyone give me an idea how to establish chatting between two clients only?(I am using Http and not sockets or RMI).
Regards,
Mithun.
P.S. Thanks to all who replied to my previous (absurd) queries. I should have stated the purpose earlier so that you guys could help me better.
You need to store all connected users in a Map<String, User> in the application scope using ServletContext#setAttribute(). The String denotes the unique user identifier (chat nickname?). You need to store the specific chat User as well in the session scope using HttpSession#setAttribute(). You also need to store the other user in individual chats in a Map<String, User> in the session scope of the users in question. You can obtain the attribute by the getAttribute() method.
This way you know which users are all available and which user is in the current session and with which users it is individually chatting.
This is a crude way to do it, but I just couldn't find a feasible solution. What I did was that I made all users connect to the servlet that had the broadcastAll code. Each user would be aware of which other user it is chatting with. Hence, while sending a message, the user would append his name and the name of the user that he is chatting with to the message. Since it is a broadcastAll code, every connected user would receive the message. After receiving the message, the user would parse the message to get the user who sent the message, and the name of the user for whom the message was intended. It would compare these two names with its records - see the statement in bold earlier. If matched it would display the message, else ignore it.
Again, its a crude way to do it and I am sure there are better solution out there.

Categories