{"id":25181694,"url":"https://github.com/vipcxj/jasync","last_synced_at":"2025-05-07T08:32:57.697Z","repository":{"id":41434478,"uuid":"377588002","full_name":"vipcxj/jasync","owner":"vipcxj","description":"make async-await code style available in java just like csharp and es6","archived":false,"fork":false,"pushed_at":"2023-10-24T18:12:11.000Z","size":1405,"stargazers_count":129,"open_issues_count":4,"forks_count":14,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-31T08:12:09.476Z","etag":null,"topics":["annotation-processor","async","async-await","await","java"],"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/vipcxj.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}},"created_at":"2021-06-16T18:12:26.000Z","updated_at":"2025-02-10T14:43:40.000Z","dependencies_parsed_at":"2023-09-24T15:09:53.508Z","dependency_job_id":"5dc282b8-b23c-45a3-a92e-b3f641ca965a","html_url":"https://github.com/vipcxj/jasync","commit_stats":null,"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vipcxj%2Fjasync","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vipcxj%2Fjasync/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vipcxj%2Fjasync/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vipcxj%2Fjasync/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vipcxj","download_url":"https://codeload.github.com/vipcxj/jasync/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252843014,"owners_count":21812786,"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":["annotation-processor","async","async-await","await","java"],"created_at":"2025-02-09T17:18:43.607Z","updated_at":"2025-05-07T08:32:57.673Z","avatar_url":"https://github.com/vipcxj.png","language":"Java","readme":"JAsync - the async-await pattern of Java\n===============\n\n[![Maven Release][maven-shield]][maven-link]\n\n[中文版](/README_CN.md)\n\n**JAsync** implements Async-Await pattern just like es in Java. \nIt allows developers to write asynchronous code in a sequential fashion.\nIt makes the developer's asynchronous programming experience as close as possible to the usual synchronous programming, including code style and debugging.\n\nOn the other hand, this framework separates the realization of the upper-level syntax tree conversion and the lower-level asynchronous workflow through a set of interfaces. This project focuses on the former, while the latter can be achieved by encapsulating existing asynchronous libraries, such as Reactor, RxJava, etc.\nThe advantage of this is that this project can be seamlessly integrated with various asynchronous libraries that have been widely used in the community to produce an effect of 1+1\u003e2.\n\nRequirement\n===\njdk \u003e= 8\n\nExamples\n=======\n#### With JAsync\n```java\n@RestController\n@RequestMapping(\"/employees\")\npublic class MyRestController {\n    @Inject\n    private EmployeeRepository employeeRepository;\n    @Inject\n    private SalaryRepository salaryRepository;\n\n    // The standard JAsync async method must be annotated with the Async annotation, and return a JPromise object.\n    @Async()\n    private JPromise\u003cDouble\u003e _getEmployeeTotalSalaryByDepartment(String department) {\n        double money = 0.0;\n        // A Mono object can be transformed to the JPromise object. So we get a Mono object first.\n        Mono\u003cList\u003cEmployee\u003e\u003e empsMono = employeeRepository.findEmployeeByDepartment(department);\n        // Transformed the Mono object to the JPromise object.\n        JPromise\u003cList\u003cEmployee\u003e\u003e empsPromise = Promises.from(empsMono);\n        // Use await just like es and c# to get the value of the JPromise without blocking the current thread.\n        for (Employee employee : empsPromise.await()) {\n            // The method findSalaryByEmployee also return a Mono object. We transform it to the JPromise just like above. And then await to get the result.\n            Salary salary = Promises.from(salaryRepository.findSalaryByEmployee(employee.id)).await();\n            money += salary.total;\n        }\n        // The async method must return a JPromise object, so we use just method to wrap the result to a JPromise.\n        return JAsync.just(money);\n    }\n\n    // This is a normal webflux method.\n    @GetMapping(\"/{department}/salary\")\n    public Mono\u003cDouble\u003e getEmployeeTotalSalaryByDepartment(@PathVariable String department) { \n        // Use unwrap method to transform the JPromise object back to the Mono object.\n        return _getEmployeeTotalSalaryByDepartment(department).unwrap(Mono.class);\n    }\n}\n```\nIn this example, **JAsync** rewrite the code like `XXX.await()` to `XXX.thenVoid(v -\u003e { ... })` to making your methods non-blocking.\nWith **JAsync**, you can not only enjoy the high throughput of non-blocking programming, but also avoid callback hell and counter-intuitive chained function calls.\n\n#### What JAsync do.\n```java\n@RestController\n@RequestMapping(\"/employees\")\npublic class MyRestController {\n    @Inject\n    private EmployeeRepository employeeRepository;\n    @Inject\n    private SalaryRepository salaryRepository;\n\n    @Async()\n    private JPromise\u003cDouble\u003e _getEmployeeTotalSalaryByDepartment(String department) {\n        double money = 0.0;\n        DoubleReference moneyRef = new DoubleReference(money);\n        Mono\u003cList\u003cEmployee\u003e\u003e empsMono = employeeRepository.findEmployeeByDepartment(department);\n        JPromise\u003cList\u003cEmployee\u003e\u003e empsPromise = Promises.from(empsMono);\n        return empsPromise.thenVoid(v0 -\u003e JAsync.doForEachObject(v0, employee -\u003e\n                Promises.from(salaryRepository.findSalaryByEmployee(employee.id)).thenVoid(v1 -\u003e {\n                    moneyRef.addAndGet(v1.total);\n                })\n            ).thenVoid(() -\u003e JAsync.doReturn(JAsync.just(moneyRef.getValue())))).catchReturn();\n    }\n\n    // This is a normal webflux method.\n    @GetMapping(\"/{department}/salary\")\n    public Mono\u003cDouble\u003e getEmployeeTotalSalaryByDepartment(@PathVariable String department) { \n        // Use unwrap method to transform the JPromise object back to the Mono object.\n        return _getEmployeeTotalSalaryByDepartment(department).unwrap(Mono.class);\n    }\n}\n```\n\nHow to use?\n=======\nFirst, select a implementation library to the Maven dependency. Currently, only one implementation is available.\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.vipcxj\u003c/groupId\u003e\n    \u003cartifactId\u003ejasync-reactive\u003c/artifactId\u003e\n    \u003cversion\u003e0.1.9\u003c/version\u003e\n\u003c/dependency\u003e\n```\nThis implementation uses the famous library **Reactor**. The `JPromise` object is a wrapper of `Mono` object.\nSo the `JPromise` object can be created from a `Mono` object using static method `io.github.vipcxj.jasync.reactive.Promises.from(reactor.core.publisher.Mono\u003cT\u003e)`.\nAnd the `JPromise` object can be converted back to the `Mono` object using instance method `JPromise.unwrap`.\n\nThen add the core library to the Maven dependency.\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.vipcxj\u003c/groupId\u003e\n    \u003cartifactId\u003ejasync-core\u003c/artifactId\u003e\n    \u003cversion\u003e0.1.9\u003c/version\u003e\n    \u003cscope\u003eprovided\u003c/scope\u003e\n\u003c/dependency\u003e\n```\nThe core library is only need at compile stage, so here use the **provided** scope.\nGenerally, the annotation processor should be discovered by jdk automatically.\nHowever, if something went wrong, jdk can not find the annotation processor, try this:\n```xml\n\u003cplugins\u003e\n  \u003cplugin\u003e\n    \u003cartifactId\u003emaven-compiler-plugin\u003c/artifactId\u003e\n    \u003cconfiguration\u003e\n      \u003cannotationProcessorPaths\u003e\n        \u003cpath\u003e\n          \u003cgroupId\u003eio.github.vipcxj\u003c/groupId\u003e\n          \u003cartifactId\u003ejasync-core\u003c/artifactId\u003e\n          \u003cversion\u003e0.1.9\u003c/version\u003e\n        \u003c/path\u003e\n      \u003c/annotationProcessorPaths\u003e\n    \u003c/configuration\u003e\n  \u003c/plugin\u003e\n\u003c/plugins\u003e\n```\n**Note:** If there exists `annotationProcessorPaths` configure, the dependency configure will not work. \n\nDebug mode\n===\n**JAsync** support a debug mode. With debug mode on, **JAsync** will inject all useful variable to the current context, even they are not captured.\nAs a result, When debugging, the developer can see all the variables in the monitor window just like debugging normal code.\n\nFor example, with debug mode off:\n\n![alt debug mode off](/debug-off.png)\n\nWith debug mode on:\n\n![alt debug mode on](/debug-on.png)\n\nIt can be seen that when the debug mode is turned on, all the defined variables can be found in the monitoring window.\n\nAbout Lombok\n===\nIf you are using **Lombok**, you should place the **JAsync** after the **Lombok**, just like this:\n```xml\n\u003cplugins\u003e\n  \u003cplugin\u003e\n    \u003cartifactId\u003emaven-compiler-plugin\u003c/artifactId\u003e\n    \u003cconfiguration\u003e\n      \u003cannotationProcessorPaths\u003e\n         \u003cpath\u003e\n            \u003cgroupId\u003eorg.projectlombok\u003c/groupId\u003e\n            \u003cartifactId\u003elombok\u003c/artifactId\u003e\n            \u003cversion\u003e1.18.22\u003c/version\u003e\n         \u003c/path\u003e\n        \u003cpath\u003e\n          \u003cgroupId\u003eio.github.vipcxj\u003c/groupId\u003e\n          \u003cartifactId\u003ejasync-core\u003c/artifactId\u003e\n          \u003cversion\u003e0.1.9\u003c/version\u003e\n        \u003c/path\u003e\n      \u003c/annotationProcessorPaths\u003e\n    \u003c/configuration\u003e\n  \u003c/plugin\u003e\n\u003c/plugins\u003e\n```\n\nKnown Issues\n===\n1. Not support new `switch` syntax introduced in java 17. It will be supported in the near future.\n2. Not support ejc (eclipse java compiler). I will try my best to support it. \n   Currently, you can compile the project using maven or gradle, then debug using ejc.\n\n[maven-shield]: https://img.shields.io/maven-central/v/io.github.vipcxj/jasync-parent.png\n[maven-link]: https://search.maven.org/artifact/io.github.vipcxj/jasync-parent","funding_links":[],"categories":["并发编程"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvipcxj%2Fjasync","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvipcxj%2Fjasync","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvipcxj%2Fjasync/lists"}