{"id":18559046,"url":"https://github.com/linux-china/java-error-messages-wizard","last_synced_at":"2025-04-10T02:30:37.630Z","repository":{"id":136595528,"uuid":"448161831","full_name":"linux-china/java-error-messages-wizard","owner":"linux-china","description":"Java Error Message Wizard","archived":false,"fork":false,"pushed_at":"2024-11-23T07:45:14.000Z","size":19,"stargazers_count":16,"open_issues_count":0,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-02T02:51:10.508Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/linux-china.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-15T02:27:41.000Z","updated_at":"2025-03-29T21:52:17.000Z","dependencies_parsed_at":"2023-12-25T11:43:16.901Z","dependency_job_id":null,"html_url":"https://github.com/linux-china/java-error-messages-wizard","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linux-china%2Fjava-error-messages-wizard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linux-china%2Fjava-error-messages-wizard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linux-china%2Fjava-error-messages-wizard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/linux-china%2Fjava-error-messages-wizard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/linux-china","download_url":"https://codeload.github.com/linux-china/java-error-messages-wizard/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248144155,"owners_count":21054876,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T21:41:55.389Z","updated_at":"2025-04-10T02:30:37.277Z","avatar_url":"https://github.com/linux-china.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"Java Error Messages Wizard - Write Good Error Message\n======================================================\n\n# Features\n\n* Error Code Design\n* Standard Error Message Format\n* Resource Bundle: properties file and i18n\n* slf4j friendly\n* IntelliJ IDEA friendly\n\n# Error Code Design\n\nError code a unique string value for a kind of error, and includes 3 parts:\n\n* System/App short name: such as RST, APP1. Yes, Jira alike\n* Component short name or code: such as LOGIN, 001\n* Status code: a 3 digital number to describe error's status, such as 404, 500. Reference from HTTP Status Code.\n\nError Code examples:\n\n* OSS-001-404\n* RST-002-500\n* UIC-LOGIN-500\n\n# Error Message\n\nA good error message with following parts:\n\n* Context: What led to the error? What was the code trying to do when it failed? where?\n* The error itself: What exactly failed? description and reason\n* Mitigation: What needs to be done in order to overcome the error? Solutions\n\nFields for an error:\n\n* context: such as app name, component, status code\n* description: Long(Short) to describe error\n* because/reason:  explain the reason with data\n* documentedAt: error link\n* solutions: possible solutions\n\nMessage format for an error: `long description(short desc): because/reason --- document link -- solutions`\n\n# Use properties file to save error code and message\n\nExample as following:\n\n```properties   \nERROR-CODE:long description(short desc): because/reason --- document link -- solutions\nRST-100400=Failed to log in system with email and password(Email login failed): can not find account with email {0} --- please refer https://example.com/login/byemail  --- Solutions: 1. check your email  2. check your password\nRST-100401=Failed to log in system with phone and pass(Phone login failed): can not find account with phone {0} --- please refer https://example.com/login/byphone  --- Solutions: 1. check your phone  2. check your pass code in SMS\n```\n\n# Java Error Code with Spring 6 ProblemDetail\n\nPlease refer https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-rest-exceptions\n\n```java\nimport org.jetbrains.annotations.Nullable;\nimport org.jetbrains.annotations.PropertyKey;\nimport org.mvnsearch.model.ProblemDetailException;\nimport org.slf4j.helpers.FormattingTuple;\nimport org.slf4j.helpers.MessageFormatter;\nimport org.springframework.http.ProblemDetail;\nimport org.springframework.web.reactive.result.method.annotation.ResponseEntityExceptionHandler;\n\nimport java.net.URI;\nimport java.util.Locale;\nimport java.util.ResourceBundle;\n\npublic class ProblemDetailExceptionHandler extends ResponseEntityExceptionHandler {\n    private static final String BUNDLE_FQN = \"app.ErrorMessages\";\n    //please use your own error message properties file\n    private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_FQN, new Locale(\"en\", \"US\"));\n    private static final String[] URL_PREFIXES = new String[]{\"https://\", \"http://\"};\n\n    public static ProblemDetail fromProblemDetailException(ProblemDetailException e, Object... params) {\n        return fromErrorCode(e, e.getHttpStatusCode(), e.getErrorCode(), params);\n    }\n\n    public static ProblemDetail fromErrorCode(Exception e, int httpStatusCode,\n                                              @PropertyKey(resourceBundle = BUNDLE_FQN) String errorCode, Object... params) {\n        String message = errorMessage(errorCode, params);\n        ProblemDetail problemDetail = ProblemDetail.forStatus(httpStatusCode);\n        problemDetail.setTitle(e.getClass().getCanonicalName());\n        problemDetail.setDetail(message);\n        final URI type = extractUri(message);\n        if (type != null) {\n            problemDetail.setType(type);\n        }\n        problemDetail.setProperty(\"errorCode\", errorCode);\n        if (params != null \u0026\u0026 params.length \u003e 0) {\n            problemDetail.setProperty(\"params\", params);\n        }\n        return problemDetail;\n    }\n\n    @Nullable\n    private static URI extractUri(String message) {\n        for (String urlPrefix : URL_PREFIXES) {\n            if (message.contains(urlPrefix)) {\n                int offset = message.indexOf(urlPrefix);\n                int endOffset = message.indexOf(\" \", offset);\n                if (endOffset == -1) {\n                    endOffset = message.length();\n                }\n                return URI.create(message.substring(offset, endOffset));\n            }\n        }\n        return null;\n    }\n\n    public static String errorMessage(@PropertyKey(resourceBundle = BUNDLE_FQN) String key, Object... params) {\n        if (RESOURCE_BUNDLE.containsKey(key)) {\n            String value = RESOURCE_BUNDLE.getString(key);\n            final FormattingTuple tuple = MessageFormatter.arrayFormat(value, params);\n            return key + \" - \" + tuple.getMessage();\n        } else {\n            return MessageFormatter.arrayFormat(key, params).getMessage();\n        }\n    }\n}\n```\n\n# FAQ\n\n### Why Choose HTTP Status Code as Error status code?\n\nMost developers know HTTP status code: 200, 404, 500\n\n* Informational responses (100–199)\n* Successful responses (200–299)\n* Redirection messages (300–399)\n* Client error responses (400–499)\n* Server error responses (500–599)\n\n### Why Choose properties file to store error messages?\n\nProperties file is friendly for i18n and IDE friendly now\n\n* Code completion support for error code\n* Error Code rename support\n* Quick view support\n* MessageFormat support\n* Resource Bundle for i18n support\n\nYes, you can choose Enum and POJO class, but some complication.\n\nIf you use Rust, and Enum is good choice, for example `thiserror` + `error-stack` :\n\n```rust\nuse thiserror::Error as ThisError;\n\n/// errors for config component: app-100\n#[derive(ThisError, Debug)]\npub enum ConfigError {\n    #[error(\"APP-100404: config file not found: {0}\")]\n    NotFound(String),\n    #[error(\"APP-100422: invalid JSON Format: {0}\")]\n    Invalid(String),\n}\n\nfn parse_config() -\u003e Result\u003cConfigMap, ConfigError\u003e {\n    let json_file = \"config.json\";\n    let config = std::fs::read_to_string(json_file)\n        .report()\n        .change_context(ConfigError::NotFound(json_file.to_string()))?;\n    let map: ConfigMap = serde_json::from_str(\u0026config)\n        .report()\n        .change_context(ConfigError::Invalid(json_file.to_string()))?;\n    Ok(map)\n}\n```\n\nFor more error code design with Rust, please visit https://github.com/linux-china/rust-error-messages-wizard\n\n# References\n\n* What's in a Good Error Message?  https://www.morling.dev/blog/whats-in-a-good-error-message/\n* jdoctor:  https://github.com/melix/jdoctor\n* HTTP response status codes: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status\n* HTTP Status cheatsheet: https://devhints.io/http-status\n* @PropertyKey support for slf4j message format - https://youtrack.jetbrains.com/issue/IDEA-286726\n* @PrintFormat: annotation to printf-like methods - https://youtrack.jetbrains.com/issue/IDEA-283556\n* Spring Boot 3 : Error Responses using Problem Details for HTTP APIs - https://www.sivalabs.in/spring-boot-3-error-reporting-using-problem-details/\n* Parameterized Logging With SLF4J: https://www.baeldung.com/slf4j-parameterized-logging\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinux-china%2Fjava-error-messages-wizard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flinux-china%2Fjava-error-messages-wizard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flinux-china%2Fjava-error-messages-wizard/lists"}