|
/*
* @(#)SimpleChat.java 1.10 04/01/05
*
* Copyright (c) 2000-2002 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/
================================================================================
@(#)README 1.7 03/22/05
================================================================================
SimpleChat example
Description
-----------
This example illustrates how JMS can be used to create a simple
chat application. This example uses JMS Topics and each instance
of the the chat application that you run is a TopicPublisher and
TopicSubscriber. SimpleChat.java does not use JNDI and relies on
the feature by which a broker can "auto-create" the destinations
desired by the user. The bulk of the application deals with the
user interface and the JMS related code is fairly straightforward.
Files
-----
SimpleChat.java Source file for this example.
*.class Prebuilt Java class files for this example.
README This file.
Configuring the environment
---------------------------
To recompile or run this example, you need to set CLASSPATH
to include at least:
jms.jar
imq.jar
directory containing this example
A detailed guideline on setting CLASSPATH is found in the README
file in the jms demo subdirectory as well as in the "Quick Start
Tutorial" in the Sun Java(tm) System Message Queue Developer's Guide.
The following are examples for setting CLASSPATH on the different
platforms. These commands are run from the directory containing
this example.
On Solaris:
setenv CLASSPATH /usr/share/lib/jms.jar:/usr/share/lib/imq.jar:.
On Windows:
set CLASSPATH=%IMQ_HOME%\lib\jms.jar;%IMQ_HOME%\lib\imq.jar;.
On Linux:
setenv CLASSPATH /opt/sun/mq/share/lib/jms.jar:
/opt/sun/mq/share/lib/imq.jar:.
#####hpux-dev#####
On HP-UX:
export CLASSPATH=/opt/sun/mq/share/lib/jms.jar:
/opt/sun/mq/share/lib/imq.jar:.
Note that it is assumed that the above export command is run on
BASH shell
Building the example
--------------------
Run the following:
javac SimpleChat.java
Running the example
-------------------
Run the following:
java SimpleChat
The application comes up not connected to any chat session.
To join a chat session, bring down the "Chat" menu and
select the "Connect ..." menu item. A dialog will appear to
query for a "Chat User Name", and the "Chat Topic" to join.
The Chat User Name is simply used to label your messages when
they appear on the "Messages in chat" textarea. The default value
for this is the "user.name" system property.
The Chat Topic is the topic name used to determine who to deliver
chat messages to i.e. the participants in the chat. The default
value is "defaulttopic".
After selecting the above 2 values (using the default values is
fine), click on the "Connect" button. The application is now
in the chat session.
From now on, you can broadcast messages to the chat participants
by typing in the textarea at the bottom (marked "Type Message:")
and selecting the "send Message as <chat name>" button.
More than one instance of the chat application will make the demo
more interesting - for all of the chat applications to talk to
one another they need to be using the same Chat Topic.
To leave the chat session, bring down the "Chat" menu and select
the "Disconnect" menu item.
To clear the "Messages in chat" textarea, bring down the "Chat"
menu and select the "Clear Messages" menu item.
To exit the simplechat demo application/program, bring down the "Chat"
menu and select the "Exit" menu item.
/*
* @(#)SimpleChat.java 1.10 04/01/05
*
* Copyright (c) 2000-2002 Sun Microsystems, Inc. All Rights Reserved.
*
* Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
* modify and redistribute this software in source and binary code form,
* provided that i) this copyright notice and license appear on all copies of
* the software; and ii) Licensee does not utilize the software in a manner
* which is disparaging to Sun.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
* IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
* NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
* LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
* OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
* LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
* INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
* CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
* OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* This software is not designed or intended for use in on-line control of
* aircraft, air traffic, aircraft navigation or aircraft communications; or in
* the design, construction, operation or maintenance of any nuclear
* facility. Licensee represents and warrants that it will not use or
* redistribute the Software for such purposes.
*/
import java.awt.*;
import java.awt.event.*;
import java.io.Serializable;
import java.net.InetAddress;
import java.util.Vector;
import java.util.Enumeration;
import javax.jms.*;
/**
* The SimpleChat example is a basic 'chat' application that uses
* the JMS APIs. It uses JMS Topics to represent chat rooms or
* chat topics.
*
* When the application is launched, use the 'Chat' menu to
* start or connect to a chat session.
*
* The command line option '-DimqAddressList='can be used to affect
* how the application connects to the message service provided by
* the Sun Java(tm) System Message Queue software.
*
* It should be pointed out that the bulk of the application is
* AWT - code for the GUI. The code that implements the messages
* sent/received by the chat application is small in size.
*
* The SimpleChat example consists of the following classes, all
* contained in one file:
*
* SimpleChat - contains main() entry point, GUI/JMS
* initialization code.
* SimpleChatPanel - GUI for message textareas.
* SimpleChatDialog - GUI for "Connect" popup dialog.
* ChatObjMessage - chat message class.
*
* Description of the ChatObjMessage class and how it is used
* ==========================================================
* The ChatObjMessage class is used to broadcast messages in
* the JMS simplechat example.
* The interface SimpleChatMessageTypes (defined in this file)
* has several message 'types':
*
* From the interface definition:
* public static int JOIN = 0;
* public static int MSG = 1;
* public static int LEAVE = 2;
*
* JOIN - for applications to announce that they just joined the chat
* MSG - for normal text messages
* LEAVE - for applications to announce that are leaving the chat
*
* Each ChatObjMessage also has fields to indicate who the sender is
* - a simple String identifier.
*
* When the chat application enters a chat session, it broadcasts a JOIN
* message. Everybody currently in the chat session will get this and
* the chat GUI will recognize the message of type JOIN and will print
* something like this in the 'Messages in chat:' textarea:
*
* *** johndoe has joined chat session
*
* Once an application has entered a chat session, messages sent as part of
* a normal 'chat' are sent as ChatObjMessage's of type MSG. Upon seeing
* these messages, the chat GUI simply displays the sender and the message
* text as follows:
*
* johndoe: Hello World !
*
* When a chat disconnect is done, prior to doing the various JMS cleanup
* operations, a LEAVE message is sent. The chat GUI sees this and prints
* something like:
*
* *** johndoe has left chat session
*
*
*/
public class SimpleChat implements ActionListener,
WindowListener,
MessageListener {
ConnectionFactory connectionFactory;
Connection connection;
Session session;
MessageProducer msgProducer;
MessageConsumer msgConsumer;
Topic topic;
boolean connected = false;
String name, hostName, topicName, outgoingMsgTypeString;
int outgoingMsgType;
Frame frame;
SimpleChatPanel scp;
SimpleChatDialog scd = null;
MenuItem connectItem, disconnectItem, clearItem, exitItem;
Button sendB, connectB, cancelB;
SimpleChatMessageCreator outgoingMsgCreator;
SimpleChatMessageCreator txtMsgCreator, objMsgCreator, mapMsgCreator, bytesMsgCreator, streamMsgCreator;
/**
* @param args Arguments passed via the command line. These are
* used to create the ConnectionFactory.
*/
public static void main(String[] args) {
SimpleChat sc = new SimpleChat();
sc.initGui();
sc.initJms(args);
}
/**
* SimpleChat constructor.
* Initializes the chat user name, topic, hostname.
*/
public SimpleChat() {
name = System.getProperty("user.name", "johndoe");
topicName = "defaulttopic";
try {
hostName = InetAddress.getLocalHost().getHostName();
} catch (Exception e) {
hostName = "localhost";
}
}
public SimpleChatMessageCreator getMessageCreator(int type) {
switch (type) {
case SimpleChatDialog.MSG_TYPE_TEXT:
if (txtMsgCreator == null) {
txtMsgCreator = new SimpleChatTextMessageCreator();
}
return (txtMsgCreator);
case SimpleChatDialog.MSG_TYPE_OBJECT:
if (objMsgCreator == null) {
objMsgCreator = new SimpleChatObjMessageCreator();
}
return (objMsgCreator);
case SimpleChatDialog.MSG_TYPE_MAP:
if (mapMsgCreator == null) {
mapMsgCreator = new SimpleChatMapMessageCreator();
}
return (mapMsgCreator);
case SimpleChatDialog.MSG_TYPE_BYTES:
if (bytesMsgCreator == null) {
bytesMsgCreator = new SimpleChatBytesMessageCreator();
}
return (bytesMsgCreator);
case SimpleChatDialog.MSG_TYPE_STREAM:
if (streamMsgCreator == null) {
streamMsgCreator = new SimpleChatStreamMessageCreator();
}
return (streamMsgCreator);
}
return (null);
}
public SimpleChatMessageCreator getMessageCreator(Message msg) {
if (msg instanceof TextMessage) {
if (txtMsgCreator == null) {
txtMsgCreator = new SimpleChatTextMessageCreator();
}
return (txtMsgCreator);
} else if (msg instanceof ObjectMessage) {
if (objMsgCreator == null) {
objMsgCreator = new SimpleChatObjMessageCreator();
}
return (objMsgCreator);
} else if (msg instanceof MapMessage) {
if (mapMsgCreator == null) {
mapMsgCreator = new SimpleChatMapMessageCreator();
}
return (mapMsgCreator);
} else if (msg instanceof BytesMessage) {
if (bytesMsgCreator == null) {
bytesMsgCreator = new SimpleChatBytesMessageCreator();
}
return (bytesMsgCreator);
} else if (msg instanceof StreamMessage) {
if (streamMsgCreator == null) {
streamMsgCreator = new SimpleChatStreamMessageCreator();
}
return (streamMsgCreator);
}
return (null);
}
/*
* BEGIN INTERFACE ActionListener
*/
/**
* Detects the various UI actions and performs the
* relevant action:
* Connect menu item (on Chat menu): Show Connect dialog
* Disconnect menu item (on Chat menu): Disconnect from chat
* Connect button (on Connect dialog): Connect to specified
* chat
* Cancel button (on Connect dialog): Hide Connect dialog
* Send button: Send message to chat
* Clear menu item (on Chat menu): Clear chat textarea
* Exit menu item (on Chat menu): Exit application
*
* @param ActionEvent UI event
*/
public void actionPerformed(ActionEvent e) {
Object obj = e.getSource();
if (obj == connectItem) {
queryForChatNames();
} else if (obj == disconnectItem) {
doDisconnect();
} else if (obj == connectB) {
scd.setVisible(false);
topicName = scd.getChatTopicName();
name = scd.getChatUserName();
outgoingMsgTypeString = scd.getMsgTypeString();
outgoingMsgType = scd.getMsgType();
doConnect();
} else if (obj == cancelB) {
scd.setVisible(false);
} else if (obj == sendB) {
sendNormalMessage();
} else if (obj == clearItem) {
scp.clear();
} else if (obj == exitItem) {
exit();
}
}
/*
* END INTERFACE ActionListener
*/
/*
* BEGIN INTERFACE WindowListener
*/
public void windowClosing(WindowEvent e) {
e.getWindow().dispose();
}
public void windowClosed(WindowEvent e) {
exit();
}
public void windowActivated(WindowEvent e) { }
public void windowDeactivated(WindowEvent e) { }
public void windowDeiconified(WindowEvent e) { }
public void windowIconified(WindowEvent e) { }
public void windowOpened(WindowEvent e) { }
/*
* END INTERFACE WindowListener
*/
/*
* BEGIN INTERFACE MessageListener
*/
/**
* Display chat message on gui.
*
* @param msg message received
*/
public void onMessage(Message msg) {
String sender, msgText;
int type;
SimpleChatMessageCreator inboundMsgCreator;
inboundMsgCreator = getMessageCreator(msg);
if (inboundMsgCreator == null) {
errorMessage("Message received is not supported ! ");
return;
}
/*
* Need to fetch msg values in this order.
*/
type = inboundMsgCreator.getChatMessageType(msg);
sender = inboundMsgCreator.getChatMessageSender(msg);
msgText = inboundMsgCreator.getChatMessageText(msg);
if (type == SimpleChatMessageTypes.BADTYPE) {
errorMessage("Message received in wrong format ! ");
return;
}
scp.newMessage(sender, type, msgText);
}
/*
* END INTERFACE MessageListener
*/
/*
* Popup the SimpleChatDialog to query the user for the chat user
* name and chat topic.
*/
private void queryForChatNames() {
if (scd == null) {
scd = new SimpleChatDialog(frame);
connectB = scd.getConnectButton();
connectB.addActionListener(this);
cancelB = scd.getCancelButton();
cancelB.addActionListener(this);
}
scd.setChatUserName(name);
scd.setChatTopicName(topicName);
scd.show();
}
/*
* Performs the actual chat connect.
* The createChatSession() method does the real work
* here, creating:
* Connection
* Session
* Topic
* MessageConsumer
* MessageProducer
*/
private void doConnect() {
if (connectedToChatSession())
return;
outgoingMsgCreator = getMessageCreator(outgoingMsgType);
if (createChatSession(topicName) == false) {
errorMessage("Unable to create Chat session. " +
"Please verify a broker is running");
return;
}
setConnectedToChatSession(true);
connectItem.setEnabled(false);
disconnectItem.setEnabled(true);
scp.setUserName(name);
scp.setDestName(topicName);
scp.setMsgType(outgoingMsgTypeString);
scp.setHostName(hostName);
scp.setEnabled(true);
}
/*
* Disconnects from chat session.
* destroyChatSession() performs the JMS cleanup.
*/
private void doDisconnect() {
if (!connectedToChatSession())
return;
destroyChatSession();
setConnectedToChatSession(false);
connectItem.setEnabled(true);
disconnectItem.setEnabled(false);
scp.setEnabled(false);
}
/*
* These methods set/return a flag that indicates
* whether the application is currently involved in
* a chat session.
*/
private void setConnectedToChatSession(boolean b) {
connected = b;
}
private boolean connectedToChatSession() {
return (connected);
}
/*
* Exit application. Does some cleanup if
* necessary.
*/
private void exit() {
doDisconnect();
System.exit(0);
}
/*
* Create the application GUI.
*/
private void initGui() {
frame = new Frame("Simple Chat");
frame.addWindowListener(this);
MenuBar menubar = createMenuBar();
frame.setMenuBar(menubar);
scp = new SimpleChatPanel();
scp.setUserName(name);
scp.setDestName(topicName);
scp.setHostName(hostName);
sendB = scp.getSendButton();
sendB.addActionListener(this);
frame.add(scp);
frame.pack();
frame.setVisible(true);
scp.setEnabled(false);
}
/*
* Create menubar for application.
*/
private MenuBar createMenuBar() {
MenuBar mb = new MenuBar();
Menu chatMenu;
chatMenu = (Menu) mb.add(new Menu("Chat"));
connectItem = (MenuItem) chatMenu.add(new MenuItem("Connect ..."));
disconnectItem = (MenuItem) chatMenu.add(new MenuItem("Disconnect"));
clearItem = (MenuItem) chatMenu.add(new MenuItem("Clear Messages"));
exitItem = (MenuItem) chatMenu.add(new MenuItem("Exit"));
disconnectItem.setEnabled(false);
connectItem.addActionListener(this);
disconnectItem.addActionListener(this);
clearItem.addActionListener(this);
exitItem.addActionListener(this);
return (mb);
}
/*
* Send message using text that is currently in the SimpleChatPanel
* object. The text message is obtained via scp.getMessage()
*
* An object of type ChatObjMessage is created containing the typed
* text. A JMS ObjectMessage is used to encapsulate this ChatObjMessage
* object.
*/
private void sendNormalMessage() {
Message msg;
if (!connectedToChatSession()) {
errorMessage("Cannot send message: Not connected to chat session!");
return;
}
try {
msg = outgoingMsgCreator.createChatMessage(session,
name,
SimpleChatMessageTypes.NORMAL,
scp.getMessage());
msgProducer.send(msg);
scp.setMessage("");
scp.requestFocus();
} catch (Exception ex) {
errorMessage("Caught exception while sending NORMAL message: " + ex);
}
}
/*
* Send a message to the chat session to inform people
* we just joined the chat.
*/
private void sendJoinMessage() {
Message msg;
try {
msg = outgoingMsgCreator.createChatMessage(session,
name,
SimpleChatMessageTypes.JOIN,
null);
msgProducer.send(msg);
} catch (Exception ex) {
errorMessage("Caught exception while sending JOIN message: " + ex);
}
}
/*
* Send a message to the chat session to inform people
* we are leaving the chat.
*/
private void sendLeaveMessage() {
Message msg;
try {
msg = outgoingMsgCreator.createChatMessage(session,
name,
SimpleChatMessageTypes.LEAVE,
null);
msgProducer.send(msg);
} catch (Exception ex) {
errorMessage("Caught exception while sending LEAVE message: " + ex);
}
}
/*
* JMS initialization.
* This is simply creating the ConnectionFactory.
*/
private void initJms(String args[]) {
/* XXX: chg for JMS1.1 to use BasicConnectionFactory for non-JNDI useage
* remove --- Use BasicConnectionFactory directly - no JNDI
*/
try {
connectionFactory
= new com.sun.messaging.ConnectionFactory();
} catch (Exception e) {
errorMessage("Caught Exception: " + e);
}
}
/*
* Create 'chat session'. This involves creating:
* Connection
* Session
* Topic
* MessageConsumer
* MessageProducer
*/
private boolean createChatSession(String topicStr) {
try {
/*
* Create the connection...
*
*/
connection = connectionFactory.createConnection();
/*
* Not transacted
* Auto acknowledegement
*/
session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
topic = session.createTopic(topicStr);
msgProducer = session.createProducer(topic);
/*
* Non persistent delivery
*/
msgProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
msgConsumer = session.createConsumer(topic);
msgConsumer.setMessageListener(this);
connection.start();
sendJoinMessage();
return true;
} catch (<
|