Enumeration types are not allowed for RPC interfaces. Why?

preface

Before we talk about this, let's take a look at the relevant background knowledge.

Introduction to RPC

RPC is short for Remote Procedure Call. Remote service call. Simply put, one node provides services (called server) and one node consumes services (client).

RPC communication mode

The communication protocol between the server and client of PRC is TCP/IP. However, you must have doubts. How does the client know the class definition in the service provided by the server? The answer is serialization and deserialization. The function of serialization: convert the structure class information into bytecode for transmission between different services. Deserialization: restore the received information into structure information according to the Convention.

Practical analysis

Emerald flower above

Don't say much. Go straight to the figure above and code it.

In the figure above, the client provides a service that can query the combat effectiveness of the role, which is packaged for the client to view and consume. However, the server secretly upgraded the second-party package version to 2.0 without telling the client. There are few cruel words. It belongs to yes.

Code on Cuihua

Enumeration class for version 1.0. It can be seen that the monkey king is still better than the third prince, ranking in the front.

1.0

public enum RoleEnum {
    WU_KONG(0,"Sun WuKong"),
    NE_ZHA(1,"nezha");
    int code;
    String desc;

    RoleEnum(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

OK. Let's simulate serialization and deserialization. Note: in RPC services, enumeration classes are generally serialized into names, and deserialization is performed through valueOf().

  // Client, serialize RoleEnum.
        String jsonString = JSON.toJSONString(RoleEnum.values());
        System.out.println("serialize");
        System.out.println(jsonString);
        //Deserialization
        List<RoleEnum> roleEnumList = JSON.parseArray(jsonString, RoleEnum.class);
        System.out.println("Deserialization");
        roleEnumList.stream().forEach(e -> System.out.println(e.toString()));

Console after operation:

serialize
["WU_KONG","NE_ZHA"]
Deserialization
WU_KONG
NE_ZHA

As you can see. When it is version 1.0, the client can correctly analyze who is the first.

2.0

OK. Next, the server secretly added a heavyweight player, Zhu Bajie, to the challenge arena.
Let's look at enumeration classes

public enum RoleEnum {
    WU_KONG(0,"Sun WuKong"),
    NE_ZHA(1,"nezha"),
    BA_JIE(2,"Zhu Bajie");
    int code;
    String desc;

    RoleEnum(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

I'm lazy here. After the server upgrades the second-party package version 2.0, the serialized RoleEnum form is:

serialize
["WU_KONG","NE_ZHA","BA_JIE"]

OK, start deserialization

public class Test01 {
    public static void main(String[] args) {

        // Client, serialize RoleEnum.
        //String jsonString = JSON.toJSONString(RoleEnum.values());
        System.out.println("serialize");
        String jsonString = "[\"WU_KONG\",\"NE_ZHA\",\"BA_JIE\"]";
        System.out.println(jsonString);
        //Deserialization
        List<RoleEnum> roleEnumList = JSON.parseArray(jsonString, RoleEnum.class);
        System.out.println("Deserialization");
        roleEnumList.stream().forEach(e -> System.out.println(e.toString()));

    }
}

Start the challenge arena and execute... Eh, why did you report wrong.

serialize
["WU_KONG","NE_ZHA","BA_JIE"]
Deserialization
WU_KONG
NE_ZHA
Exception in thread "main" java.lang.NullPointerException
	at com.pinfine.test.Test01.lambda$main$0(Test01.java:26)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1380)
	at java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:580)
	at com.pinfine.test.Test01.main(Test01.java:26)

It can be seen from the error message that a null pointer appears. That is, the error occurred when calling the valueOf() method of the enumeration class. It's because Bajie only provides a 2.0 second-party package on the server, but the client is still version 1.0. Naturally, there is no Bajie in it. According to the name, the Bajie building can not be parsed naturally.

proposal

1. When RPC provides services, it is forbidden to return enumeration classes as parameters or encapsulated in POJO objects.
2. For enumeration classes, they can be encapsulated into an object instead.

Keywords: Java network rpc

Added by lazaruz on Sat, 11 Dec 2021 12:12:39 +0200