Architectural evolution of Zhuanzhuan quality inspection desktop application

Quality inspection is an important part of Zhuanzhuan's contract fulfillment system. By conducting comprehensive inspections on the software and hardware functions, appearance and quality of mobile phones, tablets, notebooks, headphones, watches and other categories of goods, we ensure quality for buyers and sellers. Make second-hand transactions more transparent and reliable, and promote green consumption.

In the quality inspection process, through standardized production lines, combined with automation equipment, quality inspection APPs, desktop applications, etc., a comprehensive and credible "quality inspection report" is finally output and presented to users. Among them, desktop applications play a decisive role. This article will focus on the evolution and implementation of desktop application architecture.

1 background

The desktop application for quality inspection was mainly built with Qt in the early stage, with C/C++ providing underlying support. C/C++ developers are responsible for all development iterations of the view layer, application layer, and underlying capability support of these desktop applications. Secondly, with the continuous development of business, some desktop applications have gradually exposed problems of poor scalability and difficulty in iteration.

In the Zhuanzhuan quality inspection technical team, in addition to C/C++ development students, there are also mature front-end and Java back-end. In summary: for the view layer, the front-end technology ecosystem, and the technical experience of the developers, in the view layer It has great advantages in development; in terms of application layer, the advantages of Java technology ecosystem are self-evident. At the same time, Java back-end students have a relatively comprehensive and in-depth understanding of the overall business and system. In short, Java students are very good at application. In terms of layer architecture design and implementation, it is very suitable.

In summary, based on the team's actual situation, the author's team proposed a new technical architecture for desktop applications - EJC (Electron, Java, C/C++). The main advantages of this architecture are:

  • Allow C/C++ development students to focus more on the research of underlying capabilities and exert greater value.
  • Electron is essentially a front-end technology stack. Java students understand the overall business better and are better at application layer design experience; and front-end and Java resources are easier to flexibly deploy.
  • Electron and Java themselves are cross-end, which has good advantages for the subsequent integration of all ends of the quality inspection desktop application (Windows & Mac).

2 EJC architecture

Simply put, the EJC technical architecture is: Electron (view layer/user layer), Java (application layer), C/C++ (basic capability layer).

2.1 Electron

Electron is a framework based on Chromium and Node.js, a set of cross-platform desktop applications for Windows, macOS and Linux.

  • It is essentially a front-end technology stack with a built-in Chromium kernel so that applications have the latest web standards. Developers can focus on the logic and interface design of the application, and no longer have to deal with browser compatibility operations.
  • Full package updates and hot updates keep the program up-to-date, similar to the pleasure of a hybrid mobile application (Hybrid APP).
  • A secure cross-platform operating environment can effectively reduce the probability of program crashes and system errors, and achieve more reliable and stable applications.
  • The rich API, supported by C/C++ capabilities, makes the combination of software and hardware smoother and further expands the capabilities.

2.2 Java

Java application layer, mainly includes:

  • Communication module: Provides communication capabilities based on HTTP, WebSocket and other protocols.
  • The underlying interactive module: encapsulates Java's technology (JNI/JNA) for calling local code (dynamic library).
  • Data storage: Use the lightweight database SQLite to persist data and provide basic capabilities for high availability and fault tolerance of data.
  • Event listening: The event and listening mechanism based on Spring implements an event-driven programming model, which has the advantages of loose coupling, high scalability and testability.
  • Business module: necessary business logic processing.
  • Monitoring module: records the client’s real-time operating parameters, hardware abnormalities and other data, and reports them to the cloud regularly.
  • Configuration management: regularly pull the latest configuration from the cloud and overwrite the local configuration.
  • Scheduling strategy: Based on the historical status of the device, predict whether hardware (such as USB communication ports, USB hubs and other equipment on the shelf) will malfunction. When a fault is determined, other devices can be prioritized and the fault information reported.

2.3 C/C++

Basic capability layer, implementation of core SDK. Provides low-level common capabilities with Windows, IOS, Android, cameras, robotic arms, etc.

Based on the above description, during the transfer quality inspection, the EJC technical architecture presented by the author is as follows:

