{"id":15523939,"url":"https://github.com/kpavlov/await4j","last_synced_at":"2025-10-28T01:32:18.341Z","repository":{"id":248353880,"uuid":"828444556","full_name":"kpavlov/await4j","owner":"kpavlov","description":"Simplify asynchronous programming in Java with Project Loom virtual threads and a familiar async/await style API","archived":false,"fork":false,"pushed_at":"2025-01-29T05:27:47.000Z","size":446,"stargazers_count":1,"open_issues_count":6,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-02-10T06:14:07.993Z","etag":null,"topics":["async-await","java","project-loom","virtual-threads-java-21"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kpavlov.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":"2024-07-14T07:03:06.000Z","updated_at":"2024-11-03T11:33:22.000Z","dependencies_parsed_at":"2024-08-10T11:26:43.056Z","dependency_job_id":"7df14abe-1a0d-4812-a345-5df76d26b604","html_url":"https://github.com/kpavlov/await4j","commit_stats":null,"previous_names":["kpavlov/await4j"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kpavlov%2Fawait4j","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kpavlov%2Fawait4j/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kpavlov%2Fawait4j/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kpavlov%2Fawait4j/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kpavlov","download_url":"https://codeload.github.com/kpavlov/await4j/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238579805,"owners_count":19495553,"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":["async-await","java","project-loom","virtual-threads-java-21"],"created_at":"2024-10-02T10:47:48.569Z","updated_at":"2025-10-28T01:32:13.053Z","avatar_url":"https://github.com/kpavlov.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Await4J\n\n[![Maven Central](https://img.shields.io/maven-central/v/me.kpavlov.await4j/await4j?labelColor=2a2f35)](https://repo1.maven.org/maven2/me/kpavlov/await4j/await4j/)\n![GitHub License](https://img.shields.io/github/license/kpavlov/await4j?labelColor=2a2f35)\n[![Java CI with Maven](https://github.com/kpavlov/await4j/actions/workflows/maven.yml/badge.svg)](https://github.com/kpavlov/await4j/actions/workflows/maven.yml)\n[![CodeQL](https://github.com/kpavlov/await4j/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/kpavlov/await4j/actions/workflows/github-code-scanning/codeql)\n\n![awaiting.webp](mascot.webp)\n_Simplify Java async programming with virtual threads using an async/await style API._\n\n## TL;DR: Features\n\nThe `Async` class provides utility methods for executing code asynchronously on virtual threads. It simplifies handling of asynchronous operations and exceptions and provides familiar API.\n\n- **`await(() -\u003e {/* blocking code */})`**:\n  Executes a code block on a virtual thread. Handles checked exceptions and wraps them into `RuntimeException`. `RuntimeException` and `Error`are thrown as it is. If any other unexpected `Throwable` occurs, it throws an `IllegalStateException`.\n\n- **`await(Callable\u003cT\u003e block)`**:\n  Executes a `Callable\u003cT\u003e` block on a virtual thread and returns the result. Handles `InterruptedException`, `ExecutionException`, and other general exceptions by wrapping them in a `RuntimeException`.\n\n- **`await(Future\u003cT\u003e future)`**:\n  Waits for the `Future\u003cT\u003e` to complete and returns its result. Internally calls `await(Callable\u003cT\u003e block)`.\n\n- **`await(CompletableFuture\u003cT\u003e completableFuture)`**:\n  Waits for the `CompletableFuture\u003cT\u003e` to complete and returns its result. Internally calls `await(Callable\u003cT\u003e block)`.\n\nSee [Sample.java](src/test/java/me/kpavlov/await4j/Sample.java).\n\n## Background\n\nProject Loom has introduced Virtual Threads, but the API requires some boilerplate code to use it effectively in real-life projects:\n\nTo run blocking code in a Virtual Thread, it should be wrapped in:\n```java\nThread.ofVirtual().start(() -\u003e {\n    // run some blocking code here\n}).join()\n```\n\nWhen you need to get the execution result back, a common approach is to run it in an executor:\n\n```java\nint returnFromVirtualThread() {\n    try (final var executor = Executors.newVirtualThreadPerTaskExecutor()) {\n        final var task = executor.submit(() -\u003e {\n            // Do some expensive calculation here\n            return 42; // Return result\n        });\n        return task.get(); // Get result from task\n    } catch (ExecutionException e) {\n        throw new RuntimeException(e);\n    } catch (InterruptedException e) {\n        Thread.currentThread().interrupt();\n        throw new RuntimeException(e);\n    }\n}\n```\n\n## The Better Async API\n\nWhat if it were possible to use syntax similar to Javascript's `async/await` style?\n\nThis library introduces helpful utilities to simplify calls in Virtual Threads:\n\nFor example, to call a lambda function, even throwing exceptions, use:\n\n```java\nimport me.kpavlov.await4j.Async.await;\n...\n\nfinal var completed = new AtomicBoolean();\n\nfinal var slowCalculation = () -\u003e {\n  // Do something slow in a virtual thread\n  try {\n    Thread.sleep(1000);\n  } catch (InterruptedException e) {\n    throw new RuntimeException(e);\n  }\n  // Set flag to \"true\" to indicate, that the task is completed\n  completed.set(true);\n};\n\nawait(slowCalculation);\n\n// Verify that calculation has been completed\nSystem.out.println(\"Completed: \" + completed.get()); // \"Completed: true\"\n```\n\nTo call a lambda that returns a value (Callable), use:\n\n```java\nimport me.kpavlov.await4j.Async.await;\n...\n\nfinal var result = await(() -\u003e {\n    // Do some expensive calculation here\n    try {\n        Thread.sleep(1000);\n    } catch (InterruptedException e) {\n        throw new RuntimeException(e);\n    }\n    // Return the result\n    return 42; \n});\nSystem.out.println(\"Result: \" + result); // \"Result: 42\"\n```\n\nLambdas may throw exceptions, unlike the `java.lang.Runnable` interface. All non-runtime exceptions are wrapped in `java.lang.RuntimeException`, and `java.lang.Error` will be re-thrown.\n\n## Wrapping `CompletableFuture` and `Future`\n\nUsing `java.util.concurrent.CompletableFuture` and `java.util.concurrentFuture` from the Java API is also simplified:\n\n```java\nfinal CompletableFuture\u003cInteger\u003e completableFuture = CompletableFuture.supplyAsync(() -\u003e {\n  // Do some expensive calculation here\n  try {\n    Thread.sleep(1000);\n  } catch (InterruptedException e) {\n    throw new RuntimeException(e);\n  }\n  // Return the result\n  return 42;\n});\n\nfinal var completableFutureResult = await(completableFuture);\nSystem.out.println(\"CompletableFuture result: \" + completableFutureResult); // \"Result: 42\"\n\nfinal var futureResult = await((Future\u003cInteger\u003e) completableFuture);\nSystem.out.println(\"Future Result: \" + futureResult); // \"Result: 42\"\n```\n\nSee full list of requirements [here](REQUIREMENTS.md).\n\n## Useful Utility Classes\n\n- [Result\u0026lt;T\u0026gt;](src/main/java/me/kpavlov/utils/Result.java) - A discriminated union that encapsulates a successful outcome with a value of type T or a failure with an arbitrary Throwable exception. Similar to [Result](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/) in Kotlin.\n- [ThrowingRunnable](src/main/java/me/kpavlov/utils/ThrowingRunnable.java) - Runnable, which can throw Exception\n\n## Final Notes\n\n**If you want to write better code on JVM, use [Kotlin Coroutines](https://kotlinlang.org/docs/coroutines-overview.html).** This library remains a simpler choice for Java projects where adopting or migrating to [Kotlin](https://kotlinlang.org) is not feasible.\n\nThe library focuses on running blocking code on Virtual Threads without providing additional parallelism optimizations. If your IO operations are slow, they will not run faster. If a lambda takes one second to run, `await(...)` will also take approximately one second, but on a virtual thread.\n\n## How to Get Started\n\n1. Add project dependency. Latest version can be found on [maven central repository](https://mvnrepository.com/artifact/me.kpavlov.await4j/await4j):\n\n    Maven:\n    ```xml\n    \u003c!-- https://mvnrepository.com/artifact/me.kpavlov.await4j/await4j --\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eme.kpavlov.await4j\u003c/groupId\u003e\n        \u003cartifactId\u003eawait4j\u003c/artifactId\u003e\n        \u003cversion\u003e[LATEST]\u003c/version\u003e\n    \u003c/dependency\u003e\n    ```\n\n    Gradle:\n    ```kotlin\n    // https://mvnrepository.com/artifact/me.kpavlov.await4j/await4j\n      implementation(\"me.kpavlov.await4j:await4j:${await4jVersion}\")\n    ```\n\n2. Import methods from [Async](src/main/java/me/kpavlov/await4j/Async.java)\n\n    ```java\n    import me.kpavlov.await4j.Async.await;\n    ```\n\n## Links\n\n- [JEP 444: Virtual Threads](https://openjdk.org/jeps/444) -- Virtual threads are lightweight threads that dramatically reduce the effort of writing, maintaining, and observing high-throughput concurrent applications.\n- [JEP 480: Structured Concurrency](https://openjdk.org/jeps/480) -- Simplify concurrent programming by introducing an API for structured concurrency. Structured concurrency treats groups of related tasks running in different threads as a single unit of work, thereby streamlining error handling and cancellation, improving reliability, and enhancing observability. This is a preview API.\n- [JEP 429: ScopedValues](https://openjdk.org/jeps/429) -- Scoped values enables sharing of immutable data within and across threads. They are preferred to thread-local variables, especially when using large numbers of virtual threads. This is an incubating API.\n- [Java Async-Await](https://github.com/AugustNagro/java-async-await) -- Async-Await support for Java CompletionStage.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkpavlov%2Fawait4j","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkpavlov%2Fawait4j","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkpavlov%2Fawait4j/lists"}