University of Cincinnati logo and link  
Making a Serializable Object
 
  UC ingotCurrently we send a message to the server with a user for whom that message is intended.  We send these both as Strings.  But proper object oriented design would tell us to send one object instead of a series of Strings and primitives.  So let's make an object, called Message, that has our two String attributes plus one more: String sender.  This object will implement serializable.  Then, when we call sendMessage on the server, we'll pass it this Message object. 
  • Class Message:
/*
 * Message.java
 *
 * Created on May 8, 2003, 11:20 AM
 */

package chat;

/**
 *
 * @author  default
 * @version 
 */
public class Message implements java.io.Serializable {

    // Create our attributes.
    String message = new String();
    String destination = new String();
    String user = new String();
    
    /** Creates new Message */
    public Message() {
    }
    
    /** Creates a message with properties. */
    public Message(String message, String destination, String user) {
        this.message = message;
        this.destination = destination;
        this.user = user;
        
        System.out.println("Message Created.");
    }
    
    public String getMessage() {
        return message;
    }
    
    public void setMessage(String message) {
        this.message = message;
    }
    
    public String getDestination (){
        return destination;
    }
    
    public void setDestination (String destination) {
        this.destination = destination;
    }
    
    public String getUser() {
        return user;
    }
    
    public void setUser(String user) {
        this.user = user;
    }

}
 

  • New method on Chat:
/*
 * Chat.java
 *
 * Created on April 28, 2003, 11:55 PM
 */

package chat;

import java.rmi.*;

/** Remote interface.
 *
 * @author default
 * @version 1.0
 */
public interface Chat extends java.rmi.Remote {

    public void login (String user, String password) throws RemoteException;
    
    public void sendMessage (String message, String user) throws RemoteException;
    
    public void sendMessage (Message message) throws RemoteException;

}
 

  • Convenience method on ChatImpl:
package chat;

/*
 * ChatImpl.java
 *
 * Created on April 28, 2003, 11:48 PM
 */

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

/** Unicast remote object implementing Chat interface.
 *
 * @author default
 * @version 1.0
 */
public class ChatImpl extends java.rmi.server.UnicastRemoteObject implements Chat {

    BulletinBoard board;
    
    /** Constructs ChatImpl object and exports it on default port.
     */
    public ChatImpl() throws RemoteException {
        super();
        // Fire up our JFrame here.
        board = new BulletinBoard();
        board.show();
    }

    /** Constructs ChatImpl object and exports it on specified port.
     * @param port The port for exporting
     */
    public ChatImpl(int port) throws RemoteException {
        super(port);
    }

    /** Register ChatImpl object with the RMI registry.
     * @param name - name identifying the service in the RMI registry
     * @param create - create local registry if necessary
     * @throw RemoteException if cannot be exported or bound to RMI registry
     * @throw MalformedURLException if name cannot be used to construct a valid URL
     * @throw IllegalArgumentException if null passed as name
     */
    public static void registerToRegistry(String name, Remote obj, boolean create) throws RemoteException, MalformedURLException{

        if (name == null) throw new IllegalArgumentException("registration name can not be null");

        try {
            Naming.rebind(name, obj);
        } catch (RemoteException ex){
            if (create) {
                Registry r = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
                r.rebind(name, obj);
            } else throw ex;
        }
    }

    /** Main method.
     */
    public static void main(String[] args) {
        System.setSecurityManager(new RMISecurityManager());

        try {
            ChatImpl obj = new ChatImpl();
            registerToRegistry("ChatImpl", obj, true);
        } catch (RemoteException ex) {
            ex.printStackTrace();
        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        }
    }
    
    public void login(String user, String password) {
    }
    
    public void sendMessage(String message, String user) {
        System.out.println("Message: " + message + " User: " + user);
        // call method on JFrame to add this to our list.
        board.addMessage(message);
    }
    
    /** For sake of time, just make a convenience method to the existing sendMessage method. */
    public void sendMessage(Message message) {
        sendMessage(message.getMessage(), message.getUser());
    }
}
 

  • Slight change in ChatForm:
/*
 * ChatForm.java
 *
 * Created on May 1, 2003, 1:18 AM
 */

package chat;

import java.rmi.*;
import java.rmi.registry.*;

/**
 *
 * @author  default
 */
public class ChatForm extends javax.swing.JFrame {

    // Globally visible reference to the stub via interface.
    Chat chat;
    
    /** Creates new form ChatForm */
    public ChatForm() {
        // Get the stub.  
        // Change the URL if connecting to a different machine.
        try {
            chat = (Chat)Naming.lookup("rmi://localhost/ChatImpl");
        } catch (Exception e) {
            System.out.println("Exception while attempting to lookup ChatImpl.  Message: " + e.getMessage());
            e.printStackTrace();
        }
        
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents() {
        jLabel1 = new javax.swing.JLabel();
        jPanel1 = new javax.swing.JPanel();
        btnSend = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        txtMessage = new javax.swing.JTextArea();
        
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                exitForm(evt);
            }
        });
        
        jLabel1.setText("Send a Message to the Bulletin Board");
        getContentPane().add(jLabel1, java.awt.BorderLayout.NORTH);
        
        btnSend.setText("Send");
        btnSend.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnSendActionPerformed(evt);
            }
        });
        
        jPanel1.add(btnSend);
        
        getContentPane().add(jPanel1, java.awt.BorderLayout.SOUTH);
        
        txtMessage.setRows(4);
        jScrollPane1.setViewportView(txtMessage);
        
        getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);
        
        pack();
    }

    private void btnSendActionPerformed(java.awt.event.ActionEvent evt) {
        // Send a message to the bulletin board.
        try {
            // Make a message.  Hardcode some thing in until we prompt the user for this information.
            Message message = new Message(txtMessage.getText(), "BulletinBoard", "RMI User");
            // chat.sendMessage(txtMessage.getText(), "BulletinBoard");
            chat.sendMessage(message);
        } catch (Exception e) {
            System.out.println("RemoteException while attempting to send message to Bulletin Board.  Message: " + e.getMessage());
        }
        
        
    }

    /** Exit the Application */
    private void exitForm(java.awt.event.WindowEvent evt) {
        System.exit(0);
    }

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        
        // Set the security policy and security manager.
        System.setProperty("java.security.policy", "client.policy");
        System.setSecurityManager(new RMISecurityManager());
               
        new ChatForm().show();
    }
 

    // Variables declaration - do not modify
    private javax.swing.JLabel jLabel1;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JButton btnSend;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea txtMessage;
    // End of variables declaration

}

  • I had some trouble deploying this initially.  I was getting AbstractMethodError, which indicates one class is out of synch with the others.  In other words, perhaps one class was not copied once it was updated.  I verified a number of items, deleted and recopied all of my classes, and it finally worked.
  • The view does not change, except for informational messsages printed to standard output, so I'll spare the screen captures.
 Passing Remote Objects