EJC architecture diagram

The following focuses on introducing the front-end communication module and underlying communication module of the Java application layer.

2.4 Front-end communication module

The Java application layer is compatible with the communication methods of HTTP protocol and WebSocket protocol. Next, we will introduce several options for communicating with the front-end and our selection and considerations in the EJC architecture:

2.4.1 HTTP short polling

The client periodically sends requests to the server to obtain the latest data, which causes a waste of server and network resources. Suitable for scenarios with low real-time requirements: This mechanism is used when the Java client pulls configurations from the cloud.

2.4.2 HTTP long polling

Compared with HTTP short polling, HTTP long polling can avoid the client from frequently sending requests to the server, saving the cost of network and server resources, while achieving more timely and reliable data push.

2.4.3 SSE(Server-Sent Events)

It is essentially an HTTP long connection. The server sends not a data packet to the client, but a stream in the format of text/stream, so the client will not close the connection and will always wait for the server to send a new data stream. . Suitable for scenarios where the server only needs to push events to the client in one direction.


In actual application scenarios, the server only needs to push information once to the front end (for example, the front end calls the Java server to obtain system hardware configuration information). We choose SSE as the communication method between the front and back ends, which has the following advantages:

  • Better performance than http short polling.
  • More reliable than http long polling.
  • More lightweight than WebSocket.
  • Can be used on existing infrastructure and technology without requiring any additional configuration or deployment.

2.4.4 WebSocket

WebSocket is a two-way communication protocol based on TCP that enables real-time communication. It is suitable for systems with high real-time requirements and duplex communication. In actual applications, such as the privacy clearing tool, it only takes 3 to 5 seconds from inserting the phone to completing the privacy clearing. Quality inspectors need to see changes in the phone's status in real time. At this time, we choose Websocket to push the data status in real time. Go to the front end for display.

2.5 Bottom communication module

There are two ways for Java to call C/C++: JNI (Java Native Interface) and JNA (Java Native Access), both of which are technologies used in Java to call the local underlying SDK.

The following is a simple code example (getting the IOS device name) to illustrate how Java calls the underlying SDK. In order to save space, only some key codes are shown.

2.5.1 Introduction and use of JNI

A standard interface provided by the Java language, which provides a set of functions and data types that allow Java applications to call and be called by the C/C++ language. JNI enables interaction with the C/C++ language by writing native methods.

  • Use the native keyword to declare native methods.
public class JniDemo {
    
    
    /**
     * 获取IOS设备的名称
     * @param udid 设备UDID
     * @return 设备名称
     */
    public native String getDeviceNameByUDID(String udid);
}
  • Use the javah command to generate the corresponding C language header file for the native method in the code.
> javah JniDemo
// JDK10+已经移除了javah命令工具,使用以下命令
> javac JniDemo.java -h outputDir
  • After executing the above command, a C/C++ header file named JniDemo.h will be generated.
#include <jni.h>
/* Header for class JniDemo */

#ifndef _Included_JniDemo
#define _Included_JniDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * 包含了 getDeviceNameByUDID 方法的声明
 * Class:     JniDemo
 * Method:    getDeviceNameByUDID
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_JniDemo_getDeviceNameByUDID
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif
  • C/C++ implements the header file to implement the Java_JniDemo_getDeviceNameByUDID method and compiles it into a dynamic library.
#include "jnidemo.h"

JNIEXPORT jstring JNICALL Java_JniDemo_getDeviceNameByUDID(JNIEnv *env, jobject, jstring udid)
{
    
    
    string udid_cpp = jstringTostring(env, udid);
    LHW_INFO("udid_cpp = " << udid_cpp);
    IOS_Device_Interface idi;
    string device_name = idi.get_device_name_by_udid(udid_cpp);
    LHW_INFO("device_name = " << device_name);
    return stringTojstring(env, device_name.c_str());
}
  • Java uses
public class JniDemo {
    
    
    /**
     * 获取IOS设备的名称
     * @param udid 设备UDID
     * @return 设备名称
     */
    public native String getDeviceNameByUDID(String udid);

