{"id":21361983,"url":"https://github.com/kh-bd/result4j","last_synced_at":"2026-02-15T10:31:24.904Z","repository":{"id":215637620,"uuid":"739435894","full_name":"kh-bd/result4j","owner":"kh-bd","description":"Library with simple primitives like `Option` and `Result`.","archived":false,"fork":false,"pushed_at":"2024-06-15T14:17:42.000Z","size":409,"stargazers_count":2,"open_issues_count":9,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-09-15T02:45:17.266Z","etag":null,"topics":["java","library"],"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/kh-bd.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":"2024-01-05T15:03:48.000Z","updated_at":"2024-06-15T14:17:45.000Z","dependencies_parsed_at":"2024-01-25T18:44:02.685Z","dependency_job_id":"c59ce86c-219c-4701-bb7f-7aecda9a50b9","html_url":"https://github.com/kh-bd/result4j","commit_stats":null,"previous_names":["kh-bd/result4j"],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/kh-bd/result4j","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kh-bd%2Fresult4j","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kh-bd%2Fresult4j/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kh-bd%2Fresult4j/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kh-bd%2Fresult4j/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kh-bd","download_url":"https://codeload.github.com/kh-bd/result4j/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kh-bd%2Fresult4j/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29475602,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-15T10:25:47.032Z","status":"ssl_error","status_checked_at":"2026-02-15T10:25:01.815Z","response_time":118,"last_error":"SSL_read: 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":["java","library"],"created_at":"2024-11-22T06:12:58.468Z","updated_at":"2026-02-15T10:31:24.887Z","avatar_url":"https://github.com/kh-bd.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Result4j\n\nResult4j is a library with simple functional primitives like `Option` and `Result` with compiler support for them.\n\n[![CI latest](https://github.com/kh-bd/result4j/actions/workflows/main-tests.yml/badge.svg)](https://github.com/kh-bd/result4j/actions/workflows/main-tests.yml)\n\n## Why do we need it?\n\nAll we love functional primitives like `Option` and `Result`.\nTo use such primitives properly we have to write our code in so-called monad style\nwith higher-order functions like `map` and `flatmap`.\n\nFor example, we have a simplified service to sign a document.\nFirst of all, we need to search a document in a storage.\nIf document was not found, the method should return an error.\nThen do sign document. the `doSignDocument` method can return an error, to signal\nthat signing didn't go well. And lastly, we need to save signed document to storage back\nand return DTO of that document.\n\nCode might look like this:\n\n```java\n\nclass SignService {\n\n    Result\u003cGenericError, DocumentDto\u003e sign(UUID id) {\n        return Result.fromOptional(repository.findById(id), GenericError.entityNotFound(id))\n                .flatMap(document -\u003e doSignDocument(document))\n                .map(repository::save)\n                .map(mapper::toDto);\n    }\n}\n\n```\n\nSuch code style is good but there is no any compiler support.\nWe have to write all those `maps` and `flatmaps` everywhere.\n\nThe main idea of this library is to add a special method `unwrap` and compiler support for that method.\nThe invocation of this method is going to be detected at compile time and original code is rewritten.\n\nFor example, if we have a local variable declaration like this\n\n```java\nResult\u003cGenericError, DocumentDto\u003e sign(UUID id) {\n    Document document = findDocumentById(id).unwrap();\n    // ...\n}\n```\n\nit's going to be rewritten at compile time to something like this\n\n```java\nResult\u003cGenericError, DocumentDto\u003e sign(UUID id) {\n    Result\u003cGenericError, Document\u003e $$rev = findDocumentById(id);\n    if ($$rev.isError()) {\n        return Result.error($$rev.getError());\n    }\n    Document document = $$rev.get();\n    // ...\n}\n\n```\n\nSo, the original code can be rewritten in more imperative way\n\n```java\n\nclass SignService {\n\n    Result\u003cGenericError, DocumentDto\u003e sign(UUID id) {\n        Document document = Result.fromOptional(repository.findById(id), GenericError.entityNotFound(id)).unwrap();\n        Document signed = doSignDocument(document).unwrap();\n        return Result.success(mapper.toDto(repository.save(signed)));\n    }\n}\n\n```\n\nSuch code is much cleaner, easier to read and write then original one and at the same time explicitly propagates errors\nas original code does.\n\n## Versions\n\nWe are going to support separate version for each LTS release as long as that release is supported.\nIn the following table, you can find the latest result4j version for each supported java version.\n\n| Java\u003cbr/\u003e version | Latest release                                                                                                                                                                                                    |\n|-------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `11`              | [![Maven jdk11](https://img.shields.io/maven-central/v/dev.khbd.result4j/result4j?color=brightgreen\u0026versionSuffix=_jre11)](https://central.sonatype.com/artifact/dev.khbd.result4j/result4j/0.1.4_jre11/overview) \n| `17`              | [![Maven jdk17](https://img.shields.io/maven-central/v/dev.khbd.result4j/result4j?color=brightgreen\u0026versionSuffix=_jre17)](https://central.sonatype.com/artifact/dev.khbd.result4j/result4j/0.1.4_jre17/overview) |\n| `21`              | [![Maven jdk21](https://img.shields.io/maven-central/v/dev.khbd.result4j/result4j?color=brightgreen\u0026versionSuffix=_jre21)](https://central.sonatype.com/artifact/dev.khbd.result4j/result4j/0.1.4_jre21/overview) |\n\n## Maven support\n\nTo enable `unwrap()` call processing in maven-based projects you have to configure `maven-compiler-plugin` to enable `result4j` plugin during compilation.\nAdd the following configuration to your `pom.xml` file and that's it.\n\n```xml\n\n\u003cplugin\u003e\n    \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n    \u003cartifactId\u003emaven-compiler-plugin\u003c/artifactId\u003e\n    \u003cconfiguration\u003e\n        \u003ccompilerArgs\u003e\n            \u003c!-- enable result4j compiler plugin --\u003e\n            \u003carg\u003e-Xplugin:result4j\u003c/arg\u003e\n        \u003c/compilerArgs\u003e\n        \u003cannotationProcessorPaths\u003e\n            \u003cpath\u003e\n                \u003cgroupId\u003edev.khbd.result4j\u003c/groupId\u003e\n                \u003cartifactId\u003eresult4j-processor\u003c/artifactId\u003e\n                \u003cversion\u003eVERSION\u003c/version\u003e\n            \u003c/path\u003e\n        \u003c/annotationProcessorPaths\u003e\n    \u003c/configuration\u003e\n\u003c/plugin\u003e\n```\n\nCompiler plugin uses internal jdk api and this api is [strongly encapsulated by default](https://openjdk.org/jeps/403) in jdk 17.\nTo relax it at compile time configuration should be changed accordingly.\n\n```xml\n\n\u003cplugin\u003e\n    \u003cgroupId\u003eorg.apache.maven.plugins\u003c/groupId\u003e\n    \u003cartifactId\u003emaven-compiler-plugin\u003c/artifactId\u003e\n    \u003cconfiguration\u003e\n        \u003cfork\u003etrue\u003c/fork\u003e\n        \u003ccompilerArgs\u003e\n            \u003c!-- enable result4j compiler plugin --\u003e\n            \u003carg\u003e-Xplugin:result4j prettyPrint=true\u003c/arg\u003e\n            \u003carg\u003e-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED\u003c/arg\u003e\n            \u003carg\u003e-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED\u003c/arg\u003e\n            \u003carg\u003e-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED\u003c/arg\u003e\n            \u003carg\u003e-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED\u003c/arg\u003e\n            \u003carg\u003e-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED\u003c/arg\u003e\n            \u003carg\u003e-J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED\u003c/arg\u003e\n        \u003c/compilerArgs\u003e\n        \u003cannotationProcessorPaths\u003e\n            \u003cpath\u003e\n                \u003cgroupId\u003edev.khbd.result4j\u003c/groupId\u003e\n                \u003cartifactId\u003eresult4j-processor\u003c/artifactId\u003e\n                \u003cversion\u003eVERSION\u003c/version\u003e\n            \u003c/path\u003e\n        \u003c/annotationProcessorPaths\u003e\n    \u003c/configuration\u003e\n\u003c/plugin\u003e\n\n```\nAdditional exports are needed only for compiling process, resulted code will not be dependent on internal jdk api.\n\n## Gradle support\n\ntodo\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkh-bd%2Fresult4j","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkh-bd%2Fresult4j","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkh-bd%2Fresult4j/lists"}