My place to Speak!

Information

This article was written on 27 Mar 2010, and is filled under Programming.

Simple Chatting Application using Java RMI

Since so many visitors come to my blog and searching about creating an application using Java RMI, so now I want to make a new one about simple chatting application using java rmi. I hope my codes free of bugs, but it is unbelievable i think.

Before you continue make this application you must make sure that a JDK has been installed on your computer. If you do not have it before please download JDK from Sun website and install it on your computer.

Now let create the program. I will use Java RMI and make 3 classes and one 1 interface.

  1. ChatImpl (class)
  2. ChatServer (class)
  3. RMIClient (class)
  4. Chatting (interface)

We need Chatting Interface to determine what methods that can be invoked by the client. In this interface i will defines 4 methods that can be invoked by the client.

  • sendPublicMessage => send a message from a client to another client.
  • getClientList => get a numbers of user connected to the server.
  • connect => creating a new socket connection to server.
  • disconnect => terminated connection from server.
/*
File Name : Chatting.java
Author : Angga Lingga
*/

import java.rmi.*;
import java.util.*;

public interface Chatting extends Remote
{
	public void sendPublicMessage(String keyword, String username, String message) throws RemoteException;
	public ArrayList getClientList() throws RemoteException;
	public void connect(String username) throws RemoteException;
	public void disconnect(String username) throws RemoteException;
}

After we determine the methods that can be invoked by the client in the Chatting Interface, now we will create a class that implements the Chatting Interface (for creating the server stub).

/*
File Name : ChatImpl.java
Author : Angga Lingga
*/

import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
import java.net.*;

public class ChatImpl extends UnicastRemoteObject implements Chatting
{
	private ChatServer cs;

	public ChatImpl(ChatServer cs) throws RemoteException
	{
		super();
		this.cs = cs;
	}

	public void sendPublicMessage(String keyword, String username, String message) throws RemoteException
	{
		cs.sendPublicMessage(keyword, username, message);
	}

	public ArrayList getClientList() throws RemoteException
	{
		return cs.getClientList();
	}

	public void connect(String username) throws RemoteException
	{
		cs.connect(username);
	}

	public void disconnect(String username) throws RemoteException
	{
		cs.disconnect(username);
	}
}

Now after we create the ChatImpl, we create the server and the client codes.

/*
File Name : ChatServer.java
Author : Angga Lingga
*/

import java.rmi.*;
import java.rmi.server.*;
import java.net.*;
import java.io.*;
import java.util.*;
import javax.swing.JOptionPane;

public class ChatServer
{
	private static HashMap<String, Socket> connectedUser = new HashMap<String, Socket>();
	private static Socket ClientSocket = null;
	private static ServerSocket serverSocket;
	private static String username = null;
	private static PrintWriter output;

	private static final String PUBLICMESSAGE = "PUBLICMESSAGE";
	private static final String ONLINE = "ONLINE";
	private static final String OFFLINE = "OFFLINE";

	public ChatServer()
	{
		try
		{
			ChatImpl csi = new ChatImpl(this);
			Naming.rebind("rmi://localhost:1099/ChatService", csi);
		}
		catch(java.rmi.ConnectException ce)
		{
			JOptionPane.showMessageDialog(null, "Trouble : Please run rmiregistry.", "Connect Exception", JOptionPane.ERROR_MESSAGE);
			System.exit(-1);
		}
		catch (IOException ioe)
		{
			JOptionPane.showMessageDialog(null, "Trouble : Please run rmiregistry.", "Exception", JOptionPane.ERROR_MESSAGE);
			System.exit(-1);
		}
		catch (Exception e)
		{
			JOptionPane.showMessageDialog(null, "Trouble : Please run rmiregistry.", "Exception", JOptionPane.ERROR_MESSAGE);
			System.exit(-1);
		}
	}

	public static void main (String[] args)
	{
		try
		{
			int port = Integer.parseInt(args[0]);
			ChatServer cs = new ChatServer();
			cs.processConnection(port);
		}
		catch (ArrayIndexOutOfBoundsException ae)
		{
			JOptionPane.showMessageDialog(null, "Please insert the port", "ATTENTION", JOptionPane.INFORMATION_MESSAGE);
			System.exit(-1);
		}
	}

