Error Code Design in Java System

1. What is a good error message (Error Message)?

A good Error Message mainly consists of three parts:

Context: What caused the error? What is the code trying to do when an error occurs?
The error itself: What exactly caused the failure? What are the specific reasons and the data at that time?
Mitigation: What is the solution to overcome this error, can also be understood as Solutions
It still sounds a bit abstract, can you give some code? There just happened to be a jdoctor project, the author is from Labs[1] The sample code is as follows:

The Problem here is understood as no problem with Error, and the core mainly includes the following fields:

context: such as app name, component, status code, use a string to describe the current context, such as application name + component name + specific error status code, etc. This is up to you to decide, of course JSON strings are also available, such as { "app": "uic", "component": "login", "code": "111"}

description: Long(Short) to describe error Error description, both Long and Short
because/reason: explain the reason with data Explain the reason of the error in detail, of course the corresponding data must be included

documentedAt: error link The HTTP connection corresponding to the error, which describes the error in more detail
solutions: possible solutions possible solutions, such as prompting the visitor to check whether the spelling of the email is correct, whether the Pass Code of the SMS is entered correctly, etc.

With these specific fields, it will be much easier for us to understand.

2 Design of Error Code

It is recommended to use error codes for various error handling. Error codes have many advantages: uniqueness, more convenient search/statistics, etc., so we still need to discuss the design of error codes. There are also many design specifications for error codes on the Internet. Of course, this article is also indispensable for reinventing the wheel. This design is provided for your reference. You can judge by yourself. Of course, comments are welcome.

An error code usually consists of three parts:

System/App short name: The name of the system or application, such as RST, OSS, etc. If you are familiar with Jira, it is basically this specification. Java programmers should know what HHH and SPR stand for, right?

Component short name or code: The name or code of the component inside the system, such as LOGIN, AUDIT, 001, etc., which is convenient and faster to locate errors.

Status code: Wrong status code, this is a three-digit status code, such as 200, 404, 500, which is mainly borrowed from HTTP Status Code. After all, most developers understand HTTP status codes, and we don’t need to repeat them. design.

With the above specifications in place, let's see what a typical error code looks like:

OSS-001-404: You should know that a certain component of OSS reported that the resource was not found.
RST-002-500: This is an internal error of a component
UIC-LOGIN-404: This should be that the specified account cannot be found when the member logs in
We use the abbreviation of the application name, the component name or code, and the state value, and then connect them with a dash. The underscore is easier to read, and the underscore is sometimes interpreted as a space when displayed. At the same time, with the standard HTTP Status Code support, you can guess a good one without referring to the document. The design of the error code should not be too complicated. Try to add all the information. Of course, the information is very comprehensive, but it also increases the cost of understanding and use by developers. This may be a trade-off. Of course, I am not saying that the current one The structure of the three-link button (reward, like and forward) is the most reasonable, and you can also adjust it yourself. Are there any students who have done psychological research to tell me, is this three-part method most in line with people's cognitive habits? If there are more than three parts, such as 4 and 5, will the probability that people can remember and use it drop very much?

Remember the context of the error mentioned earlier? The error code here is actually the function of starting the context, such as UIC-LOGIN-404, where did the error occur? The error code will help you locate it. What was the code trying to do at the time? The error code is also explained. Although the error code cannot fully represent the context of the error, the information it carries is enough to help us understand the context at that time, so the error code here plays the role of context. At present, at least the error code is more convincing and standardized than the Hawaiian pizza in ProblemBuilder.newBuilder(TestProblemId.ERROR1, StandardSeverity.ERROR, "Hawaiian pizza") as a context.

Three error message writing format

After the error code is designed, we can't use the error code + short message to output the error, otherwise there will be a situation like ORA-00942: table or view does not exist, and you will definitely complain: "Why don't you tell which table or view?". Therefore, we also need to design a message format that can include all wrong context, description, reason, document link, and solutions, so that it will be more friendly to developers. Here I have drawn up a Message specification. Of course, everyone can express their own opinions, as follows:

long description(short desc): because/reason --- document link -- solutions
explain:

The wrong long description is written directly, and the short description is enclosed in brackets. This way of writing is very common in contracts, such as Alibaba Cloud Computing Co., Ltd. (Alibaba Cloud), when you sign a labor contract, the company's title is basically the full name (proxy name) in this way. Many students will write login failure in the error log, but there are multiple login methods in the login system, so it is far less than Failed to log in with email and password(Login Failed), Failed to log in with phone and passcode(Login Failed), Failed to log in with oauth2(Login Failed) is clearer.