    public static void main(String[] args) {
    
    
        System.loadLibrary("jniDemo");
        JniDemo obj = new JniDemo();
        String result = obj.getDeviceNameByUDID("00008110-001518392EE3801E");
        System.out.println("Result is " + result);
        // Result is iphone 13 pro
    }
}

2.5.2 JNA introduction and use

JNA is a programming framework implemented on the basis of JNI, which implements automatic conversion from Java types to C types. Java developers only need to describe the functions and structures of the target native library in a Java interface, and no longer need to write any Native/JNI code, which greatly reduces the difficulty of developing Java dynamic libraries.

  • Write C/C++ code and declare header files (requires the extern "C" keyword to be called by JNA).
#pragma once
#include "pch.h"

#ifndef JNADemoAPI
#define JNADemoAPI __declspec(dllexport)
#endif // !_Included_JnaDemo

#ifdef __cplusplus
extern "C" {
    
    
#endif // __cplusplus

    JNADemoAPI const char* getDeviceNameByUDID(const char *udid);


#ifdef __cplusplus
}
#endif // __cplusplus

  • Implement the header file and compile it into a dynamic library.
#include "pch.h"
#include "JnaDemo.h"
#include "IOSDevice/ios_device_pimpl.h"

string IOS_Device_Interface::getDeviceNameByUDID(string udid) {
    
    
    return ios_device->get_deviceName_by_udid(udid);
}
  • Used in Java.

First introduce the JNA library into the project:

<dependency>
  <groupId>com.sun.jna</groupId>
  <artifactId>jna</artifactId>
  <version>5.12.1</version>
</dependency>

Declare the Java interface class corresponding to the dynamic library:

/**
 *  定义动态库接口
 */
public interface JnaDemo extends Library {
    
    
    /**
     * 与 C/C++ 中的函数名对应
     * @param 设备UDID
     * @return 设备名称
     */
    String getDeviceNameByUDID(String udid);
}

Load the dynamic library and call the method:


/**
 * 通过 JNA 调用 C/C++ 函数
 *
 */
public class JnaDemoTest {
    
    

    public static void main(String[] args) {
    
    
        // 加载名为 jnaDemo 动态库
        JnaDemo jnaDemo = Native.load("JnaDemo", JnaDemo.class);
        // 调用方法并获取结果
        String result = jnaDemo.getDeviceNameByUDID("00008110-001518392EE3801E");
        System.out.println("Result is " + result);
        // Result is iphone 13 pro
    }
}

2.5.3 Selection and considerations

Through the above sample code, we compared the advantages and disadvantages of the two solutions and conducted performance tests.

JNI JNA
advantage After compilation, the native method can be implemented in C or C++. Calling local methods is more efficient than JNA. It encapsulates the dynamic libraries commonly used in the system and can be used directly. The development efficiency is relatively high compared to JNI, and there is no need to write native methods in Java.
shortcoming The development efficiency is relatively low, requiring Java to write native methods and compile and generate C/C++ header files. C/C++ needs to be coded and implemented according to the generated header files. Dynamic libraries generated by C++ compilation are not supported and need to be encapsulated in C language on top of the C++ interface.

From a developer's perspective: JNA is more friendly to Java developers, while JNI is more friendly to C/C++ developers.

At the same time, we used JNI and JNA to conduct performance tests of reading IOS device names from 100 to 500 times respectively, and obtained time-consuming comparisons. Running on an 8-core 16G machine yields the following results:

Calculate quantity (hundred times) JNI JNA
1 1197ms 26957ms
2 2196ms 52800ms
3 2759ms 79260ms
4 4573ms 106377ms
5 6299ms 132482ms

Through the above comparison and performance testing, we have formulated the following selection criteria:

  • Self-developed SDK: Gaoyou uses JNI as the underlying communication method. The advantages are: JNI has better performance, and the underlying data interaction interface is defined by Java. C/C++ developers can choose C or C++ for implementation, giving them more selectivity and flexibility.
  • SDK provided by external manufacturers: Priority is given to calling the SDK provided by the manufacturer. The advantage is: there is no need to encapsulate a layer of dynamic libraries in C/C++ again, reducing the investment in development resources.