	private void processConnection(int port)
	{
		try
		{
			serverSocket = new ServerSocket(port);
			System.out.println("Server is running on port " + port + " .... ");
		}
		catch (IOException ioe)
		{
			JOptionPane.showMessageDialog(null, "Could not listen port " + port, "ERROR", JOptionPane.ERROR_MESSAGE);
			System.exit(-1);
		}

		try
		{
			while (true)
			{
				addClient(serverSocket.accept());
				String username = getUsername();
				sendPublicMessage(PUBLICMESSAGE, "SERVER", "[" + username + "] is now online");
			}
		}
		catch (IOException ioe)
		{
			JOptionPane.showMessageDialog(null, "Could not accept connection.", "ERROR", JOptionPane.ERROR_MESSAGE);
			System.exit(-1);
		}
	}

	public void connect(String username)
	{
		this.username = username;
	}

	public String getUsername()
	{
		return username;
	}

	public ArrayList getClientList()
	{
		ArrayList myUser = new ArrayList();

		Iterator i = connectedUser.keySet().iterator();
		String user = null;

		while(i.hasNext())
		{
			user = i.next().toString();
			myUser.add(user);
		}

		return myUser;
	}

	public void addClient(Socket clientSocket) throws RemoteException
	{
		connectedUser.put(getUsername(), clientSocket);
		sendPublicMessage(ONLINE, getUsername(), "CLIENT");
	}

	public void sendPublicMessage(String keyword, String username, String message) throws RemoteException
	{
		Iterator i = connectedUser.keySet().iterator();
		String user = null;
		while(i.hasNext())
		{
			try
			{
				user = i.next().toString();
				ClientSocket =  connectedUser.get(user);
				output = new PrintWriter(ClientSocket.getOutputStream(), true);
				output.println(keyword + "***" + username + "***" + message);
				output.flush();
			}
			catch(IOException ioe)
			{
				connectedUser.remove(user);
				sendPublicMessage(OFFLINE, user, user + " has been left the conversation");
			}
		}
	}

	public void disconnect(String username) throws RemoteException
	{
		connectedUser.remove(username);
		sendPublicMessage(OFFLINE, username, username + " has been left the conversation");
		sendPublicMessage(PUBLICMESSAGE, "SERVER", username + " has been left the conversation");
	}
}

 

/*
File Name : RMIClient.java
Author : Angga Lingga
*/

import java.rmi.*;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;

public class RMIClient extends JFrame implements ActionListener, Runnable
{
	private Chatting c;

	private static String ipAddress;
	private int port;
	private BufferedReader in = null;
	private Thread thread;

	private JButton jButtonConnect;
	private JButton jButtonSend;
	private JLabel jLabelUserList;
	private JList jListUser;
	private JScrollPane jScrollPaneListUser;
	private JScrollPane jScrollPaneMessage;
	private JTextArea jTextAreaMessage;
	private JTextField jTextSendMessage;
	private JTextField jTextUserName;

	private Socket socket = null;
	private DefaultListModel listClient;

	private String message;

	private final String SEPARATOR = "\\*\\*\\*";
	private final String PUBLICMESSAGE = "PUBLICMESSAGE";
	private final String ONLINE = "ONLINE";
	private final String OFFLINE = "OFFLINE";

	public RMIClient()
	{
		initComponents();
		thread = new Thread(this);
	}

