views:

177

answers:

3

Hi, can somebody please tell me where i m wrong why this RMI chat application not working,the goal is to achieve decoupleing between client, server and logic by remote objects or serialized objects.


    import javax.swing.*;
    import java.awt.event.*;
    import java.rmi.*;
    import java.rmi.server.*;

    public class ChatClient1 implements ICallback {

        JFrame frame = new JFrame("Chat Client");
        private JTextArea myText;
        private static JTextArea TAUinDispMsg;
        private JScrollPane myTextScroll;
        private JScrollPane TAUinDispMsgScroll;
        private String textString = "";
        private boolean firstMessage = true;
        private static String name = null;

        private static final int HOR_SIZE = 400;
        private static final int VER_SIZE = 150;

        protected static ServerServices chatServer;
        MessageImpl remomsg ; 

        public ChatClient1() throws RemoteException {
            super();

            try {

                this.chatServer = (ServerServices) Naming.lookup("rmi://localhost"
                        + "/ChatServer");

                 UnicastRemoteObject.exportObject(this);
                 chatServer.register(this);
            } catch (Exception e) {
                System.err.println("RemoteException: " + e.getMessage());
                System.exit(0);
            }
            ;

            java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    initComponents();
                }
            });

            frame.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    try {
                        if (name != null) {
                            // chatServer.leave(displayChat, name);
                        }
                    } catch (Exception ex) {
                        TAUinDispMsg.append("Exit failed.");
                    }
                    System.exit(0);
                }
            });
        }


        private void initComponents() {

            myText = new JTextArea();

            myTextScroll = new JScrollPane(myText);
            myTextScroll
                    .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            myTextScroll
                    .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
            myTextScroll.setMaximumSize(new java.awt.Dimension(HOR_SIZE, VER_SIZE));
            myTextScroll.setMinimumSize(new java.awt.Dimension(HOR_SIZE, VER_SIZE));
            myTextScroll
                    .setPreferredSize(new java.awt.Dimension(HOR_SIZE, VER_SIZE));

            myText.addKeyListener(new java.awt.event.KeyAdapter() {
                public void keyTyped(java.awt.event.KeyEvent evt) {
                    textTyped(evt);
                }
            });

            frame.getContentPane().add(myTextScroll, java.awt.BorderLayout.NORTH);

            TAUinDispMsg = new JTextArea();

            TAUinDispMsgScroll = new JScrollPane(TAUinDispMsg);
            TAUinDispMsg.setBackground(new java.awt.Color(200, 200, 200));
            TAUinDispMsgScroll
                    .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
            TAUinDispMsgScroll
                    .setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
            TAUinDispMsgScroll.setMaximumSize(new java.awt.Dimension(HOR_SIZE,
                    VER_SIZE));
            TAUinDispMsgScroll.setMinimumSize(new java.awt.Dimension(HOR_SIZE,
                    VER_SIZE));
            TAUinDispMsgScroll.setPreferredSize(new java.awt.Dimension(HOR_SIZE,
                    VER_SIZE));
            TAUinDispMsg.setEditable(false);

            frame.getContentPane().add(TAUinDispMsgScroll,
                    java.awt.BorderLayout.CENTER);

            frame.pack();
            frame.setVisible(true);
        }

        private void textTyped(java.awt.event.KeyEvent evt) {

             try {
                remomsg = new MessageImpl();
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } 
            char c = evt.getKeyChar();
            if (c == '\n') {
                try {
                    if (firstMessage) {
                        name = textString;
                    //  .join(name);
                        firstMessage = false;
                    } else {
                        remomsg.sendMessage(name, textString);
                    }
                } catch (RemoteException ie) {
                    TAUinDispMsg.append("Failed to send message.");
                    System.err.println(ie.getMessage());
                }
                textString = "";
            } else {
                textString = textString + c;
            }
        }

        @Override
        public void updateClients(final String msg) throws RemoteException {
            // TODO Auto-generated method stub


            System.out.println("Recived Message: " + msg);
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    TAUinDispMsg.append(name + " says: " + msg + "\n");
                }
            });



        }

        public static void main(String args[]) throws RemoteException {

            ChatClient1 ch = null;
            try {
                ch = new ChatClient1();
            } catch (RemoteException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }




 **ICallback.java: interface for callbacks from server to client**


    import java.rmi.*;

    public interface ICallback extends Remote {
        void updateClients(String msg) throws RemoteException;

    }

The object which i want to serve as business logic (gamelogic).

 import java.rmi.*;

        public interface Message extends Remote {

            public void sendMessage(String name, String message) throws RemoteException;

            public void updateClients() throws RemoteException;

        }

Its implementation:

import java.io.Serializable;
import java.rmi.*;
import java.rmi.server.*;
import java.util.ArrayList;
import java.util.Iterator;

import java.util.List;

public class MessageImpl extends UnicastRemoteObject implements Message {
private String name;
private String message;

public MessageImpl() throws RemoteException {
    super();

}
public MessageImpl(ArrayList clients2) throws RemoteException {
    // TODO Auto-generated constructor stub
    this.clients = clients2;

}

static ServerServicesImpl si;
// static ArrayListDemo az;
private List<ICallback> clients = new ArrayList<ICallback>();
// private List<ICallback> clients;

private ServerEngine serverEngine = new ServerEngine();

// Notice this one not called remotely
public void setName(String name) throws RemoteException {
    this.name = name;
}

public String getName() {
    return name;
}

public void setServerList(ServerEngine serverList2) throws RemoteException {
    this.serverEngine = serverList2;

}

public void setClientList(List<ICallback> aclients) throws RemoteException {
    this.clients = (ArrayList<ICallback>) aclients;
    System.err.println("in setClientlist");
}

public ServerEngine getServerList() {
    return serverEngine;
}

// Notice this one not called remotely
public void setMessage(String message) throws RemoteException {
    this.message = message;
}

public String getMessage() {
    return message;
}



public void updateClients() throws RemoteException {


    si = new ServerServicesImpl();
    ArrayList j = si.getClientNames();
    System.out.println(j.size());
    if (clients != null) {
        System.out.println(clients.size());
        for (ICallback aClient : clients) {
            aClient.updateClients(message);
        }

    } else
        System.err.println("Clientlist is empty");

    if (clients != null) {
        System.out.println(j.size());


    } else
        System.err.println("Clientlist is empty");

}

public void sendMessage(String name, String message1)
throws RemoteException {

    setName(name);
    setMessage(message1);
    updateClients();


}

}

class for managaing client threads

import java.lang.*;
import java.util.*;

class ServerEngine {

    private Collection<ICallback> threadList =
                new ArrayList<ICallback>();
    private int counter = 0;

    //  Get the lock on threadList, and wait until the counter is zero - that
    //is, no reads are taking place. Then it's safe to add the thread.

    public synchronized void add(ICallback item) {
        try {
            while (counter > 0) {
                wait();
            }
            threadList.add(item);
        }
        catch (InterruptedException e) {
            System.out.println("Addition interrupted.");
        }
        finally{
            notifyAll();
        }
    }

    // Similarly for removal.
    public synchronized void remove(ICallback item) {
        try {
            while (counter > 0) {
                wait();
            }
            threadList.remove(item);
        }
        catch (InterruptedException e) {
            System.out.println("Removal interrupted.");
        }
        finally {
            notifyAll();
        }
    }

    // Similarly for changing counter
    public synchronized void incCounter() {
        counter++;
        notifyAll();
    }

    public synchronized void decCounter() {
        counter--;
        notifyAll();
    }

    //This is because it would be too much effort to make this class implement
    //Collection, return it's own Iterator etc. etc...\
    //Note it is *not* a bug that it isn't synchronized
    public Collection getCollection() {
        return threadList;
    }
}

Service.java: server the object which will be register and will bind to.

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

public interface ServerServices extends Remote {

    // added so client can register self with server for callbacks
    public void register(ICallback newClient) throws RemoteException;

    public ArrayList getClients() throws RemoteException;

}

ServerServicesImpl.java: implementation side of server

import java.io.Serializable;
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;

class ServerServicesImpl extends UnicastRemoteObject implements ServerServices,
        Serializable {

    String message;
    MessageImpl msgimpl;
    static Vector data = new Vector();

    private static ArrayList Aclients = new ArrayList<ICallback>();
    private static ArrayList testlist;

    public ServerServicesImpl() throws RemoteException {
        super();
        testlist = new ArrayList();

    }

    public synchronized void register(ICallback newClient)
            throws RemoteException {
        data.addElement(newClient);
        Aclients.add(newClient);
        // //serverEngine.add(newClient);

        testlist.add("testing");
        System.out.println("testlist size =" + testlist.size());

        System.out.println(Aclients.size());

        setClientList(Aclients);

    }

    ArrayList getClientNames() {
        // Aclients.add(ic);
        System.out.println("vector size =" + data.size());
        System.out.println("testlist size =" + testlist.size());
        System.out.println(" Aclientlist size =" + Aclients.size());
        return Aclients;
    }

    public void setClientList(ArrayList aclients2) {
        this.Aclients = aclients2;
    }

}

   // the server  which will publish the above remote object

    import java.net.MalformedURLException;
    import java.rmi.*;


    public class ServiceLoader
    {

        public static void main(String[] args)
        {
            try
            {
                // Install a security manager
                System.setSecurityManager(new RMISecurityManager());
                ServerServicesImpl obj = new ServerServicesImpl();

                Naming.rebind("ChatServer", obj);


                System.out.println("ServiceLoader running.");

            }
            catch (MalformedURLException e)
            {
                System.err.println(e.getMessage());
            }
            catch (RemoteException e)
            {
                System.err.println(e.getMessage());
            }
        }

    }
+1  A: 

your question is not clear enough but:

debug your code, or put some logs (simply System.out.println) before the line that you are getting NPE. maybe you List is still null.

public void updateClients() throws RemoteException {
    **if (serverList != null) {**
        for (TTTClientRemote aClient : serverList) {
           aClient.updateClients("slam");
        }
    }
}
mohammad shamsi
@jibbylala: if its null, then yes its a problem, because you are trying to iterate over a null Collection and it will throw NPE.
mohammad shamsi
i wanted to iterate the list which is coming from other remoteobject
Static Void Main
@jibbylala Note that Java `null` is not like a Lisp `nil`. It doesn't mean you have an empty List object, it means you have nothing at all. You iterate over `null` or invoke any method on it for that matter.
Aaron Novstrup
thanks a lot but the application isn't working as intented :-\
Static Void Main
@mohammad BTW, you can't put markup inside code blocks
TheLQ
+2  A: 

Change

private List<TTTClientRemote> serverList;

To:

private List<TTTClientRemote> serverList = new ArrayList<TTTClientRemote>();

Or initialize it somewhere before the for() in updateClients();

Zenzen
when i will reinstantiate again i will not loose the reference which i m getting from other object(TTTServiceImpl1)
Static Void Main
A: 

As answered by Ernest Friedman-Hill at link texthttp://www.coderanch.com/t/508960/java/java/pass-reference:

The root of problem was the fact that RMI doesn't support pass by reference , so making the message class serializable and creating the remote instance of ServerServices in that serializable class can make this application work

OR

creating the remote instance of Message class in client class and publishing that from RMI registry can also work.

In this code the local references were used instead of remote, so it was getting the 0 elements in the list from Serverservices class.

thanks again to: Ernest Friedman-Hill.

Static Void Main