{"id":21031298,"url":"https://github.com/workable/java-error-handler","last_synced_at":"2025-06-24T06:32:52.425Z","repository":{"id":72865952,"uuid":"63353944","full_name":"Workable/java-error-handler","owner":"Workable","description":"Error handling library for Android and Java","archived":false,"fork":false,"pushed_at":"2024-04-15T14:53:43.000Z","size":242,"stargazers_count":241,"open_issues_count":1,"forks_count":16,"subscribers_count":18,"default_branch":"master","last_synced_at":"2025-06-10T11:12:16.689Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","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/Workable.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog.md","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":"2016-07-14T16:54:02.000Z","updated_at":"2024-09-29T14:16:42.000Z","dependencies_parsed_at":"2024-12-25T06:10:55.709Z","dependency_job_id":"c3bede96-205d-47bd-9856-50ce7f4090f2","html_url":"https://github.com/Workable/java-error-handler","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/Workable/java-error-handler","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Workable%2Fjava-error-handler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Workable%2Fjava-error-handler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Workable%2Fjava-error-handler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Workable%2Fjava-error-handler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Workable","download_url":"https://codeload.github.com/Workable/java-error-handler/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Workable%2Fjava-error-handler/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261620334,"owners_count":23185490,"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-19T12:27:09.549Z","updated_at":"2025-06-24T06:32:52.398Z","avatar_url":"https://github.com/Workable.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ErrorHandler\n[![Download](https://api.bintray.com/packages/workable/maven/ErrorHandler/images/download.svg) ](https://bintray.com/workable/maven/ErrorHandler/_latestVersion)\n[![Travis](https://travis-ci.org/Workable/java-error-handler.svg?branch=master)](https://travis-ci.org/Workable/java-error-handler)\n\n\u003e Error handling library for Android and Java\n\nEncapsulate error handling logic into objects that adhere to configurable defaults. Then pass them around as parameters or inject them via DI. \n\n## Download\nDownload the [latest JAR](https://bintray.com/workable/maven/ErrorHandler/_latestVersion) or grab via Maven:\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.workable\u003c/groupId\u003e\n  \u003cartifactId\u003eerror-handler\u003c/artifactId\u003e\n  \u003cversion\u003e1.1.0\u003c/version\u003e\n  \u003ctype\u003epom\u003c/type\u003e\n\u003c/dependency\u003e\n```\n\nor Gradle:\n\n```groovy\ncompile 'com.workable:error-handler:1.1.0'\n```\n\n\n## Usage\n\nLet's say we're building a messaging Android app that uses both the network and a local database.\n\nWe need to:\n\n### Setup a default ErrorHandler once\n\n - Configure the default ErrorHandler\n - Alias errors to codes that are easier to use like Integer, String and Enum values\n - Map errors to actions to take when those errors occur (exceptions thrown)\n\n```java\n// somewhere inside MessagingApp.java\n\nErrorHandler\n  .defaultErrorHandler()\n\n  // Bind certain exceptions to \"offline\"\n  .bind(\"offline\", errorCode -\u003e throwable -\u003e {\n      return throwable instanceof UnknownHostException || throwable instanceof ConnectException;\n  })\n\n  // Bind HTTP 404 status to 404\n  .bind(404, errorCode -\u003e throwable -\u003e {\n      return throwable instanceof HttpException \u0026\u0026 ((HttpException) throwable).code() == 404;\n  })\n\n  // Bind HTTP 500 status to 500\n  .bind(500, errorCode -\u003e throwable -\u003e {\n      return throwable instanceof HttpException \u0026\u0026 ((HttpException) throwable).code() == 500;\n  })\n\n  // Bind all DB errors to a custom enumeration\n  .bindClass(DBError.class, errorCode -\u003e throwable -\u003e {\n      return DBError.from(throwable) == errorCode;\n  })\n\n  // Handle HTTP 500 errors\n  .on(500, (throwable, errorHandler) -\u003e {\n    displayAlert(\"Kaboom!\");\n  })\n\n  // Handle HTTP 404 errors\n  .on(404, (throwable, errorHandler) -\u003e {\n    displayAlert(\"Not found!\");\n  })\n\n  // Handle \"offline\" errors\n  .on(\"offline\", (throwable, errorHandler) -\u003e {\n    displayAlert(\"Network dead!\");\n  })\n\n  // Handle unknown errors\n  .otherwise((throwable, errorHandler) -\u003e {\n    displayAlert(\"Oooops?!\");\n  })\n\n  // Always log to a crash/error reporting service\n  .always((throwable, errorHandler) -\u003e {\n    Logger.log(throwable);\n  });\n```\n\n### Use ErrorHandler inside catch blocks\n\n```java\n// ErrorHandler instances created using ErrorHandler#create(), delegate to the default ErrorHandler\n// So it's actually a \"handle the error using only defaults\"\n// i.e. somewhere inside MessageListActivity.java\ntry {\n  fetchNewMessages();\n} catch (Exception ex) {\n  ErrorHandler.create().handle(ex);\n}\n```\n\n### Run blocks of code using ErrorHandler.run\n\n```java\nErrorHandler.run(() -\u003e fetchNewMessages());\n```\n\n### Override defaults when needed\n\n```java\n// Configure a new ErrorHandler instance that delegates to the default one, for a specific method call\n// i.e. somewhere inside MessageListActivity.java\ntry {\n  fetchNewMessages();\n} catch (Exception ex) {\n  ErrorHandler\n    .create()\n    .on(StaleDataException.class, (throwable, errorHandler) -\u003e {\n        reloadList();\n        errorHandler.skipDefaults();\n    })\n    .on(404, (throwable, errorHandler) -\u003e {\n        // We handle 404 specifically on this screen by overriding the default action\n        displayAlert(\"Could not load new messages\");\n        errorHandler.skipDefaults();\n    })\n    .on(DBError.READ_ONLY, (throwable, errorHandler) -\u003e {\n        // We could not open our database to write the new messages\n        ScheduledJob.saveMessages(someMessages).execute();\n        // We also don't want to log this error because ...\n        errorHandler.skipAlways();\n    })\n    .handle(ex);\n}\n```\n\n### Things to know\n\nErrorHandler is __thread-safe__.\n\n\n## API\n\n### Initialize\n\n* `defaultErrorHandler()` Get the default ErrorHandler.\n\n* `create()` Create a new ErrorHandler that is linked to the default one.\n\n* `createIsolated()` Create a new empty ErrorHandler that is not linked to the default one.\n\n### Configure\n\n* `on(Matcher, Action)` Register an _Action_ to be executed if _Matcher_ matches the error.\n\n* `on(Class\u003c? extends Exception\u003e, Action)` Register an _Action_ to be executed if error is an instance of `Exception`.\n\n* `on(T, Action)` Register an _Action_ to be executed if error is bound to T, through `bind()` or `bindClass()`.\n\n* `otherwise(Action)` Register an _Action_ to be executed only if no other _Action_ gets executed.\n\n* `always(Action)` Register an _Action_ to be executed always and after all other actions. Works like a `finally` clause.\n\n* `skipFollowing()`  Skip the execution of any subsequent _Actions_ except those registered via `always()`.\n\n* `skipAlways()` Skip all _Actions_ registered via `always()`.\n\n* `skipDefaults()` Skip any default actions. Meaning any actions registered on the `defaultErrorHandler` instance.\n\n* `bind(T, MatcherFactory\u003cT\u003e)` Bind instances of _T_ to match errors through a matcher provided by _MatcherFactory_.\n\n* `bindClass(Class\u003cT\u003e, MatcherFactory\u003cT\u003e)` Bind class _T_ to match errors through a matcher provided by _MatcherFactory_.\n\n* `clear()` Clear all registered _Actions_.\n\n### Execute\n\n* `handle(Throwable)` Handle the given error.\n\n\n## About\n\nWhen designing for errors, we usually need to:\n\n1. have a **default** handler for every **expected** error \n   // i.e. network, subscription errors\n2. handle **specific** errors **as appropriate** based on where and when they occur \n   // i.e. network error while uploading a file, invalid login\n3. have a **catch-all** handler for **unknown** errors \n   // i.e. system libraries runtime errors we don't anticipate\n4. keep our code **DRY**\n\nJava, as a language, provides you with a way to do the above. By mapping cross-cutting errors to runtime exceptions and catching them lower in the call stack, while having specific expected errors mapped to checked exceptions and handle them near where the error occurred. Still, countless are the projects where this simple strategy has gone astray with lots of errors being either swallowed or left for the catch-all `Thread.UncaughtExceptionHandler`. Moreover, it usually comes with significant boilerplate code. `ErrorHandler` however eases this practice through its fluent API, error aliases and defaults mechanism.\n\nThis library doesn't try to solve Java specific problems, although it does help with the `log and shallow` anti-pattern as it provides an opinionated and straightforward way to act inside every `catch` block.  It was created for the needs of an Android app and proved itself useful very quickly. So it may work for you as well. If you like the concept and you're developing in  _Swift_ or _Javascript_, we're baking 'em and will be available really soon.\n\n## License\n```\nThe MIT License\n\nCopyright (c) 2013-2016 Workable SA\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fworkable%2Fjava-error-handler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fworkable%2Fjava-error-handler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fworkable%2Fjava-error-handler/lists"}