{"id":19711675,"url":"https://github.com/melthaw/spring-web-error","last_synced_at":"2026-05-07T16:17:08.787Z","repository":{"id":87148313,"uuid":"97922878","full_name":"melthaw/spring-web-error","owner":"melthaw","description":"The general web error(we) handler abstraction based on Spring MVC Framework.","archived":false,"fork":false,"pushed_at":"2019-04-28T08:23:30.000Z","size":60,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-11-22T16:03:35.513Z","etag":null,"topics":["error-handling","java","spring"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/melthaw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2017-07-21T08:06:51.000Z","updated_at":"2019-04-28T08:23:32.000Z","dependencies_parsed_at":"2023-03-13T19:46:21.556Z","dependency_job_id":null,"html_url":"https://github.com/melthaw/spring-web-error","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/melthaw/spring-web-error","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melthaw%2Fspring-web-error","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melthaw%2Fspring-web-error/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melthaw%2Fspring-web-error/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melthaw%2Fspring-web-error/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/melthaw","download_url":"https://codeload.github.com/melthaw/spring-web-error/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/melthaw%2Fspring-web-error/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32745430,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-07T02:14:30.463Z","status":"ssl_error","status_checked_at":"2026-05-07T02:14:29.405Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["error-handling","java","spring"],"created_at":"2024-11-11T22:13:16.896Z","updated_at":"2026-05-07T16:17:08.758Z","avatar_url":"https://github.com/melthaw.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Introduction\n\nThe general web error(we) handler abstraction based on Spring MVC Framework. \n\n# Why \u0026 How\n\nAs we know, the Restful API is the  standard for web development, \nSpring MVC which is the powerful framework for REST API development but the default exception handler is not good enough . \nMostly we expect the unified error format in json if any exception thrown by the web application based on Spring MVC framework.\n\nFor example :\n\n```json\n \t{\n        errorCode: \"400\",\n        errorMessage: \"Bad Request\",\n        developerMessage: \"[org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:114), org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77), org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:162), org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:129), org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110), org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:777), org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:706), org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85), org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943), org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877), org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966), org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857), javax.servlet.http.HttpServlet.service(HttpServlet.java:618), org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842), javax.servlet.http.HttpServlet.service(HttpServlet.java:725), org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291), org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206), org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88), org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107), org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239), org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206), org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77), org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107), org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239), org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206), org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219), org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106), org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501), org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142), org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79), org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88), org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:537), org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1085), org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658), org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222), org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1556), org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1513), java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142), java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617), org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61), java.lang.Thread.run(Thread.java:745)]\",\n        moreInfo: \"org.springframework.validation.BeanPropertyBindingResult: 1 errors\n        Field error in object 'foo' on field 'name': rejected value [null]; codes [NotNull.foo.name,NotNull.name,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [foo.name,name]; arguments []; default message [name]]; default message [may not be null]\",\n        formError: [\n            {\n                field: \"name\",\n                message: \"may not be null\"\n            }\n        ]\n    }\n```\n\n   \n\n\nThe `errorCode` indicates that the client can determine which error flow will be triggered based on the returned errorCode.\n\nThe `errorMessage` supplies what message may be prompted to the end user.\n\nAnd the `developerMessage` provides more information to developer which can help to locate what caused the exception, the `moreInfo` shows help message as the supplement for developerMessage.\n\nIf the `@Valid` is enabled in Spring MVC configuration ,the formError can tell the detail of what happened , the client can parse the formError (in json format) to render the html form error.\n\nHere is the reason we override the `org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver` to send unified error response\nif any exception thrown by the `@Controller` from Spring MVC framework.\n\n\n# Dependencies\n\n* Spring Framework Web 4.x\n\n# Usage\n\nSo far `2.1.1` is available \n\n## Maven\n\n```xml\n    \u003cdependency\u003e\n        \u003cgroupId\u003ein.clouthink.daas\u003c/groupId\u003e\n        \u003cartifactId\u003edaas-we\u003c/artifactId\u003e\n        \u003cversion\u003e${daas.we.version}\u003c/version\u003e\n    \u003c/dependency\u003e\n\n```\n\n## Gradle\n\n```groovy\n    compile \"in.clouthink.daas:daas-we:${daas_we_version}\"\n```\n\n## Get Hooking Started\n\nFirst ,we assume you have the base knowledge of Spring Mvc Exception Handler, especially, how the ExceptionHandlerExceptionResolver is working.\nHere is the extension points we supplied in the CustomExceptionHandlerExceptionResolver which is override the default Spring ExceptionHandlerExceptionResolver.\n\n* ErrorContextBuilder\n* ErrorResolver \n* ErrorResponseHandler\n\n### ErrorContextBuilder\n\nErrorContextBuilder will build the ErrorContext instance based on the parameters which can access from the ExceptionHandlerExceptionResolver#doResolveHandlerMethodException.\nThe default implementation is in.clouthink.daas.we.DefaultErrorContextBuilder which build the DefaultErrorContext for output.\n\n```java\n    public interface ErrorContextBuilder {\n        \n        ErrorContext build(HttpServletRequest request,\n                           HttpServletResponse response,\n                           HandlerMethod handlerMethod,\n                           Exception exception);\n                           \n    }\n\n```\n\nHere is the definition of ErrorContext, it's quite simple that returns the Exception thrown by your controller's method and the method is returned wrapped in Spring HandlerMethod.\nAnd the ErrorContext also tells that the ExceptionResolver is under developer mode or not. Obviously, if you are under the developer mode , more detailed message will be output for the developer.\n\n```java\n    public interface ErrorContext {\n        \n        HandlerMethod getHandlerMethod();\n        \n        Exception getException();\n        \n        boolean isDeveloperMode();\n        \n    }\n\n```\n\nIf you have something else you'd like to add to the ErrorContext ,just extend it . But please also remember to supply the corresponding ErrorContextBuilder .\nAnd pop it into the CustomExceptionHandlerExceptionResolver instance .\n\n```java\n     CustomExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver = new CustomExceptionHandlerExceptionResolver(true);\n     exceptionHandlerExceptionResolver.setErrorContextBuilder(theCustomizedErrorContextBuilder);\n\n```\n\n### ErrorResolver\n\nOnce you get the ErrorContext built ,we can move to the next phase , resolve the error from context. \n\n```java\n    public interface ErrorResolver\u003cT\u003e {\n        \n        ResponseEntity\u003cT\u003e resolve(ErrorContext errorContext);\n        \n    }\n\n```\n\nAs the interface defined, the resolve method will return the ResponseEntity type in generic style. \nIn another words, any body of the ResponseEntity is legal .\nOur default implementation is in.clouthink.daas.we.ErrorResponse for your reference.\n\n```java\n    public class ErrorResponse {\n    \n        private String errorCode;\n        \n        private String errorMessage;\n        \n        private String developerMessage;\n        \n        private String moreInfo;\n        \n        //GETTERs \n        //SETTERs\n        \n    }\n\n```\n    \nThree build-in implementations of ErrorResolver is listed as follow:\n\n* ErrorMappingResolver \n\nfor the controller methods annotated with @ErrorMappings\n\n* DefaultErrorResolver \n\nThe general handler for the controller methods which is not annotated with @ErrorMappings\n\n* CompositeErrorResolver \n\nThe CompositeErrorResolver acts as the ErrorResolver registry which the ErrorResolver can be added to it and ordered in list,\nWhen no one in the ErrorResolver registry can resolve the incoming ErrorContext, and default resolver will take over.\n\nHere is the configure sample we recommended.\n\n```java\n    CustomExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver = new CustomExceptionHandlerExceptionResolver(true);\n    exceptionHandlerExceptionResolver.getErrorResolver() // return the composite error resolver by default\n                                     .add(new ErrorMappingResolver())\n                                     .setDefaultErrorResolver(new DefaultErrorResolver());\n\n```\n\nIf you implement the ErrorResolver for customization , here is the way you can make it work for the CustomExceptionHandlerExceptionResolver\n\nWay 1:\n\n```java\n    CustomExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver = new CustomExceptionHandlerExceptionResolver(true);\n    exceptionHandlerExceptionResolver.setErrorResolver(yourErrorResolverImplementation); // replace the default composite error resolver\n\n```\n\nWay 2:\n\n```java\n    CustomExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver = new CustomExceptionHandlerExceptionResolver(true);\n    exceptionHandlerExceptionResolver.getErrorResolver()\n                                     .add(new ErrorMappingResolver())\n                                     .add(yourErrorResolverImplementation) // or add to the registry\n                                     .setDefaultErrorResolver(new DefaultErrorResolver());    \n\n```    \n\n\n### ErrorResponseHandler\n\nFinally , we need to convert the error response to match the http servlet spec.\n\n```java\n    public interface ErrorResponseHandler\u003cT\u003e {\n        \n        void handle(ServletWebRequest webRequest, ResponseEntity\u003cT\u003e responseEntity);\n        \n    }\n\n```\n\nThe default implementation is in.clouthink.daas.we.DefaultErrorResponseHandler which is quite simple to delegate the work to HandlerMethodReturnValueHandler.\n\n\n## Spring Configuration\n\nHow to enable the new Customized Exception Handler Exception Resolver implementation.\n \n```java\n    @Bean\n    public HandlerExceptionResolver customExceptionHandlerExceptionResolver() {\n        CustomExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver = new CustomExceptionHandlerExceptionResolver(true);\n        exceptionHandlerExceptionResolver.getErrorResolver()\n                                         .add(new ErrorMappingResolver())\n                                         .setDefaultErrorResolver(new DefaultErrorResolver());\n        return exceptionHandlerExceptionResolver;\n    }\n    \n    @Override\n    public void configureHandlerExceptionResolvers(List\u003cHandlerExceptionResolver\u003e exceptionResolvers) {\n        exceptionResolvers.add(customExceptionHandlerExceptionResolver());\n    }\n\n```\n    \nHow to run the daas we sample :\n    \n```shell\n    cd module/daas-we-sample\n    mvn clean spring-boot:run\n```    \n    \nFollow the sample `in.clouthink.daas.we.sample.web.SampleRestApi` in module/daas-we-sample.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmelthaw%2Fspring-web-error","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmelthaw%2Fspring-web-error","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmelthaw%2Fspring-web-error/lists"}