Use of RMI in Java

Posted by Mgccl on Fri, 11 Feb 2022 17:52:06 +0100

RMI introduction

RMI (Remote Method Invocation) model is a distributed object application. Using RMI technology, objects in one JVM can call object methods in another JVM and obtain the call results. The other JVM here can be on the same computer or a remote computer. Therefore, RMI means a Server side and a Client side.

The Server side usually creates an object and makes it accessible remotely.

  • This object is called a remote object.
  • The Server side needs to register this object, which can be accessed remotely by the Client.

When the Client side calls the method on the object that can be accessed remotely, the Client side can communicate with the Server side and transfer information to each other.

When it comes to building distributed services, it is very convenient to use RMI. It is not the same as the idea of building distributed services.

How RMI works

It is necessary to know the working principle of RMI and RMI Server before writing RMI code?

The figure below can help us understand the workflow of RMI.

As can be seen from the figure, the Client side has something called Stub, which is sometimes called Stub. It is the proxy object of RMI Client. The main function of Stub is to construct an information block when requesting remote methods, and RMI protocol will send this information block to the Server side.

This information block consists of several parts:

  • Remote object identifier.
  • Description of the method called.
  • Parameter value after grouping (object serialization is used in RMI protocol).

Since the Client side has a Stub that can construct information blocks and send them to the Server side, the Server side must have an object that receives this information quickly, which is called Skeleton.

Its main work is:

  • Analyze the calling object identifier and method description in the information cache, and call the specific object method on the Server side.
  • Get the return value or exception value of the call.
  • Group the returned values and return them to the client Stub

Here, you can get the result of a call from the Client side to the Server side.

RMI development

Through the above introduction, we know the concept of RMI and the working principle of RMI. Next, we introduce the development process of RMI.

This will be demonstrated through a scenario. It is assumed that the Client needs to query the user information, and the user information exists in the Server, so the RMI protocol interface is opened on the Server for the Client to call and query.

RMI Server

The Server side mainly constructs a class User that can be transmitted and a class UserService that can be accessed remotely. At the same time, this object should be registered with RMI and opened to the client.

  1. Define the server interface (you need to inherit the Remote class, and the method needs to throw RemoteException).

    package com.wdbyte.rmi.server;
    
    import java.rmi.Remote;
    import java.rmi.RemoteException;
    
    
    /**
     * RMI Server
     *
     * @author www.wdbyte.com
     * @date 2021/05/08
     */
    public interface UserService extends Remote {
    
        /**
         * Find users
         * 
         * @param userId
         * @return
         * @throws RemoteException
         */
        User findUser(String userId) throws RemoteException;
    }
    

    The User object is defined in step 3.

  2. Implement the server interface (you need to inherit the UnicastRemoteObject class to implement the defined interface).

    package com.wdbyte.rmi.server;
    
    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;
    
    /**
     * @author www.wdbyte.com
     * @date 2021/05/08
     */
    public class UserServiceImpl extends UnicastRemoteObject implements UserService {
    
        protected UserServiceImpl() throws RemoteException {
        }
    
        @Override
        public User findUser(String userId) throws RemoteException {
            // Load in query
             if ("00001".equals(userId)) {
                User user = new User();
                user.setName("Jin Yong");
                user.setAge(100);
                user.setSkill("writing");
                return user;
            }
            throw new RemoteException("No one was found");
        }
    }
    
  3. Define the transmitted object, which needs to implement the Serializable interface.

    The class to be transmitted must implement the serialization interface, otherwise an error will be reported during transmission. A simple tutorial on how to generate serialVersionUID in IDEA is also attached at the end of the article.

    package com.wdbyte.rmi.server;
    
    import java.io.Serializable;
    
    /**
     *
     * @author www.wdbyte.com
     * @date 2021/05/08
     */
    public class User implements Serializable {
    
        private static final long serialVersionUID = 6490921832856589236L;
    
        private String name;
        private Integer age;
        private String skill;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getSkill() {
            return skill;
        }
    
        public void setSkill(String skill) {
            this.skill = skill;
        }
        
        @Override
        public String toString() {
            return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", skill='" + skill + '\'' +
                '}';
        }
    }
    
  4. Register the remote object and start the server program.

    The server binds the UserService object as a remote access object, and the port is set to 1900 at startup.

    package com.wdbyte.rmi.server;
    
    import java.rmi.Naming;
    import java.rmi.registry.LocateRegistry;
    
    /**
     * RMI Server end
     *
     * @author https://www.wdbyte.com
     * @date 2021/05/08
     */
    public class RmiServer {
    
        public static void main(String[] args) {
            try {
                UserService userService = new UserServiceImpl();
                LocateRegistry.createRegistry(1900);
                Naming.rebind("rmi://localhost:1900/user", userService);
                System.out.println("start server,port is 1900");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

RMI Client

Compared with the Server side, the Client side is much simpler. Directly introduce the classes that can be accessed remotely and need to be transmitted. You can initiate a call through the port and the address bound on the Server side.

package com.wdbyte.rmi.client;

import java.rmi.Naming;

import com.wdbyte.rmi.server.User;
import com.wdbyte.rmi.server.UserService;

/**
 * @author https://www.wdbyte.com
 * @date 2021/05/08
 */
public class RmiClient {
    public static void main(String args[]) {
        User answer;
        String userId = "00001";
        try {
            // lookup method to find reference of remote object
            UserService access = (UserService)Naming.lookup("rmi://localhost:1900/user");
            answer = access.findUser(userId);
            System.out.println("query:" + userId);
            System.out.println("result:" + answer);
        } catch (Exception ae) {
            System.out.println(ae);
        }
    }
}

RMI test

Start the Server side.

start server,port is 1900

Start the Client side.

query:00001
result:User{name='Jin Yong', age=100, skill='writing'}

If the Client side passes in a userId that does not exist.

java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
	java.rmi.RemoteException: No one was found

Generation of serialVersionUID

Generate serialVersionUID in IDEA, open the setting, and check it as shown in the figure below.

Select the class to generate serialVersionUID and press the smart prompt shortcut key.

reference resources

[1] https://docs.oracle.com/javase/tutorial/rmi/overview.html

subscribe

Can focus Unread code blog Or wechat search Unread code 」.

Articles will be updated in the same way as blogs and official account numbers.

Topics: Java Distribution Microservices