Kubernetes official java client two: serialization and deserialization issues

Welcome to my GitHub

https://github.com/zq2599/blog_demos

Problem scenario

This article is the second chapter of "Kubernetes Official Java Client". Before entering the actual coding chapter, there is a problem that requires everyone to have enough understanding to avoid spending energy to deal with this type of problem in the subsequent actual combat. Let's see what it is. problem:

  1. SpringBoot is a commonly used application framework. The applications of the "Kubernetes Official Java Client" series are all based on SpringBoot-2.3.1 version;

  2. The following figure is the official document of SpringBoot-2.3.1.RELEASE. The red box indicates that the default JSON processing library is Jackson:
    Insert picture description here

  3. Seeing this, do you have an ominous hunch: K8S official java client is Google. When it comes to JSON processing, will your own Gson be preferred?

  4. V1HTTPGetAction.java is a data structure commonly used in java clients. It is used to encapsulate the parameters related to the http request. Let 's take a look at the source code. As shown in the figure below, it really uses Gson's annotations:
    Insert picture description here

  5. The IntOrString class mentioned in the figure above should be focused on and has a wide range of uses. Open its source code as shown in the figure below. Please write down the code in the red box 2. The problem mentioned later comes from this:
    Insert picture description here

  • Summary: The default JSON processing class of SpringBoot is Jackson. The Bean in the official K8S java client uses Gson annotations when it comes to JSON-related serialization and deserialization. Therefore, the above Bean instance involves JSON processing in SpringBoot. At this time, there may be problems (we can only say that at this time), for example, the object returned by RestController will be converted to JSON by Jackson;

Recurring problem

  1. Here is a SpringBoot project to demonstrate this problem (the project is named OutsideclusterApplication, which will be explained in detail in the next article). The following code is an http interface response. It can be seen that when the V1PodList instance is returned as an interface, it will be converted to JSON by SpringBoot using Jackson front end:
@RequestMapping(value = "/hello")
    public V1PodList hello() throws Exception {
    
    
        // 存放K8S的config文件的全路径
        String kubeConfigPath = "/Users/zhaoqin/temp/202007/05/config";

        // 以config作为入参创建的client对象,可以访问到K8S的API Server
        ApiClient client = ClientBuilder
                .kubeconfig(KubeConfig.loadKubeConfig(new FileReader(kubeConfigPath)))
                .build();

        Configuration.setDefaultApiClient(client);

        CoreV1Api api = new CoreV1Api();

        // 调用客户端API取得所有pod信息
        V1PodList v1PodList = api.listPodForAllNamespaces(null, null, null, null, null, null, null, null, null);

        return v1PodList;
    }
  1. The above code runs. When the browser accesses the interface, the console throws the following error. The IntOrString.getStrValue method is the paragraph we have seen before. IntOrString actually stores int data, but Jackson executes its getStrValue method:
    Insert picture description here

  2. As for why Jackson will execute the getStrValue method, the length of the reason will not be expanded here. Simply mention that in the BeanPropertyWriter class of the java client, the logic of the selection method is shown in the figure below. The red box shows the determination logic. Here the getStrValue method hits this Logic, if you try to observe with a breakpoint in the red box, you will find that there are many methods that meet this condition:
    Insert picture description here

Ideas to solve the problem

Here I have two ideas to solve the problem:

  1. Allow Jackson to call the correct method during serialization. Take IntOrString as an example. If int data is stored internally at this time, its getIntValue method should be executed;
  2. The Gson annotation is used in Bean, which is intended to use Gson to handle serialization and deserialization operations, so the serialization and deserialization are changed to Gson processing;
  • For the above two ideas, I chose the second one. After all, the first one is too difficult...

Solve the problem

  1. The problem is not difficult to solve, first look at the official SpringBoot-2.3.1.RELEASE document:
    Insert picture description here

  2. Combined with official documents, we have to do two things:

  • First of all, there is Gson in the classpath, this is already there, because the official K8S java client will rely on Gson;
  • Secondly, do not include Jackson in the classpath. In order to achieve this, we need to do the following to exclude the dependency of spring-boot-starter-web (why not directly exclude the Jackson library? You can execute the mvn dependency:tree command to take a closer look at the dependency tree , You will find that the dependence on jackson is not a single relationship):
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
		<exclusions>
			<exclusion>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-starter-json</artifactId>
			</exclusion>
		</exclusions>
</dependency>
  1. It is recommended that you execute the mvn dependency:tree command to take a closer look at the dependency tree of the entire project to ensure that all jackson dependencies have been removed;
  2. Run the above project again, as shown in the figure below, the server no longer reports an error, and the data returned on the page is normal:
    Insert picture description here

Scenes using Jackson

  • Although the above method is feasible, not all projects can stick to Gson and give up Jackson. For projects that use Jackson, please avoid Jackson participating in the serialization and deserialization operations of K8S official java client beans. Take the Controller code that appears above as For example, don't return the V1PodList instance directly. You can choose to serialize it into a JSON string with Gson first, and then return the string to the front end, or you can define your own VO object, convert the V1PodList instance into a VO object and then return;

  • At this point, the issues that should be paid attention to before using the K8S official java client have been figured out. Next, let's enter the wonderful practical chapter and experience the tools carefully prepared by kubernetes official for java programmers;

Guess you like

Origin blog.csdn.net/boling_cavalry/article/details/107503695