	@SuppressWarnings("unchecked")
	private void initComponents()
	{
		listClient = new DefaultListModel();
		jScrollPaneMessage = new JScrollPane();
		jTextAreaMessage = new JTextArea();
		jTextUserName = new JTextField();
		jButtonConnect = new JButton();
		jScrollPaneListUser = new JScrollPane();
		jListUser = new JList(listClient);
		jTextSendMessage = new JTextField();
		jButtonSend = new JButton();
		jLabelUserList = new JLabel();

		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setTitle("Chat Client");
		setResizable(false);
		getContentPane().setLayout(null);

		jTextAreaMessage.setColumns(20);
		jTextAreaMessage.setEditable(false);
		jTextAreaMessage.setRows(5);
		jTextAreaMessage.setAutoscrolls(false);
		jScrollPaneMessage.setViewportView(jTextAreaMessage);

		getContentPane().add(jScrollPaneMessage);
		jScrollPaneMessage.setBounds(10, 10, 340, 240);

		jTextUserName.addActionListener(this);
		getContentPane().add(jTextUserName);
		jTextUserName.setBounds(360, 10, 100, 20);

		jButtonConnect.setFont(new java.awt.Font("Times New Roman", 0, 11));
		jButtonConnect.setText("Connect");

		getContentPane().add(jButtonConnect);
		jButtonConnect.setBounds(470, 10, 80, 21);

		jListUser.setToolTipText("List of User");
		jScrollPaneListUser.setViewportView(jListUser);

		getContentPane().add(jScrollPaneListUser);
		jScrollPaneListUser.setBounds(360, 50, 190, 200);

		jTextSendMessage.addActionListener(this);

		getContentPane().add(jTextSendMessage);
		jTextSendMessage.setBounds(10, 260, 340, 30);

		jButtonSend.setFont(new java.awt.Font("Times New Roman", 0, 11));
		jButtonSend.setText("Send");
		jButtonSend.addActionListener(this);

		getContentPane().add(jButtonSend);
		jButtonSend.setBounds(360, 261, 70, 30);

		jLabelUserList.setFont(new java.awt.Font("Arial Black", 0, 11));
		jLabelUserList.setText("User List");
		getContentPane().add(jLabelUserList);
		jLabelUserList.setBounds(360, 30, 55, 17);

		java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
		setBounds((screenSize.width-570)/2, (screenSize.height-330)/2, 570, 330);

		jButtonConnect.addActionListener(this);
		jButtonSend.setEnabled(false);
	}

	public static void main(String args[])
	{
		JFrame.setDefaultLookAndFeelDecorated(true);
		try
		{
			RMIClient rm = new RMIClient();
			rm.setIPAddress(args[0]);
			rm.setPort(Integer.parseInt(args[1]));
			rm.setServer(ipAddress);
			rm.setVisible(true);
		}
		catch (ArrayIndexOutOfBoundsException ae)
		{
			JOptionPane.showMessageDialog(null, "Please insert the port", "ATTENTION", JOptionPane.INFORMATION_MESSAGE);
			System.exit(-1);
		}
	}

	private void setIPAddress(String ipAddress)
	{
		this.ipAddress = ipAddress;
	}

	private void setPort(int port)
	{
		this.port = port;
	}

	private String getIPAddress()
	{
		return ipAddress;
	}

	private int getPort()
	{
		return port;
	}

	private void setServer(String ipAddress)
	{
		try
		{
			c = (Chatting) Naming.lookup("rmi://" + ipAddress + "/ChatService");
		}
		catch (MalformedURLException murle)
		{
			System.out.println();
			System.out.println("MalformedURLException");
			System.out.println(murle);
		}
		catch (RemoteException re)
		{
			System.out.println();
			System.out.println("RemoteException");
			System.out.println(re);
		}
		catch (NotBoundException nbe)
		{
			System.out.println();
			System.out.println("NotBoundException");
			System.out.println(nbe);
		}
		catch (Exception e)
		{
			System.out.println(e);
		}
	}

	public void updateMessage(String username, String message) throws RemoteException
	{
		jTextAreaMessage.append(username + " >> " + message + "\n");
	}

	public void run()
	{
		System.out.println(socket);
		try
		{
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

			while((message = in.readLine()) != null)
			{
				System.out.println(message);
				String[] fromServer = message.split(SEPARATOR);
				if (fromServer[0].equals(ONLINE) || fromServer[0].equals(OFFLINE))
				{
					updateClient(c.getClientList());
				}
				else if (fromServer[0].equals(PUBLICMESSAGE))
				{
					String sender = fromServer[1];
					String content = fromServer[2];
					updateMessage(sender, content);
				}
			}

			in.close();
			socket.close();
		}
		catch(java.net.UnknownHostException e) {}
		catch(IOException e) {}
	}

