https://github.com/kh-bd/result4j
Library with simple primitives like `Option` and `Result`.
https://github.com/kh-bd/result4j
java library
Last synced: 5 months ago
JSON representation
Library with simple primitives like `Option` and `Result`.
- Host: GitHub
- URL: https://github.com/kh-bd/result4j
- Owner: kh-bd
- Created: 2024-01-05T15:03:48.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-06-15T14:17:42.000Z (about 2 years ago)
- Last Synced: 2025-09-15T02:45:17.266Z (10 months ago)
- Topics: java, library
- Language: Java
- Homepage:
- Size: 399 KB
- Stars: 2
- Watchers: 3
- Forks: 0
- Open Issues: 9
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Result4j
Result4j is a library with simple functional primitives like `Option` and `Result` with compiler support for them.
[](https://github.com/kh-bd/result4j/actions/workflows/main-tests.yml)
## Why do we need it?
All we love functional primitives like `Option` and `Result`.
To use such primitives properly we have to write our code in so-called monad style
with higher-order functions like `map` and `flatmap`.
For example, we have a simplified service to sign a document.
First of all, we need to search a document in a storage.
If document was not found, the method should return an error.
Then do sign document. the `doSignDocument` method can return an error, to signal
that signing didn't go well. And lastly, we need to save signed document to storage back
and return DTO of that document.
Code might look like this:
```java
class SignService {
Result sign(UUID id) {
return Result.fromOptional(repository.findById(id), GenericError.entityNotFound(id))
.flatMap(document -> doSignDocument(document))
.map(repository::save)
.map(mapper::toDto);
}
}
```
Such code style is good but there is no any compiler support.
We have to write all those `maps` and `flatmaps` everywhere.
The main idea of this library is to add a special method `unwrap` and compiler support for that method.
The invocation of this method is going to be detected at compile time and original code is rewritten.
For example, if we have a local variable declaration like this
```java
Result sign(UUID id) {
Document document = findDocumentById(id).unwrap();
// ...
}
```
it's going to be rewritten at compile time to something like this
```java
Result sign(UUID id) {
Result $$rev = findDocumentById(id);
if ($$rev.isError()) {
return Result.error($$rev.getError());
}
Document document = $$rev.get();
// ...
}
```
So, the original code can be rewritten in more imperative way
```java
class SignService {
Result sign(UUID id) {
Document document = Result.fromOptional(repository.findById(id), GenericError.entityNotFound(id)).unwrap();
Document signed = doSignDocument(document).unwrap();
return Result.success(mapper.toDto(repository.save(signed)));
}
}
```
Such code is much cleaner, easier to read and write then original one and at the same time explicitly propagates errors
as original code does.
## Versions
We are going to support separate version for each LTS release as long as that release is supported.
In the following table, you can find the latest result4j version for each supported java version.
| Java
version | Latest release |
|-------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `11` | [](https://central.sonatype.com/artifact/dev.khbd.result4j/result4j/0.1.4_jre11/overview)
| `17` | [](https://central.sonatype.com/artifact/dev.khbd.result4j/result4j/0.1.4_jre17/overview) |
| `21` | [](https://central.sonatype.com/artifact/dev.khbd.result4j/result4j/0.1.4_jre21/overview) |
## Maven support
To enable `unwrap()` call processing in maven-based projects you have to configure `maven-compiler-plugin` to enable `result4j` plugin during compilation.
Add the following configuration to your `pom.xml` file and that's it.
```xml
org.apache.maven.plugins
maven-compiler-plugin
-Xplugin:result4j
dev.khbd.result4j
result4j-processor
VERSION
```
Compiler plugin uses internal jdk api and this api is [strongly encapsulated by default](https://openjdk.org/jeps/403) in jdk 17.
To relax it at compile time configuration should be changed accordingly.
```xml
org.apache.maven.plugins
maven-compiler-plugin
true
-Xplugin:result4j prettyPrint=true
-J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
-J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
-J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
-J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
-J--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
-J--add-exports=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
dev.khbd.result4j
result4j-processor
VERSION
```
Additional exports are needed only for compiling process, resulted code will not be dependent on internal jdk api.
## Gradle support
todo