3 Implementation of EJC architecture

The EJC architecture has been successfully implemented in multiple applications in Zhuanzhuan quality inspection. The following mainly introduces the implementation of EJC in Windows notebook quality inspection tools.

3.1 Project background

With the development of quality inspection business, the quality inspection volume of notebooks has reached a new high. The early laptop inspection tools developed by C/C++ and built using Qt can no longer meet the needs of the business, mainly reflected in the following points:

  • High maintenance costs: The complexity of the code is high, and maintenance requires developers to invest more time and energy.
  • Low coverage: The functions are not complete enough, the ease of use is poor, and the usage coverage is low.
  • Poor portability: Cannot be ported to the Mac platform.

Based on the above project background, we used the EJC architecture to reconstruct the notebook inspection tool.

3.2 Architecture implementation

3.2.1 Glossary of terms

  • WMI: Windows Management Instrumentation; is a standard information service for Windows systems.
  • WinAPI: The low-level interface provided by Windows system.
  • DLL©: The C in EJC, the underlying SDK developed by our C/C++ classmates.

3.2.2 Process description

  • Enter the data acquisition process: After Electron is started -> Start the Java server asynchronously in the background -> Enable asynchronous global scanning of notebook basic data item annotations -> Obtain the computer attributes that need to be read -> Scheduler classification execution attribute acquisition command - > Execute acquisition command execution chain (horizontally scalable acquisition method) -> Data processing -> Data error correction -> Push page rendering through SSE channel.
  • Quality inspection process auxiliary process: Enter the quality inspection process -> Request quality inspection item assistance (a certain function, such as whether the fingerprint is normal) -> Java calls the bottom layer (Dll, Wmi and other methods) -> Return the auxiliary quality inspection results -> The page returns the rendering quality inspection item support results.

3.2.3 Process explanation

  • Execution chain: Considering that a certain attribute of the computer needs to be obtained in multiple ways and corrected by each other, its unique execution chain can be configured in a targeted manner to achieve better reading accuracy and more convenient expansion.
  • Data error correction: Some attributes such as battery health value are read by WMI by default; however, some manufacturers do not write values ​​according to WMI standards, resulting in empty results; therefore, other acquisition methods of DLL© need to be called as a supplement.

3.3 Project presentation

3.3.1 Input module

Read the key information of the notebook through Java and C/C++ to obtain the basic situation of the notebook. Through the input function, front-line personnel are assisted in selecting system standard items, and at the same time, they are associated with the quality inspection code and stored in the warehouse. On this basis, a mapping relationship between the original information and the standard product ID is generated, which reduces one operation step for the same model next time and facilitates the portability of front-line operators in quality inspection of the same model.

Notebook entry module

3.3.2 Quality inspection module

Obtain the quality inspection template corresponding to the system through the brand model, provide automatic & auxiliary quality inspection capabilities, and assist front-line quality inspection personnel to more quickly and accurately inspect notebooks.
Laptop quality inspection module

4 Summary

This article shares some information about the EJC architecture of transfer quality inspection and gives some practical experience. I hope it can provide some help for everyone to solve similar problems. At present, the EJC architecture system has launched multiple desktop applications in the quality inspection business and is running stably. In the future, it will cover more application scenarios and help the business develop substantially.

5 Reference links

  • https://www.electronjs.org
  • http://java-native-access.github.io/jna/5.13.0/javadoc/overview-summary.html#overview_description
  • https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html#wp914
  • https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events

About the author

Main writer: Wen Yunting, RD, Zhuanzhuan Performance Technology Department.

The participants in this article are also other partners of the EJC team, a passionate and innovative small team.

Zhuanzhuan is a technical learning and exchange platform for R&D centers and industry partners, regularly sharing frontline practical experience and cutting-edge technical topics in the industry.
Follow the public accounts "Zhuanzhuan Technology" (comprehensive), "Zhuanzhuan FE" (focused on FE), "Zhuanzhuan QA" (focused on QA), and more useful practices, Welcome to communicate and share~

Guess you like

Origin blog.csdn.net/zhuanzhuantech/article/details/129622733