├── .build
├── deploy-snapshot.sh
├── perform-release.sh
├── release.sh
└── settings.xml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── me
│ └── escoffier
│ └── vertx
│ └── completablefuture
│ └── VertxCompletableFuture.java
└── test
└── java
└── me
└── escoffier
└── vertx
└── completablefuture
├── CompletableFutureOperatorTest.java
├── SupplyAndRunAsyncTest.java
├── VertxCompletableFutureTest.java
└── examples
└── HttpClientTest.java
/.build/deploy-snapshot.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # Deploy a jar, source jar, and javadoc jar to Sonatype's snapshot repo.
4 | #
5 |
6 | REPO="cescoffier/vertx-completable-future"
7 | BRANCH="master"
8 |
9 | set -e
10 | echo "Configuring deployment using ${SONATYPE_USERNAME} for repository ${TRAVIS_REPO_SLUG}"
11 | if [ "$TRAVIS_REPO_SLUG" != "$REPO" ]; then
12 | echo "Skipping snapshot deployment: wrong repository. Expected '$REPO' but was '$TRAVIS_REPO_SLUG'."
13 | elif [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
14 | echo "Skipping snapshot deployment: was pull request."
15 | elif [ "$TRAVIS_BRANCH" != "$BRANCH" ]; then
16 | echo "Skipping snapshot deployment: wrong branch. Expected '$BRANCH' but was '$TRAVIS_BRANCH'."
17 | else
18 | echo "Deploying snapshot..."
19 | mvn clean source:jar javadoc:jar deploy --settings=".build/settings.xml" -Dmaven.test.skip=true -Psonatype
20 | echo "Snapshot deployed!"
21 | fi
22 |
--------------------------------------------------------------------------------
/.build/perform-release.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e
3 |
4 | RED='\033[0;31m'
5 | NC='\033[0m' # No Color
6 | YELLOW='\033[0;33m'
7 | BLUE='\033[0;34m'
8 |
9 | # Extract versions
10 | LAST_TAG=$(git tag -l --sort=-v:refname | head -n 1)
11 |
12 | echo -e "${BLUE}Last tag:${YELLOW} ${LAST_TAG} ${NC}"
13 |
14 | cd target || exit
15 | export GPG_TTY=$(tty)
16 | echo -e "${BLUE}Cloning repo${NC}"
17 | git clone git@github.com:cescoffier/vertx-completable-future release-work
18 | cd release-work
19 | echo -e "${BLUE}Switching to tag${NC}"
20 | git checkout ${LAST_TAG}
21 | echo -e "${BLUE}Running deployment${NC}"
22 | mvn deploy -Psonatype,release
23 |
24 | #echo -e "${BLUE}Build doc${NC}"
25 | #mvn -Pdoc-html
26 | #echo -e "${BLUE}Deploying doc${NC}"
27 | #git clone -b gh-pages git@github.com:cescoffier/vertx-completable-future gh-pages
28 | #cp -rv target/generated-docs/* gh-pages
29 | #cd gh-pages
30 | #git add --ignore-errors *
31 | #git commit -m "generated documentation"
32 | #git push origin gh-pages
33 |
34 | cd ../.. || exit
35 |
36 |
37 |
--------------------------------------------------------------------------------
/.build/release.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -e
3 |
4 | RED='\033[0;31m'
5 | NC='\033[0m' # No Color
6 | YELLOW='\033[0;33m'
7 | BLUE='\033[0;34m'
8 |
9 | # Extract versions
10 | LAST_TAG=$(git tag -l --sort=-v:refname | head -n 1)
11 | VERSION=""
12 | NEXT_DEV_VERSION=""
13 | TAG=""
14 |
15 | echo "Last tag: ${LAST_TAG}"
16 | regex="v([0-9]+).([0-9]+).([0-9]+)"
17 | if [[ ${LAST_TAG} =~ $regex ]]
18 | then
19 | major="${BASH_REMATCH[1]}"
20 | minor="${BASH_REMATCH[2]}"
21 | micro="${BASH_REMATCH[3]}"
22 | VERSION=${major}.${minor}.$(($micro +1))
23 | TAG="v${VERSION}"
24 | NEXT_DEV_VERSION="${major}.${minor}-SNAPSHOT"
25 | echo -e "${BLUE}Release version: ${YELLOW}${VERSION} ${NC}"
26 | echo -e "${BLUE}Next development version: ${YELLOW}${NEXT_DEV_VERSION} ${NC}"
27 | else
28 | echo -e "${RED}Invalid last tag ${NC}"
29 | exit -1
30 | fi
31 |
32 | # Update version in pom.xml file
33 | echo -e "${BLUE}Updating project version to: ${YELLOW} ${VERSION} ${NC}"
34 | mvn versions:set -DnewVersion=${VERSION} >& bump-version-dev.log
35 | echo -e "${BLUE}Issuing a verification build${NC}"
36 | mvn clean install -DskipTests >& fast-build.log
37 |
38 | echo -e "${BLUE}Committing changes${NC}"
39 | git commit -am "Releasing version ${VERSION}"
40 |
41 | echo -e "${BLUE}Creating the tag ${YELLOW}${TAG}${NC}"
42 | git tag -a ${TAG} -m "Releasing ${TAG}"
43 |
44 | echo -e "${BLUE}Updating project version to: ${YELLOW}${NEXT_DEV_VERSION}${NC}"
45 | mvn versions:set -DnewVersion=${NEXT_DEV_VERSION} >& bump-version-dev.log
46 |
47 | mvn clean install -DskipTests >& fast-build-dev.log
48 |
49 | echo -e "${BLUE}Committing changes${NC}"
50 | git commit -am "Bumping version to ${NEXT_DEV_VERSION}"
51 |
52 | echo -e "${BLUE}Pushing changes${NC}"
53 | git push origin master --tags
54 |
55 | rm -Rf *.log pom.xml.versionsBackup
56 |
57 |
58 |
--------------------------------------------------------------------------------
/.build/settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | sonatype-nexus-snapshots
5 | ${env.SONATYPE_USERNAME}
6 | ${env.SONATYPE_PASSWORD}
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | ### Java template
3 | *.class
4 |
5 | # Mobile Tools for Java (J2ME)
6 | .mtj.tmp/
7 |
8 | # Package Files #
9 | *.jar
10 | *.war
11 | *.ear
12 |
13 | .project
14 | .classpath
15 | .settings
16 |
17 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
18 | hs_err_pid*
19 | ### Maven template
20 | target/
21 | pom.xml.tag
22 | pom.xml.releaseBackup
23 | pom.xml.versionsBackup
24 | pom.xml.next
25 | release.properties
26 | dependency-reduced-pom.xml
27 | buildNumber.properties
28 | .mvn/timing.properties
29 |
30 |
31 | ### Vert.x
32 | .vertx
33 |
34 | ### IntelliJ
35 | .idea/
36 | *.iml
37 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | jdk:
3 | - openjdk8
4 | addons:
5 | sonarcloud:
6 | organization: reactiverse-vertx-maven-plugin
7 | token:
8 | secure: "s/a5VFbYyomNVymcgpHdX74vHscmmJedwVwOFajYsiArfhvjlpY45s/0ATuvFzWc98qyoQlztcNmIHEtFD3gdJMYoTgz2sEDNUZ4OC5K95SPIMLeYmw/IxXP7IsLqeBwrZX+yjwXzZgkevqMNkdAtKtsSTN/B9XOXuG3zn397WFVA6X4m6psG8YwPOyZafCDEqgauCX19jmaEXwD3e4mzptay3dfzwVV8rghAgrCpc3tSK076nhzYmZZ7LG1L8l1Pk0pvvLLO6YRRDassre07nOQlZcv1GlSVn4Ce/ZcSz7O2q0usyJ3iTU/atovjbdOTB56oybe0kSWosXWFki8r4Az3vkr+IAvAkDf7R56ly7s/CLs7Ka874mLBvVdGWwNXfBV5/3E8TJYRasukNwJOqGRc3AVytcJp7p7TwpQce8kk8MnVoH6k1h4qUoLPSTjt6K12Yee64bukGAG0OrY3vxDU86EtXpnopMhty1qzN/IYAJ14hHKTuqp5USLRpfPTzE21SrV/ZxUBuT4ySxPwAu7SCvwaLPJTj95sDnZnoL7S1I/fHvwG2IwwOT5YyP91l7FTvggXmWvC7X5spviri/wIEwr0loCfJU+FfwKrFHx6tw7g+XoSD80agU3NooAeGkVVfEm5/rKHxPFfBXm0NfkI8WSz2ooqrwxXzBjbTo="
9 | env:
10 | global:
11 | - SONATYPE_USERNAME="clement.escoffier"
12 | - secure: h887vbdiBD8HPV0Ltssu2JIUWVHKHkshxiXu/7uh9ZFQyyzqVWLTjcSeXWqWwKgTVgUtDBtF0OICw7RqKAKzSA2EX+v0A9EzkkR2cqa5EKlii1GJRec7qbteRUIln0ejNHYKo66wzU3p/1AGMGK7b8nAu3jdAViTFgQ2b/1RHSA6lCWsOFMPkQVxGwsexXifWIIps4wCKmFmCN5yzFLOPDfv9bV76jcC5MyUy4KuLW8igm2ygJ8b+O71t3WJNPf12s/mRWcQ5AaRU772l8affbDvDjeud+IHpG7vmWCnCrVd2pLogfLnL/4Uj6uXhLScuHzynqAWRTW2GOrwbBEV5Qz01fcVTE2J1KfEkeQtGhpCWcB/6YQOgilttK0k+nwENxehg2fJgR5ZvxcfO+qkOMWsDNCGHRYKvQlJFHiY3DHsE4DuAKxE8WK5fVMNWA4eslAPJW/NOY5PQ0p8jWo2JSyR/ZvKPtR2z4CpwQcMgrtFIZWe4DhZbf73MedQ7n8qtx+WuBW1iL5fSUMye63VYuTILUTmNotrBSARqonlbZ5iglviZUwB/rm8dNklCNufuuEOeBkCLLuygF2/6mIlYN5X+UL1RZWsy4nx0oMNE6/TAGSoKPjt0DMYSABssPCJ7MRniIDzwhoJ6/CSlAnii29OGzcLEGQ2CXsLeE4NiRs=
13 | script:
14 | - mvn clean install sonar:sonar -Pcoverage -Dsonar.host.url=https://sonarcloud.io/
15 | after_success:
16 | - ".build/deploy-snapshot.sh"
17 | notifications:
18 | email:
19 | - clement@apache.org
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Vert.x Completable Future
2 |
3 | This project provides a way to use the Completable Future API with Vert.x.
4 |
5 | ## Why can't you use Completable Future with Vert.x
6 |
7 | Using Completable Future with Vert.x may lead to some thread issues.
8 |
9 | When you execute an asynchronous operation with Vert.x, the `Handler>` is called on on the same thread as the method having enqueued the asynchronous operation. Thanks to this _single-threaded_ aspect, Vert.x removes the need of synchronization and also it improves performances.
10 |
11 | Completable Future uses a fork-join thread pool. So callbacks (dependent stages) are called in a thread of this pool, so it's not the caller thread.
12 |
13 | This project provides the Completable Future API but enforces the Vert.x threading model:
14 |
15 | * When using `xAsync` methods (without `executor`), the callbacks are called on the Vert.x context
16 | * When using non-async, it uses the caller thread. If it's a Vert.x thread the same thread is used. If not called from a Vert.x thread,
17 | it still uses the caller thread
18 | * When using `xAsync` methods with an `Executor` parameter, this executor is used to execute the callback (does not enforce the Vert.x thread system)
19 |
20 | ## Examples
21 |
22 | All methods taking a `Vertx` instance as parameter exists with a `Context` parameter.
23 |
24 | ### Creating a VertxCompletableFuture
25 |
26 | ```
27 | // From a Vert.x instance
28 | CompletableFuture future = new VertxCompletableFuture(vertx);
29 |
30 | // From a specific context
31 | Context context = ...
32 | CompletableFuture future = new VertxCompletableFuture(context);
33 |
34 | // From a completable future
35 | CompletableFuture cf = ...
36 | CompletableFuture future = VertxCompletableFuture.from(context, cf);
37 |
38 | // From a Vert.x future
39 | Future fut = ...
40 | CompletableFuture future = VertxCompletableFuture.from(context, fut);
41 | ```
42 |
43 | You can also pass a `Supplier` or a `Runnable`:
44 |
45 | ```
46 | // Run in context
47 | CompletableFuture future = VertxCompletableFuture.supplyAsync(vertx, () -> return "foo";);
48 | // Run in Vert.x worker thread
49 | CompletableFuture future = VertxCompletableFuture.supplyBlockingAsync(vertx, () -> return "foo");
50 |
51 | CompletableFuture future = VertxCompletableFuture.runAsync(vertx, () -> System.out.println(foo"));
52 | CompletableFuture future = VertxCompletableFuture.runBlockingAsync(vertx, () -> System.out.println(foo"));
53 | ```
54 |
55 | _*BlockingAsync_ method uses a Vert.x worker thread and do not block the Vert.x Event Loop.
56 |
57 | ### Stages
58 |
59 | Once you have the `VertxCompletableFuture` instance, you can use the `CompletableFuture` API:
60 |
61 | ```
62 | VertxCompletableFuture future = new VertxCompletableFuture<>(vertx);
63 | future
64 | .thenApply(this::square)
65 | .thenAccept(System.out::print)
66 | .thenRun(System.out::println);
67 |
68 | // Somewhere in your code, later...
69 | future.complete(42);
70 | ```
71 |
72 | You can compose, combine, join completable futures with:
73 |
74 | * combine
75 | * runAfterEither
76 | * acceptEither
77 | * runAfterBoth
78 | * ...
79 |
80 | ### All and Any operations
81 |
82 | The `VertxCompletableFuture` class offers two composition operators:
83 |
84 | * `allOf` - execute all the passed `CompletableFuture` (not necessarily `VertxCompletableFuture`) and calls dependant stages when all of the futures have been completed or one has failed
85 | * `anyOf` - execute all the passed `CompletableFuture` (not necessarily `VertxCompletableFuture`) and calls dependant stages when one of them has been completed
86 |
87 | Unlike `CompletableFuture`, the dependent stages are called in the Vert.x context.
88 |
89 | ```
90 | HttpClientOptions options = new HttpClientOptions().setDefaultPort(8080).setDefaultHost("localhost");
91 | HttpClient client1 = vertx.createHttpClient(options);
92 | HttpClient client2 = vertx.createHttpClient(options);
93 |
94 | VertxCompletableFuture requestA = new VertxCompletableFuture<>(vertx);
95 | client1.get("/A").handler(resp -> {
96 | resp.exceptionHandler(requestA::completeExceptionally)
97 | .bodyHandler(buffer -> {
98 | requestA.complete(Integer.parseInt(buffer.toString()));
99 | });
100 | }).exceptionHandler(requestA::completeExceptionally).end();
101 |
102 | VertxCompletableFuture requestB = new VertxCompletableFuture<>(vertx);
103 | client2.get("/B").handler(resp -> {
104 | resp.exceptionHandler(requestB::completeExceptionally)
105 | .bodyHandler(buffer -> {
106 | requestB.complete(Integer.parseInt(buffer.toString()));
107 | });
108 | }).exceptionHandler(requestB::completeExceptionally).end();
109 |
110 |
111 | VertxCompletableFuture.allOf(requestA, requestB).thenApply(v -> requestA.join() + requestB.join())
112 | .thenAccept(i -> {
113 | tc.assertEquals(65, i);
114 | async.complete();
115 | });
116 | }
117 | ```
118 |
119 | ### From / To Vert.x Futures
120 |
121 | You can transform a `VertxCompletableFuture` to a Vert.x `Future` with the `toFuture` method.
122 |
123 | You can also creates a new `VertxCompletableFuture` from a Vert.x `Future` using:
124 |
125 | ```
126 | Future vertxFuture = ...
127 | VertxCompletableFuture vcf = VertxCompletableFuture.from(vertx, vertxFuture);
128 |
129 | vcf.thenAccept(i -> {...}).whenComplete((res, err) -> {...})
130 | ```
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4.0.0
5 |
6 | me.escoffier.vertx
7 | vertx-completable-future
8 | 0.1.3-SNAPSHOT
9 |
10 | Vert.x Completable Future
11 | An implementation of CompletableFuture for Vert.x 3.x
12 | https://github.com/cescoffier/vertx-completable-future
13 |
14 |
15 |
16 | Apache License 2.0
17 | http://www.apache.org/licenses/LICENSE-2.0
18 |
19 |
20 |
21 |
22 |
23 | UTF-8
24 | 3.7.1
25 |
26 |
27 |
28 |
29 | io.vertx
30 | vertx-core
31 |
32 | provided
33 |
34 |
35 | junit
36 | junit
37 | 4.13.1
38 | test
39 |
40 |
41 | io.vertx
42 | vertx-unit
43 | test
44 |
45 |
46 | com.google.guava
47 | guava
48 | 28.0-jre
49 | test
50 |
51 |
52 |
53 |
54 |
55 | io.vertx
56 | vertx-dependencies
57 | ${vertx.version}
58 | pom
59 | import
60 |
61 |
62 |
63 |
64 |
65 |
66 | ossrh
67 | https://oss.sonatype.org/content/repositories/snapshots
68 |
69 |
70 |
71 |
72 |
73 |
74 | org.sonatype.plugins
75 | nexus-staging-maven-plugin
76 | 1.6.8
77 | true
78 |
79 | ossrh
80 | https://oss.sonatype.org/
81 | true
82 |
83 |
84 |
85 | maven-compiler-plugin
86 | 3.8.1
87 |
88 | 1.8
89 | 1.8
90 |
91 |
92 |
93 | org.apache.maven.plugins
94 | maven-release-plugin
95 | 2.5.3
96 |
97 | true
98 | false
99 | release
100 | deploy
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | release
109 |
110 |
111 |
112 | org.apache.maven.plugins
113 | maven-source-plugin
114 | 3.1.0
115 |
116 |
117 | attach-sources
118 |
119 | jar-no-fork
120 |
121 |
122 |
123 |
124 |
125 | org.apache.maven.plugins
126 | maven-javadoc-plugin
127 | 3.1.1
128 |
129 |
130 | attach-javadocs
131 |
132 | jar
133 |
134 |
135 | -Xdoclint:none
136 |
137 |
138 |
139 |
140 |
141 | org.apache.maven.plugins
142 | maven-gpg-plugin
143 | 1.6
144 |
145 |
146 | sign-artifacts
147 | verify
148 |
149 | sign
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 | sonatype
160 |
161 |
162 | sonatype-nexus-snapshots
163 | https://oss.sonatype.org/content/repositories/snapshots
164 |
165 |
166 | sonatype-nexus-snapshots
167 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
168 |
169 |
170 |
171 |
172 | 1.6.8
173 |
174 |
175 |
176 |
177 |
178 | org.sonatype.plugins
179 | nexus-staging-maven-plugin
180 | ${nexus-staging-maven-plugin.version}
181 | true
182 |
183 | sonatype-nexus-snapshots
184 | https://oss.sonatype.org/
185 | true
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 | coverage
194 |
195 |
196 |
197 | org.jacoco
198 | jacoco-maven-plugin
199 | 0.8.4
200 |
201 |
202 |
203 | prepare-agent
204 |
205 |
206 |
207 | report
208 | test
209 |
210 | report
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 | https://github.com/cescoffier/vertx-completable-future
222 | https://github.com/cescoffier/vertx-completable-future.git
223 | scm:git:git@github.com:cescoffier/vertx-completable-future.git
224 | HEAD
225 |
226 |
227 | 2016
228 |
229 |
230 | github
231 | https://github.com/cescoffier/vertx-completable-future/issues
232 |
233 |
234 |
235 | escoffier.me
236 | http://escoffier.me
237 |
238 |
239 |
240 |
241 | cescoffier
242 | Clement Escoffier
243 | clement[AT]apache[DOT]org
244 | https://github.com/cescoffier
245 |
246 |
247 |
248 |
249 |
--------------------------------------------------------------------------------
/src/main/java/me/escoffier/vertx/completablefuture/VertxCompletableFuture.java:
--------------------------------------------------------------------------------
1 | package me.escoffier.vertx.completablefuture;
2 |
3 | import io.vertx.core.AsyncResult;
4 | import io.vertx.core.Context;
5 | import io.vertx.core.Future;
6 | import io.vertx.core.Vertx;
7 | import io.vertx.core.WorkerExecutor;
8 |
9 | import java.util.Objects;
10 | import java.util.concurrent.CompletableFuture;
11 | import java.util.concurrent.CompletionStage;
12 | import java.util.concurrent.Executor;
13 | import java.util.function.*;
14 |
15 | /**
16 | * An implementation of {@link CompletableFuture} for Vert.x. It differs in the way to handle async calls:
17 | *
18 | * * {@link VertxCompletableFuture} are attached to a Vert.x {@link Context}
19 | * * All operator methods returns {@link VertxCompletableFuture}
20 | * * method not passing an {@link Executor} are executed on the attached {@link Context}
21 | * * All non async method are executed on the current Thread (so not necessary on the attached {@link Context}
22 | *
23 | * The class also offer bridges methods with Vert.x {@link Future}, and regular {@link CompletableFuture}.
24 | *
25 | * @param the expected type of result
26 | */
27 | @SuppressWarnings("WeakerAccess")
28 | public class VertxCompletableFuture extends CompletableFuture implements CompletionStage {
29 | private final Executor executor;
30 |
31 | /**
32 | * The {@link Context} used by the future.
33 | */
34 | private final Context context;
35 |
36 | // ============= Constructors =============
37 |
38 | /**
39 | * Creates an instance of {@link VertxCompletableFuture}, using the current Vert.x context or create a new one.
40 | *
41 | * @param vertx the Vert.x instance
42 | */
43 | public VertxCompletableFuture(Vertx vertx) {
44 | this(Objects.requireNonNull(vertx).getOrCreateContext());
45 | }
46 |
47 | /**
48 | * Creates an instance of {@link VertxCompletableFuture}, using the given {@link Context}.
49 | *
50 | * @param context the context
51 | */
52 | public VertxCompletableFuture(Context context) {
53 | this.context = Objects.requireNonNull(context);
54 | this.executor = command -> context.runOnContext(v -> command.run());
55 | }
56 |
57 | /**
58 | * Creates a new {@link VertxCompletableFuture} from the given context and given {@link CompletableFuture}.
59 | * The created {@link VertxCompletableFuture} is completed successfully or not when the given completable future
60 | * completes successfully or not.
61 | *
62 | * @param context the context
63 | * @param future the completable future
64 | */
65 | private VertxCompletableFuture(Context context, CompletableFuture future) {
66 | this(context);
67 | Objects.requireNonNull(future).whenComplete((res, err) -> {
68 | if (err != null) {
69 | completeExceptionally(err);
70 | } else {
71 | complete(res);
72 | }
73 | });
74 | }
75 |
76 | /**
77 | * Creates a new {@link VertxCompletableFuture} using the current {@link Context}. This method
78 | * must be used from a Vert.x thread, or fails.
79 | */
80 | public VertxCompletableFuture() {
81 | this(Vertx.currentContext());
82 | }
83 |
84 | // ============= Factory methods (from) =============
85 |
86 | /**
87 | * Creates a new {@link VertxCompletableFuture} with the current {@link Context} and given
88 | * {@link CompletableFuture}.
89 | *
90 | * The created {@link VertxCompletableFuture} is completed successfully or not when the given completable future
91 | * completes successfully or not.
92 | *
93 | * @param future the future
94 | * @param the type of the result
95 | * @return the new {@link VertxCompletableFuture}
96 | */
97 | public static VertxCompletableFuture from(CompletableFuture future) {
98 | return from(Vertx.currentContext(), future);
99 | }
100 |
101 | /**
102 | * Creates a new {@link VertxCompletableFuture} with the current {@link Context} and given
103 | * {@link CompletionStage}.
104 | *
105 | * The created {@link VertxCompletableFuture} is completed successfully or not when the given completable future
106 | * completes successfully or not.
107 | *
108 | * @param stage the completion stage
109 | * @param the type of the result
110 | * @return the new {@link VertxCompletableFuture}
111 | */
112 | public static VertxCompletableFuture from(CompletionStage stage) {
113 | return from(Vertx.currentContext(), stage);
114 | }
115 |
116 | /**
117 | * Creates a new {@link VertxCompletableFuture} with the current {@link Context} and given
118 | * {@link Future}.
119 | *
120 | * The created {@link VertxCompletableFuture} is completed successfully or not when the given completable future
121 | * completes successfully or not.
122 | *
123 | * @param future the future
124 | * @param the type of the result
125 | * @return the new {@link VertxCompletableFuture}
126 | */
127 | public static VertxCompletableFuture from(Future future) {
128 | return from(Vertx.currentContext(), future);
129 | }
130 |
131 | /**
132 | * Creates a new {@link VertxCompletableFuture} from the given {@link Vertx} instance and given
133 | * {@link CompletableFuture}. The returned future uses the current Vert.x context, or creates a new one.
134 | *
135 | * The created {@link VertxCompletableFuture} is completed successfully or not when the given completable future
136 | * completes successfully or not.
137 | *
138 | * @param vertx the Vert.x instance
139 | * @param future the future
140 | * @param the type of the result
141 | * @return the new {@link VertxCompletableFuture}
142 | */
143 | public static VertxCompletableFuture from(Vertx vertx, CompletableFuture future) {
144 | return from(vertx.getOrCreateContext(), future);
145 | }
146 |
147 | /**
148 | * Creates a new {@link VertxCompletableFuture} from the given {@link Vertx} instance and given
149 | * {@link CompletionStage}. The returned future uses the current Vert.x context, or creates a new one.
150 | *
151 | * The created {@link VertxCompletableFuture} is completed successfully or not when the given completable future
152 | * completes successfully or not.
153 | *
154 | * @param vertx the Vert.x instance
155 | * @param stage the completion stage
156 | * @param the type of the result
157 | * @return the new {@link VertxCompletableFuture}
158 | */
159 | public static VertxCompletableFuture from(Vertx vertx, CompletionStage stage) {
160 | return from(vertx.getOrCreateContext(), stage);
161 | }
162 |
163 | /**
164 | * Creates a new {@link VertxCompletableFuture} from the given {@link Context} instance and given
165 | * {@link Future}. The returned future uses the current Vert.x context, or creates a new one.
166 | *
167 | * The created {@link VertxCompletableFuture} is completed successfully or not when the given future
168 | * completes successfully or not.
169 | *
170 | * @param vertx the Vert.x instance
171 | * @param future the Vert.x future
172 | * @param the type of the result
173 | * @return the new {@link VertxCompletableFuture}
174 | */
175 | public static VertxCompletableFuture from(Vertx vertx, Future future) {
176 | return from(vertx.getOrCreateContext(), future);
177 | }
178 |
179 | /**
180 | * Creates a {@link VertxCompletableFuture} from the given {@link Context} and {@link CompletionStage}.
181 | *
182 | * The created {@link VertxCompletableFuture} is completed successfully or not when the given future
183 | * completes successfully or not. The completion is called on the given {@link Context}, immediately if it is
184 | * already executing on the right context, asynchronously if not.
185 | *
186 | * @param context the context
187 | * @param stage the completion stage
188 | * @param the type of result
189 | * @return the creation {@link VertxCompletableFuture}
190 | */
191 | public static VertxCompletableFuture from(Context context, CompletionStage stage) {
192 | return from(context, stage.toCompletableFuture());
193 | }
194 |
195 | /**
196 | * Creates a {@link VertxCompletableFuture} from the given {@link Context} and {@link CompletableFuture}.
197 | *
198 | * The created {@link VertxCompletableFuture} is completed successfully or not when the given future
199 | * completes successfully or not. The completion is called on the given {@link Context}, immediately if it is
200 | * already executing on the right context, asynchronously if not.
201 | *
202 | * @param context the context
203 | * @param future the future
204 | * @param the type of result
205 | * @return the creation {@link VertxCompletableFuture}
206 | */
207 | public static VertxCompletableFuture from(Context context, CompletableFuture future) {
208 | VertxCompletableFuture res = new VertxCompletableFuture<>(Objects.requireNonNull(context));
209 | Objects.requireNonNull(future).whenComplete((result, error) -> {
210 | if (context == Vertx.currentContext()) {
211 | res.complete(result, error);
212 | } else {
213 | res.context.runOnContext(v -> res.complete(result, error));
214 | }
215 | });
216 | return res;
217 | }
218 |
219 | /**
220 | * Creates a new {@link VertxCompletableFuture} from the given {@link Context} instance and given
221 | * {@link Future}. The returned future uses the current Vert.x context, or creates a new one.
222 | *
223 | * The created {@link VertxCompletableFuture} is completed successfully or not when the given future
224 | * completes successfully or not. The created {@link VertxCompletableFuture} is completed successfully or not
225 | * when the given future completes successfully or not. The completion is called on the given {@link Context},
226 | * immediately if it is already executing on the right context, asynchronously if not.
227 | *
228 | * @param context the context
229 | * @param future the Vert.x future
230 | * @param the type of the result
231 | * @return the new {@link VertxCompletableFuture}
232 | */
233 | public static VertxCompletableFuture from(Context context, Future future) {
234 | VertxCompletableFuture res = new VertxCompletableFuture<>(Objects.requireNonNull(context));
235 | Objects.requireNonNull(future).setHandler(ar -> {
236 | if (context == Vertx.currentContext()) {
237 | res.completeFromAsyncResult(ar);
238 | } else {
239 | res.context.runOnContext(v -> res.completeFromAsyncResult(ar));
240 | }
241 | });
242 | return res;
243 | }
244 |
245 | /**
246 | * Returns a new CompletableFuture that is asynchronously completed by a task running in the current Vert.x
247 | * {@link Context} with the value obtained by calling the given Supplier.
248 | *
249 | * This method is different from {@link CompletableFuture#supplyAsync(Supplier)} as it does not use a fork join
250 | * executor, but use the Vert.x context.
251 | *
252 | * @param vertx the Vert.x instance
253 | * @param supplier a function returning the value to be used to complete the returned CompletableFuture
254 | * @param the function's return type
255 | * @return the new CompletableFuture
256 | */
257 | public static VertxCompletableFuture supplyAsync(Vertx vertx, Supplier supplier) {
258 | return supplyAsync(Objects.requireNonNull(vertx).getOrCreateContext(), supplier);
259 | }
260 |
261 | /**
262 | * Returns a new CompletableFuture that is asynchronously completed by a task running in the
263 | * current Vert.x {@link Context} after it runs the given action.
264 | *
265 | * This method is different from {@link CompletableFuture#supplyAsync(Supplier)} as it does not use a fork join
266 | * executor, but use the Vert.x context.
267 | *
268 | * @param vertx the Vert.x instance
269 | * @param runnable the action to run before completing the returned CompletableFuture
270 | * @return the new CompletableFuture
271 | */
272 | public static VertxCompletableFuture runAsync(Vertx vertx, Runnable runnable) {
273 | return runAsync(Objects.requireNonNull(vertx).getOrCreateContext(), runnable);
274 | }
275 |
276 | /**
277 | * Returns a new CompletableFuture that is asynchronously completed by a task running in the current Vert.x
278 | * {@link Context} with the value obtained by calling the given Supplier.
279 | *
280 | * This method is different from {@link CompletableFuture#supplyAsync(Supplier)} as it does not use a fork join
281 | * executor, but use the Vert.x context.
282 | *
283 | * @param context the context in which the supplier is executed.
284 | * @param supplier a function returning the value to be used to complete the returned CompletableFuture
285 | * @param the function's return type
286 | * @return the new CompletableFuture
287 | */
288 | public static VertxCompletableFuture supplyAsync(Context context, Supplier supplier) {
289 | Objects.requireNonNull(supplier);
290 | VertxCompletableFuture future = new VertxCompletableFuture<>(Objects.requireNonNull(context));
291 | context.runOnContext(v -> {
292 | try {
293 | future.complete(supplier.get());
294 | } catch (Throwable e) {
295 | future.completeExceptionally(e);
296 | }
297 | });
298 | return future;
299 | }
300 |
301 | /**
302 | * Returns a new CompletableFuture that is asynchronously completed by a task running in the
303 | * current Vert.x {@link Context} after it runs the given action.
304 | *
305 | * This method is different from {@link CompletableFuture#runAsync(Runnable)} as it does not use a fork join
306 | * executor, but use the Vert.x context.
307 | *
308 | * @param context the context
309 | * @param runnable the action to run before completing the returned CompletableFuture
310 | * @return the new CompletableFuture
311 | */
312 | public static VertxCompletableFuture runAsync(Context context, Runnable runnable) {
313 | Objects.requireNonNull(runnable);
314 | VertxCompletableFuture future = new VertxCompletableFuture<>(context);
315 | context.runOnContext(v -> {
316 | try {
317 | runnable.run();
318 | future.complete(null);
319 | } catch (Throwable e) {
320 | future.completeExceptionally(e);
321 | }
322 | });
323 | return future;
324 | }
325 |
326 | /**
327 | * Returns a new CompletableFuture that is asynchronously completed by a task running in the worker thread pool of
328 | * Vert.x
329 | *
330 | * This method is different from {@link CompletableFuture#supplyAsync(Supplier)} as it does not use a fork join
331 | * executor, but the worker thread pool.
332 | *
333 | * @param vertx the Vert.x instance
334 | * @param supplier a function returning the value to be used to complete the returned CompletableFuture
335 | * @param the function's return type
336 | * @return the new CompletableFuture
337 | */
338 | public static VertxCompletableFuture supplyBlockingAsync(Vertx vertx, Supplier supplier) {
339 | return supplyBlockingAsync(Objects.requireNonNull(vertx).getOrCreateContext(), supplier);
340 | }
341 |
342 | /**
343 | * Returns a new CompletableFuture that is asynchronously completed by a task running in the worker thread pool of
344 | * Vert.x
345 | *
346 | * This method is different from {@link CompletableFuture#supplyAsync(Supplier)} as it does not use a fork join
347 | * executor, but the worker thread pool.
348 | *
349 | * @param vertx the Vert.x instance
350 | * @param worker the WorkerExecution on which the supplier is to be executed
351 | * @param supplier a function returning the value to be used to complete the returned CompletableFuture
352 | * @param the function's return type
353 | * @return the new CompletableFuture
354 | */
355 | public static VertxCompletableFuture supplyBlockingAsyncOn(Vertx vertx, WorkerExecutor worker, Supplier supplier) {
356 | return supplyBlockingAsyncOn(Objects.requireNonNull(vertx).getOrCreateContext(), worker, supplier);
357 | }
358 |
359 | /**
360 | * Returns a new CompletableFuture that is asynchronously completed by a action running in the worker thread pool of
361 | * Vert.x
362 | *
363 | * This method is different from {@link CompletableFuture#runAsync(Runnable)} as it does not use a fork join
364 | * executor, but the worker thread pool.
365 | *
366 | * @param vertx the Vert.x instance
367 | * @param runnable the action, when its execution completes, it completes the returned CompletableFuture. If the
368 | * execution throws an exception, the returned CompletableFuture is completed exceptionally.
369 | * @return the new CompletableFuture
370 | */
371 | public static VertxCompletableFuture runBlockingAsync(Vertx vertx, Runnable runnable) {
372 | return runBlockingAsync(Objects.requireNonNull(vertx).getOrCreateContext(), runnable);
373 | }
374 |
375 | /**
376 | * Returns a new CompletableFuture that is asynchronously completed by a action running in the worker thread pool of
377 | * Vert.x
378 | *
379 | * This method is different from {@link CompletableFuture#runAsync(Runnable)} as it does not use a fork join
380 | * executor, but the worker thread pool.
381 | *
382 | * @param context the Vert.x context
383 | * @param runnable the action, when its execution completes, it completes the returned CompletableFuture. If the
384 | * execution throws an exception, the returned CompletableFuture is completed exceptionally.
385 | * @return the new CompletableFuture
386 | */
387 | public static VertxCompletableFuture runBlockingAsync(Context context, Runnable runnable) {
388 | Objects.requireNonNull(runnable);
389 | VertxCompletableFuture future = new VertxCompletableFuture<>(Objects.requireNonNull(context));
390 | context.executeBlocking(
391 | fut -> {
392 | try {
393 | runnable.run();
394 | fut.complete(null);
395 | } catch (Throwable e) {
396 | fut.fail(e);
397 | }
398 | },
399 | false,
400 | ar -> {
401 | if (ar.failed()) {
402 | future.completeExceptionally(ar.cause());
403 | } else {
404 | future.complete(ar.result());
405 | }
406 | }
407 | );
408 | return future;
409 | }
410 |
411 | /**
412 | * Returns a new CompletableFuture that is asynchronously completed by a action running in the provided
413 | * Vert.x worker thread pool.
414 | *
415 | * This method is different from {@link CompletableFuture#runAsync(Runnable)} as it does not use a fork join
416 | * executor, but the worker thread pool.
417 | *
418 | * @param vertx the Vert.x instance
419 | * @param worker the WorkerExecution on which the runnable is to be executed
420 | * @param runnable the action, when its execution completes, it completes the returned CompletableFuture. If the
421 | * execution throws an exception, the returned CompletableFuture is completed exceptionally.
422 | * @return the new CompletableFuture
423 | */
424 | public static VertxCompletableFuture runBlockingAsyncOn(Vertx vertx, WorkerExecutor worker, Runnable runnable) {
425 | return runBlockingAsyncOn(Objects.requireNonNull(vertx).getOrCreateContext(), worker, runnable);
426 | }
427 |
428 | /**
429 | * Returns a new CompletableFuture that is asynchronously completed by a action running in the provided
430 | * Vert.x worker thread pool.
431 | *
432 | * This method is different from {@link CompletableFuture#runAsync(Runnable)} as it does not use a fork join
433 | * executor, but the provided worker thread pool.
434 | *
435 | * @param context the Vert.x context
436 | * @param worker the WorkerExecution on which the runnable is to be executed
437 | * @param runnable the action, when its execution completes, it completes the returned CompletableFuture. If the
438 | * execution throws an exception, the returned CompletableFuture is completed exceptionally.
439 | * @return the new CompletableFuture
440 | */
441 | public static VertxCompletableFuture runBlockingAsyncOn(Context context, WorkerExecutor worker, Runnable runnable) {
442 | Objects.requireNonNull(runnable);
443 | VertxCompletableFuture future = new VertxCompletableFuture<>(Objects.requireNonNull(context));
444 | Objects.requireNonNull(worker).executeBlocking(
445 | fut -> {
446 | try {
447 | runnable.run();
448 | fut.complete(null);
449 | } catch (Throwable e) {
450 | fut.fail(e);
451 | }
452 | },
453 | false,
454 | ar -> {
455 | if (ar.failed()) {
456 | future.completeExceptionally(ar.cause());
457 | } else {
458 | future.complete(ar.result());
459 | }
460 | }
461 | );
462 | return future;
463 | }
464 |
465 | /**
466 | * Returns a new CompletableFuture that is asynchronously completed by a task running in the worker thread pool of
467 | * Vert.x
468 | *
469 | * This method is different from {@link CompletableFuture#supplyAsync(Supplier)} as it does not use a fork join
470 | * executor, but the worker thread pool.
471 | *
472 | * @param context the context in which the supplier is executed.
473 | * @param supplier a function returning the value to be used to complete the returned CompletableFuture
474 | * @param the function's return type
475 | * @return the new CompletableFuture
476 | */
477 | public static VertxCompletableFuture supplyBlockingAsync(Context context, Supplier supplier) {
478 | Objects.requireNonNull(supplier);
479 | VertxCompletableFuture future = new VertxCompletableFuture<>(context);
480 | context.executeBlocking(
481 | fut -> {
482 | try {
483 | fut.complete(supplier.get());
484 | } catch (Throwable e) {
485 | fut.fail(e);
486 | }
487 | },
488 | false,
489 | ar -> {
490 | if (ar.failed()) {
491 | future.completeExceptionally(ar.cause());
492 | } else {
493 | future.complete(ar.result());
494 | }
495 | }
496 | );
497 | return future;
498 | }
499 |
500 | /**
501 | * Returns a new CompletableFuture that is asynchronously completed by a task running in the provided
502 | * Vert.x worker thread pool.
503 | *
504 | * This method is different from {@link CompletableFuture#supplyAsync(Supplier)} as it does not use a fork join
505 | * executor, but the worker thread pool.
506 | *
507 | * @param context the context in which the supplier is executed.
508 | * @param worker the WorkerExecution on which the supplier is to be executed
509 | * @param supplier a function returning the value to be used to complete the returned CompletableFuture
510 | * @param the function's return type
511 | * @return the new CompletableFuture
512 | */
513 | public static VertxCompletableFuture supplyBlockingAsyncOn(Context context, WorkerExecutor worker, Supplier supplier) {
514 | Objects.requireNonNull(supplier);
515 | VertxCompletableFuture future = new VertxCompletableFuture<>(context);
516 | Objects.requireNonNull(worker).executeBlocking(
517 | fut -> {
518 | try {
519 | fut.complete(supplier.get());
520 | } catch (Throwable e) {
521 | fut.fail(e);
522 | }
523 | },
524 | false,
525 | ar -> {
526 | if (ar.failed()) {
527 | future.completeExceptionally(ar.cause());
528 | } else {
529 | future.complete(ar.result());
530 | }
531 | }
532 | );
533 | return future;
534 | }
535 |
536 | // ============= Wrapping methods =============
537 |
538 | /**
539 | * Creates a Vert.x {@link Future} from the given {@link CompletableFuture} (that can be a
540 | * {@link VertxCompletableFuture}).
541 | *
542 | * @param future the future
543 | * @param the type of the result
544 | * @return the Vert.x future completed or failed when the given {@link CompletableFuture} completes or fails.
545 | */
546 | public static Future toFuture(CompletableFuture future) {
547 | Future fut = Future.future();
548 | Objects.requireNonNull(future).whenComplete((res, err) -> {
549 | if (err != null) {
550 | fut.fail(err);
551 | } else {
552 | fut.complete(res);
553 | }
554 | });
555 | // this can't recurse because the Future API guarantees repeated completions should do nothing
556 | fut.setHandler(res -> {
557 | if (res.succeeded()) {
558 | future.complete(res.result());
559 | } else {
560 | future.completeExceptionally(res.cause());
561 | }
562 | });
563 | return fut;
564 | }
565 |
566 | // ============= Parallel composition methods =============
567 |
568 | /**
569 | * Returns a new CompletableFuture that is completed when all of the given CompletableFutures complete. If any of
570 | * the given CompletableFutures complete exceptionally, then the returned CompletableFuture also does so, with a
571 | * CompletionException holding this exception as its cause. Otherwise, the results, if any, of the given
572 | * CompletableFutures are not reflected in the returned CompletableFuture, but may be obtained by inspecting them
573 | * individually. If no CompletableFutures are provided, returns a CompletableFuture completed with the value
574 | * {@code null}.
575 | *
576 | *
Among the applications of this method is to await completion
577 | * of a set of independent CompletableFutures before continuing a
578 | * program, as in: {@code CompletableFuture.allOf(c1, c2, c3).join();}.
579 | *
580 | * Unlike the original {@link CompletableFuture#allOf(CompletableFuture[])} this method invokes the dependent
581 | * stages into the Vert.x context.
582 | *
583 | * @param vertx the Vert.x instance to retrieve the context
584 | * @param futures the CompletableFutures
585 | * @return a new CompletableFuture that is completed when all of the given CompletableFutures complete
586 | * @throws NullPointerException if the array or any of its elements are {@code null}
587 | */
588 | public static VertxCompletableFuture allOf(Vertx vertx, CompletableFuture>... futures) {
589 | CompletableFuture all = CompletableFuture.allOf(futures);
590 | return VertxCompletableFuture.from(vertx, all);
591 | }
592 |
593 | /**
594 | * Returns a new CompletableFuture that is completed when all of the given CompletableFutures complete. If any of
595 | * the given CompletableFutures complete exceptionally, then the returned CompletableFuture also does so, with a
596 | * CompletionException holding this exception as its cause. Otherwise, the results, if any, of the given
597 | * CompletableFutures are not reflected in the returned CompletableFuture, but may be obtained by inspecting them
598 | * individually. If no CompletableFutures are provided, returns a CompletableFuture completed with the value
599 | * {@code null}.
600 | *
601 | *
Among the applications of this method is to await completion
602 | * of a set of independent CompletableFutures before continuing a
603 | * program, as in: {@code CompletableFuture.allOf(c1, c2, c3).join();}.
604 | *
605 | * Unlike the original {@link CompletableFuture#allOf(CompletableFuture[])} this method invokes the dependent
606 | * stages into the Vert.x context.
607 | *
608 | * @param context the context
609 | * @param futures the CompletableFutures
610 | * @return a new CompletableFuture that is completed when all of the given CompletableFutures complete
611 | * @throws NullPointerException if the array or any of its elements are {@code null}
612 | */
613 | public static VertxCompletableFuture allOf(Context context, CompletableFuture>... futures) {
614 | CompletableFuture all = CompletableFuture.allOf(futures);
615 | return VertxCompletableFuture.from(context, all);
616 | }
617 |
618 | /**
619 | * Returns a new CompletableFuture that is completed when any of the given CompletableFutures complete, with the
620 | * same result. Otherwise, if it completed exceptionally, the returned CompletableFuture also does so, with a
621 | * CompletionException holding this exception as its cause. If no CompletableFutures are provided, returns an
622 | * incomplete CompletableFuture.
623 | *
624 | * Unlike the original {@link CompletableFuture#allOf(CompletableFuture[])} this method invokes the dependent
625 | * stages into the Vert.x context.
626 | *
627 | * @param vertx the Vert.x instance to retrieve the context
628 | * @param futures the CompletableFutures
629 | * @return a new CompletableFuture that is completed with the result or exception of any of the given
630 | * CompletableFutures when one completes
631 | * @throws NullPointerException if the array or any of its elements are {@code null}
632 | */
633 | public static VertxCompletableFuture