The specific reason for the error: followed by a colon, and then write a detailed reason, such as email user@example.com not found, gender field is not allowed in package.json must contain specific data information, including input, or labor contract Similarly, after the title is your specific position and salary, although the contract is formatted, the specific position and salary of each person is different, and these parameters are obtained from the outside. Some security students here ask, how to desensitize data? This is another question. Most developers should know how to mask, so we will skip it here. When the error of labor dispute occurs, the data in the specific reason, such as position and salary, etc., so that the Labor Arbitration Bureau can quickly locate and solve the "error".

document link: Next, we use three dashes --- to separate and enter the corresponding error link. The three-dash line is used as a separator in many scenarios, such as mdx, yaml, etc. You are not too unfamiliar. If there is no link, just ignore it.

solutions: Natural text expressions are enough, and it is enough to explain clearly, and it is also placed after the three underlines.
Look at a specific message format example:

The description corresponding to the above APP-100-400 error code basically covers the information needed in jdoctor. It can be said that the description of an error should be very complete, and it has a certain format, which is also convenient for subsequent log analysis.

Four assembly and save error code + Message

With the specification of error code and message, how should we save this information next? If it is Java, is it necessary to create a corresponding ErrorEnum, and then some POJO? Here I personally recommend using the properties file to save the error code and message information. The file name can be directly ErrorMessages.properties, of course under a certain package, the file example is as follows:

Why choose the properties file to save the error code and message information, mainly for the following reasons:

Internationalization support: Java students know that if you want to adjust the error message to Chinese, just create an ErrorMessages-zh_CN.properties. The suggestion in the original text is Don’t localize error messages, but considering that most programmers in China may not be able to express clearly in English, Chinese is also possible. Digression: If Chinese programmers can clearly read articles and express their thoughts and opinions in English, our level of computer skills may be raised to a higher level.

Various languages support the parsing of properties files, not only Java, but also other languages, and the properties file itself is not complicated, so the properties file can be used by Node.js, Rust and other languages, if it is Java enum and POJO Basically impossible.

The properties file format is rich: support comments, line breaks, multi-line escapes, etc. are also no problem.

Finally, the most important thing is that the IDE support is very friendly. For IntelliJ IDEA used by Java developers, the support for Properties files can be said to be extreme, as follows:

Automatic prompt for Error code

Quick view: You can move the mouse up, press CMD to move the mouse up, Alt+Space can also be used, of course, click to locate directly.

Refactoring and search support: Although the Error Code is a string, it is also the key of properties, so if you rename the error code, all references will be renamed. It also supports find usage, where the error code is quoted, which is very convenient. Of course, if the Error Code is not used in the system, it will also be grayed out.

Folding automatic display function: When your code is in the folded state, IDEA directly takes the message and displays it, which is much more convenient for you when you are reviewing the code, and it is also easier for you to understand the code.

Modify the value of message directly

In short, IntellIJ IDEA supports the properties file to the extreme, and we have no reason not to consider the problem of developer experience, jumping around to find error codes, this kind of thing that hurts the programmer's development experience cannot be done. Of course, other IDEs of JetBrains, WebStorm, etc. have support for editing properties files.

Five code implementation

It seems that the function is quite cool, is it necessary to intervene in a development kit for error management in this way? No, you only need 10 lines of code to get it done, as follows:

In this way, if you want to print an error message anywhere, log.info(AppErrorMessages.message("APP-100-400","xxx")); will do. If you still have an idea to wrap the log with the log, such as log.info("APP-100-400","xxx"); , there is no problem. The sample code is as follows:

Then you can directly integrate the error code in the log, which is very convenient. I have written the above code, you can refer to the project address at the end of the article.

The final log output is as follows:


Reminder: Here we use slf4j's MessageFormatter, mainly to facilitate the subsequent integration of Slf4j, and slf4j's MessageFormatter is better than Java's MessageFormat in terms of fault tolerance and performance.

Six FAQs

1 Why choose the 3-digit HTTP Status Code as the Error Status Code?
Most developers are familiar with HTTP Status Code, so they can roughly understand what it means when they see these codes. Of course, there are strict requirements for application developers. You must not interpret 404 as an internal error, such as database connection failure. , Don't do things that go against normal thinking. HTTP status codes are classified as follows, of course you can also refer to HTTP Status Codes Cheat Sheet[2].

But Error Status Code is not limited to HTTP Status Code, you can also refer to SMTP, POP3 and other Status Codes, and you can also choose codes such as 007, 777, as long as you can explain it reasonably.

In daily life, we use some numbers with special meaning or homonyms with numbers. Here are some friendly reminders:

