Dears,

This blog is moved to a new blog at:

The new update will be found at that new blog, please follow it!
This blog is no more updated.
Thanks for your visit!

Monday, September 16, 2013

Distributed programming with RMI

Objective
This topic will help you to program an application of RMI (Remote Method Invocation) technology. The case study is always a login example.


Assume that we would like create an application as following description:
- A remote server RMI which provides a method enabling to check login (verify whether an username/password logged in is correct in a database)
- The RMI server also manages a database which contains a table of users including at least two columns of username and password.
- At the client side, a GUI is provided which enables user to enter username/password lo login, and, once logged in, this interface will display the login results (success or fail).
- The client will call the remote method from server RMI to verify whether an username/password logged in is correct

Application Design
So the classes for the server side are:
- User (entity class): represents the username/password that a client entered and then, need to be verified
- RMILoginServerView (view class): is a simple view class with console interface. Its mission is to display the server status and show errors if they occur
- RMILoginInterface: an interface of RMI method. This includes an interface of the method checkLogin(User): String
- RMILoginServerControl (control class): a control class for defining the whole method of checkLogin(User): String, and then register this method to the RMI Registry



At the client side, there are following classes:
- using the same class of User as that of the server side
- RMILoginClientView (view class): this class plays the role of GUI interface enabling user to enter username/password and see the login results
- RMILoginClientControl (control class): this gets login information entered by user, calls the remote method from server RMI to verify this login and return the results to the view class to display.



And the sequence of activities between two sides of application are (assume that the server already registed its method):
1. At the client side, an user enters his username and password to login
2. The RMILoginClientView receives these information and then sends to User class to pack them in to an User entity
3. The User class packs them in to an User entity end return it to the view class
4. The view class will forward this entity to control to verify the login
5. The client control searches the remote method of checkUser(User) from remote server RMI
6. The remote RMI server (control) return a stub of the called method
7. The client control calls the method to verify the login
8. The client control return the login results to the view class
9. The view class displays the login results (success or fail) to the user.



User.java
import java.io.Serializable;

public class User implements Serializable{
    private String userName;
    private String password;
   
    public User(){       
    }
   
    public User(String username, String password){
        this.userName = username;
        this.password = password;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

RMILoginServerView.java
package rmi.server;

public class RMILoginServerView {
    public RMILoginServerView(){       
    }
   
    public void showMessage(String msg){
        System.out.println(msg);
    }
   
}

RMILoginInterface.java
package rmi.server;
import java.rmi.Remote;
import java.rmi.RemoteException;
import rmi.server.User;

public interface RMILoginInterface extends Remote{
    public String checkLogin(User user) throws RemoteException;
}

RMILoginServerControl.java
package rmi.server;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import rmi.server.User;

public class RMILoginServerControl extends UnicastRemoteObject implements RMILoginInterface{
    private int serverPort = 3232;
    private Registry registry;
    private Connection con;
    private RMILoginServerView view;
    private String rmiService = "rmiLoginServer";
   
    public RMILoginServerControl(RMILoginServerView view) throws RemoteException{
        this.view = view;
        view.showMessage("RMI server is running...");
       
       try{
           getDBConnection("hotelmanagement", "root", "12345678");
            registry = LocateRegistry.createRegistry(serverPort);
            registry.rebind(rmiService, this);
        }catch(RemoteException e){
            throw e;
        }
    }
   
    public String checkLogin(User user) throws RemoteException{
        String result = "";
        if(checkUser(user))
            result = "ok";
        return result;
    }
   
    private void getDBConnection(String dbName, String username, String password){
        String dbUrl = "jdbc:mysql://localhost/" + dbName;
        String dbClass = "com.mysql.jdbc.Driver";

        try {
            Class.forName(dbClass);
            con = DriverManager.getConnection (dbUrl, username, password);
        }catch(Exception e) {
            view.showMessage(e.getStackTrace().toString());
        }
    }
   
    private boolean checkUser(User user) {
        String query = "Select * FROM users WHERE username ='" + user.getUserName()
                + "' AND password ='" + user.getPassword() + "'";

        try {
            Statement stmt = con.createStatement();
            ResultSet rs = stmt.executeQuery(query);

            if (rs.next()) {
              return true;
            }
        }catch(Exception e) {
            view.showMessage(e.getStackTrace().toString());
        }         return false;
      }



    public static void main(String[] args) {
        RMILoginServerView view       = new RMILoginServerView();
        try{
            RMILoginServerControl control = new RMILoginServerControl(view); 
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}


RMILoginClientView.java
package rmi.client;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

public class RMILoginClientView extends JFrame implements ActionListener{
    private JTextField txtUsername;
    private JPasswordField txtPassword;
    private JButton btnLogin;
   
    public RMILoginClientView(){
        super("RMI Login MVC");
       
        txtUsername = new JTextField(15);
        txtPassword = new JPasswordField(15);
        txtPassword.setEchoChar('*');
        btnLogin = new JButton("Login");
       
        JPanel content = new JPanel();
        content.setLayout(new FlowLayout());
        content.add(new JLabel("Username:"));
        content.add(txtUsername);
        content.add(new JLabel("Password:"));
        content.add(txtPassword);
        content.add(btnLogin);
                 
        this.setContentPane(content);
        this.pack();
       
        this.addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent e){
                System.exit(0);
            }
        });
    }

    public void actionPerformed(ActionEvent e) {
    }
   
    public User getUser(){
        User model = new User(txtUsername.getText(), txtPassword.getText());
        return model;       
    }
   
    public void showMessage(String msg){
        JOptionPane.showMessageDialog(this, msg);
    }
   
    public void addLoginListener(ActionListener log) {
          btnLogin.addActionListener(log);
        }
}

RMILoginClientControl.java
package rmi.client;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import rmi.server.RMILoginInterface;


public class RMILoginClientControl {
    private RMILoginClientView view;
    private String serverHost = "localhost";
    private int serverPort = 3232;
    private RMILoginInterface rmiServer;
    private Registry registry;
    private String rmiService = "rmiLoginServer";
   
    public RMILoginClientControl(RMILoginClientView view){
        this.view = view;       
        view.addLoginListener(new LoginListener());
       
        try{
            registry = LocateRegistry.getRegistry(serverHost, serverPort);
            rmiServer =    (RMILoginInterface)(registry.lookup(rmiService));
        }catch(RemoteException e){
            view.showMessage(e.getStackTrace().toString());
            e.printStackTrace();
        }catch(NotBoundException e){
            view.showMessage(e.getStackTrace().toString());
            e.printStackTrace();
        }
    }
   
    class LoginListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            try {
                User model = view.getUser();
                if(rmiServer.checkLogin(model).equals("ok")){
                    view.showMessage("Login succesfully!");
                }else{
                    view.showMessage("Invalid username and/or password!");
                }               
            } catch (Exception ex) {
                view.showMessage(ex.getStackTrace().toString());
                ex.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        RMILoginClientView view       = new RMILoginClientView();
        RMILoginClientControl control = new RMILoginClientControl(view);       
        view.setVisible(true);
    }
}



No comments:

Post a Comment