	public void updateClient(ArrayList allClientList) throws RemoteException
	{
		listClient.clear();
		int i = 0;
		String username;

		for(i=0; i<allClientList.size(); i++)
		{
			username = allClientList.get(i).toString();
			listClient.addElement(username);
		}
	}

	public void actionPerformed(ActionEvent ae)
	{
		if (ae.getActionCommand().equals("Connect") && !jTextUserName.getText().equals(""))
		{
			try
			{
				System.out.println(jTextUserName.getText());
				c.connect(jTextUserName.getText());
				socket = new Socket(ipAddress, port);
				jTextUserName.setEditable(false);
				jButtonConnect.setText("Disconnect");
				System.out.println("You are connect to server");
				thread.start();
				jButtonSend.setEnabled(true);
			}
			catch (RemoteException re) {}
			catch(java.net.UnknownHostException e)
			{
				JOptionPane.showMessageDialog(null, "Can not connect to server " + ipAddress ,"WARNING", JOptionPane.WARNING_MESSAGE);
				System.exit(-1);
			}
			catch(IOException e)
			{
				JOptionPane.showMessageDialog(null, "The server " + ipAddress + " on port " + port + " is not found!", "ERROR",JOptionPane.ERROR_MESSAGE);
				System.exit(-1);
			}
		}
		else if (ae.getActionCommand().equals("Disconnect"))
		{
			try
			{
				c.disconnect(jTextUserName.getText());
				jTextUserName.setText("");
				jTextUserName.setEditable(true);
				listClient.clear();
				jButtonConnect.setText("Connect");
				thread.interrupt();
			}
			catch (RemoteException re) {}
		}
		else if (ae.getSource() == jButtonSend && !jTextSendMessage.getText().equals(""))
		{
			try
			{
				c.sendPublicMessage(PUBLICMESSAGE, jTextUserName.getText(), jTextSendMessage.getText());
				jTextSendMessage.setText("");
			}
			catch (RemoteException re) {}
		}
	}
}

Now after we make the code. Let run the application.

  1. Open your command prompt(under Windows OS).
  2. Compile all the files >>  javac *.java
  3. Compile the ChatImpl.java (it will create a new stub) >> rmic ChatImpl
  4. Run the RMIRegistry >> rmirgistry
  5. You must make sure that your rmiregistrycommand run successfully. If your command does not run, may this command has not recognized by your system yet. If this command does not run, please follow these instructions below (I use Microsoft Windows Vista):
    • Right click on your My Computer and click ‘Properties‘.
    • Click ‘Advanced system settings‘.
    • You must make sure that you already on the ‘Advanced’ tab. Click ‘Environment Variables‘.
    • On the ‘Systems variables‘ section, find ‘Path‘ item and double click and insert your JDK lib directory location on ‘variable value‘ text box. You must make a separator ‘;‘ (without quotes) before insert it (required).
      My JDK lib directory location: ‘C:\Program Files\Java\jdk1.6.0_10\bin
    • Click OK > OK > OK
  6. Open a new command prompt.
  7. Run the server >> java ChatServer YOUR_AVAILABLE_PORT (ex: java ChatServer 4444)
    I hope the response should be like this >> Server is running on port YOUR_AVAILABLE_PORT
  8. Open a new command prompt.
  9. Run a new client >> java RMIClient SERVER_ADDRESS SERVER_PORT (ex: java RMIClient 127.0.0.1 4444)
  10. Insert your name “angga” and client Connect.
    I hope the server response should be like this >> SERVER >> [angga] is now online
    It show that you have connect to server.
  11. Open a new command prompt again.
  12. Run a new client again >> java RMIClient SERVER_ADDRESS SERVER_PORT (ex: java RMIClient 127.0.0.1 4444)
  13. Insert your name “lingga” and client Connect.
    I hope the server response should be like this >> SERVER >> [lingga] is now online
    It show that you have connect to server.
  14. Now you angga and lingga can chat with one server.

You can download the source codes here.