UIC-LOGIN-666: Very smooth, perfect login. But if there are European and American foreigners in your team, he may understand it as a malicious login, and the login fails

APP-LOGIN-062: Do not use the number 62 if your team has Hangzhou natives
APP-001-013: If the error code is to be transparently transmitted to the end user, please do not use the number 13, which will cause discomfort

This kind of number with special meaning or digital homophony, such as 520, 886, 999, 95, etc., is very convenient to understand or more friendly if used properly, such as transparently transmitted to the user UIC-REG-200 (registration is successful), if adjusted It may be more warm for UIC-REG-520. Generally speaking, you should pay attention to the scenario when using these numbers. Of course, it is safer to refer to the status code designed by HTTP, SMTP, etc.

2 properties files store error code and message, is it really better than enum and POJO?
As far as the support of Java and IntelliJ IDEA is concerned, the current cooperation is relatively good, such as i18n, maintenance costs, etc., and these ErrorMessages.properties can also be submitted to the central warehouse for centralized management of Error Code. If it is Java Enum+POJO for i18n Both centralized management and centralized management are more troublesome, and the amount of code is relatively large, as you can see from the above-mentioned problem builder of jdoctor. Of course, it may not be absolute in different languages. For example, in Rust, due to the rich features of enum,

3 Why not provide error level in Error Code
Many error code designs will add error levels, such as RS-001-404-9, the last bit indicates the severity level of the error. There is no problem in doing so, but realistic factors must also be considered, as follows:

The level of error will be adjusted dynamically: as time and space change, the level of error that was very serious before is not so serious now. If the resource cannot be found, it may have been very serious before, but now that a backup solution has been added, it can be searched again from the backup server, so this error may not be so serious now if it occurs on the main service.

Different teams have different perceptions of error levels: For example, OSS-404 cannot be found on the data server of the OSS team, and the meta-information is available. As a result, no corresponding data can be found on the data server. This is a very serious error. . Lei Juan is in the business team, such as in charge of Serverless Jamstack, and one of the missing files, such as html, css, image, may not be a big problem. Wait a while and try again, if it fails, upload it again. What I want to express is that the same mistakes have different importance in different teams.
If the error is basically solidified into the error code, you will not be able to adjust it later. If you adjust the error level, it may be another error code, which will cause problems for statistics and understanding. Personally, I suggest that the error code should not include the severity level information, but explain it through peripheral documents and descriptions. Of course, you can also determine the error level through such as log.info and log.error.

4 Can shared libraries be provided?

Since IntelliJ IDEA does not support dynamic properties file names, if you use dynamic properties file names, you cannot perform code prompts, search and other functions cannot be used, so it must be this @PropertyKey(resourceBundle = BUNDLE_FQN) static properties file name method. Just a Java class, you have to copy this Java class, after all, it is a one-time job, of course, if you want to personalize and adjust the code, it is more convenient, such as integrating with Log4j 2.x or a custom logging framework is also easier. Logging is the most basic requirement of a project, so when you create a project, add the code corresponding to the Error Code to the project template, so that the functions of logging and error code will be automatically included after the project is created.

5 Other considerations

The original text and related discussions on Reddit have also been sorted out and explained:

There is a difference between inside and outside: For example, the error of the internal developer may include the specific information of the server. Of course, for the final consumer, such as the FaaS developer of the platform, such information may not be output, and there is a certain security risk.

Be careful of exposing sensitive data in errors: the data output to the error log must be masked, and of course it should not affect your location of errors. This depends on the specific scenario.

Do not use error messages as an API contract: In the API scenario, there are two ways to respond to errors: respond according to the error code, such as REST API; the other is to respond according to the message, such as GraphQL, so this is your choice.

Consistency of Error Code: Error messages will be output to different consumers, such as REST API, interface, etc. The error message may be different, such as internationalization, desensitization, etc., but it is best to have the same error code, That is, front end + backend share the same error code, which is convenient for locating errors and statistics.

seven summary

Using error code + storing error message based on properties file, this design is actually a comprehensive choice. If IDEA cannot support properties files well, and you see an Error Code, you cannot directly locate the error message, but instead need to jump to find the corresponding message, then Enum + POJO may be a good choice. In addition, the design of the error code is also very biased towards the http status code scheme. This is mainly based on the fact that everyone is very familiar with HTTP and can basically guess the general meaning. On the contrary, random coded numbers do not have the advantage of this method, so you need to use the error code If the center goes to look it up again, it will waste the developer's time virtually.

Related Articles

Explore More Special Offers

  1. Short Message Service(SMS) & Mail Service

    50,000 email package starts as low as USD 1.99, 120 short messages start at only USD 1.00

phone Contact Us