I have develop a new one chatting application using Java RMI too. This application have many server. It allows one client in the different server can talk each other.

Client Chatting

Client Chatting Process

>> java RMIClient SERVER_ADDRESS SERVER_PORT

22 Comments

  1. Planet Orange
    April 26, 2010

    Hallo bro…

    Kunjungan perdana nih…..baru tahu blognya bro Lingga….

  2. aang
    June 3, 2010

    thanks mas, uda aku coba postnya mas yang diatas woooo…. hsilnya keren juga………………………

    tak tunggu postingan yang lainnya mas, tapi tentang java………..

    • Angga Lingga
      June 3, 2010

      @aang yoi sama-sama … iya ntar tak buatin lagi artikel tentan Java. Sering-sering berkunjung ya … :D

  3. Yiannis Gkoufas
    February 9, 2011

    Hi!

    Great RMI example! Helped us a lot!!
    Just one more thing. I think that you should display the RemoteException because in our case the app didn’t work due to the Virtual-Box adapter.

    Thanks a lot,
    Yiannis

  4. Nada
    April 14, 2011

    Thanks great example…but i tried to run it on eclipse and it kept showing me the exception “Attention : insert the port”
    so whats the deal??

    • Angga Lingga
      April 16, 2011

      @Nada I use Command Prompt to compile and test it. Let me try on Eclipe and I will inform again if have fix this one. Thanks for testing my application :)

  5. Henn Claus
    June 25, 2011

    hi,.. i am a student,.. a basic level java programmer,.. very nice shots,…!! I am planning to make a desktop app with java but the database server in the internet,.. would you share what i have to prepare,..? a kind of steps of learning or something like that,…

  6. Loosu
    October 4, 2011

    WOW… WHAT an application … !! really awesome n handy .. :)

    Thanks.

  7. Salvan
    December 30, 2011

    Hi,

    I try to execute the application in Eclipse at Windows 7, i’m starting the Rmiregistry in a console by the command
    >start rmiregistry &
    and in the other console when i execute de command :
    >java ChatServer N° Port
    it give me a problem that “Trouble : Please run rmiregistry”

    Thanks for your interesting code and please response me in the shortest delay

    • Angga Lingga
      February 14, 2012

      I’m so sorry but I use EditPlus when I code this program so I don’t know the problems when you run it by using Eclipse or another IDE.

      Anyway I will try to help you and inform you ASAP when I get the answer.

      • Jad
        November 5, 2013

        I tried it with command prompt and i got the same msg

  8. Shivam Saxena
    August 1, 2012

    Hii, This is nice tuorial and i successfully implemented it. But how can i implement for desktop .Please give me suggestion and give any good link.

  9. Shivam Saxena
    August 1, 2012

    Hii, This is nice tuorial and i successfully implemented it. But how can i implement for desktop .Please give me suggestion and from where we can read proper documentation for chatting application.

  10. Rakesh Parte
    April 10, 2013

    Thanks for this code

  11. DJ
    July 16, 2013

    Nice article. It’s a shame the source download is on a popup-fest farm website.

  12. bhakti
    July 28, 2013

    hey,
    this is exactly what i am looking for
    but i am not allowed to use socket
    i can only use rmi
    i need to make a server client chat where there are many clients and one server
    clients can chat among each other via server i.e client1 sends a message along with ip of client2 to the server and the server forwards this meassage to client2 using the ip address provided by client1
    i am just stuck on this portion i dont know to does the server sends the message to any client using its ip
    and one more thing the client cannot be made a server in itself
    sorry school project limitations

  13. ana
    September 16, 2013

    Develop an RMI application for chatting between client and server , the chatting should stop when both of them say “bye

  14. ana
    September 16, 2013

    this is not my comment….this is my question…….

  15. kishore
    September 17, 2013

    i am not able to connect through intranet

  16. kishore
    September 17, 2013

    i am not able to connect through intranet from different system

  17. Jad
    November 5, 2013

    When I try to run the server, I get Trouble: Please run rmiregistry
    And I already have rmiregistry running
    Is there a specific port that the rmiregistry is running at?
    Please Help

Leave a Reply