31 | * This represents a service which may or may not be available. 32 | *
33 | * We were using Expected a lot where we really wanted something like a Breaker. 34 | *35 | * This could be extended to blow the circuit with different conditions by providing 36 | * your own Breaker. 37 | *
38 | *39 | * Also we want to use interfaces for all core concepts. 40 | *
41 | * In addition we wanted callback for ifBroken and ifOperational. 42 | *43 | * If a service is active and healthy, {@code isOperational()} will return {@code true}. 44 | * If a service is not healthy or not working, {code isBroken()} will return {@code true}. 45 | *
46 | * This is heavily modeled after {@code Expected} optional. 47 | * 48 | * @author Rick Hightower 49 | * @author Geoff Chandler 50 | */ 51 | public interface Breaker
162 | * This tracks errors thrown by the consumer.
163 | *
164 | * @param consumer executed if a value is present
165 | * @return this, fluent API
166 | * @throws NullPointerException if value is present and {@code consumer} is
167 | * null
168 | */
169 | Breaker
15 | * This is a helper methods for producers (services that produce results) to send a failed result.
16 | *
17 | * @param error error
18 | */
19 | void reject(final Throwable error);
20 |
21 |
22 | /**
23 | * (Service view)
24 | * This allows services to send back a failed result easily to the client/handler.
25 | *
26 | * This is a helper methods for producers (services that produce results) to send a failed result.
27 | *
28 | * @param errorMessage error message
29 | */
30 | void reject(final String errorMessage);
31 |
32 |
33 | /**
34 | * (Service view)
35 | * This allows services to send back a failed result easily to the client/handler.
36 | *
37 | * This is a helper methods for producers (services that produce results) to send a failed result.
38 | *
39 | * @param errorMessage error message
40 | * @param error exception
41 | */
42 | void reject(final String errorMessage, final Throwable error);
43 |
44 |
45 | /**
46 | * Calls replayDone, for VOID callback only. ES6 promise style.
47 | */
48 | void resolve();
49 |
50 | /**
51 | * Resolve resolves a promise.
52 | *
53 | * @param result makes it more compatible with ES6 style promises
54 | */
55 | void resolve(final T result);
56 |
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/io/advantageous/reakt/CallbackHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Copyright (c) 2016. Rick Hightower, Geoff Chandler
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | *
17 | */
18 |
19 | package io.advantageous.reakt;
20 |
21 | import io.advantageous.reakt.exception.RejectedPromiseException;
22 | import io.advantageous.reakt.impl.ResultImpl;
23 |
24 | import java.util.function.Consumer;
25 |
26 | import static io.advantageous.reakt.Result.doneResult;
27 |
28 | /**
29 | * A generic event handler which can be thought of as a callback handler.
30 | *
31 | * This is like an async future or promise.
32 | *
33 | * This was modeled after QBit's callback, and JavaScripts callbacks.
34 | * The {@link Result} result represents the result or error from an async operation.
35 | *
36 | * A {@code CallbackHandler} is a {@code Consumer} and can be used anywhere a consumer is used.
37 | * This is for easy integration with non-Reakt libs and code bases.
38 | *
39 | *
40 | * @param
50 | * This is registered from the callers (or event receivers perspective).
51 | * A client of a service would override {@code onResult}.
52 | *
53 | * @param result to handle
54 | */
55 | void onResult(Result
62 | * This is a helper methods for producers (services that produce results) to send a failed result.
63 | *
64 | * @param error error
65 | */
66 | default void reject(final Throwable error) {
67 | onResult(new ResultImpl<>(error));
68 | }
69 |
70 |
71 | /**
72 | * (Service view)
73 | * This allows services to send back a failed result easily to the client/handler.
74 | *
75 | * This is a helper methods for producers (services that produce results) to send a failed result.
76 | *
77 | * @param errorMessage error message
78 | */
79 | default void reject(final String errorMessage) {
80 | reject(new RejectedPromiseException(errorMessage));
81 | }
82 |
83 |
84 | /**
85 | * (Service view)
86 | * This allows services to send back a failed result easily to the client/handler.
87 | *
88 | * This is a helper methods for producers (services that produce results) to send a failed result.
89 | *
90 | * @param errorMessage error message
91 | * @param error exception
92 | */
93 | default void reject(final String errorMessage, final Throwable error) {
94 | reject(new RejectedPromiseException(errorMessage, error));
95 | }
96 |
97 | /**
98 | * Calls replayDone, for VOID callback only. ES6 promise style.
99 | */
100 | @SuppressWarnings("unused")
101 | default void resolve() {
102 | onResult((Result
34 | * Also we want to use interfaces for all core concepts.
35 | *
36 | * In addition we wanted callback for ifPresent and ifEmpty.
37 | *
38 | * Contains an value object which may not be set. This is like {@code Optional} but could be the value from an async operation
39 | * which sent a null.
40 | *
41 | * If a value is present, {@code isPresent()} will return {@code true} and
42 | * {@code get()} will return the value.
43 | *
44 | * This is heavily modeled after {@link java.util.Optional} optional.
45 | *
46 | * @author Rick Hightower
47 | * @author Geoff Chandler
48 | */
49 | public interface Expected
181 | * If you just want a null check, use {@code isAbsent}.
182 | *
183 | * @return {@code true} if there is not a value present or present and empty,
184 | * otherwise {@code false}
185 | */
186 | boolean isEmpty();
187 |
188 |
189 | /**
190 | * If a value is not present or present and empty (collection, string, charSequence size/length 0),
191 | * invoke the runnable. See for more details {@link Expected#isAbsent()}.
192 | *
193 | * If you just want a null check, use {@code ifAbsent}.
194 | *
195 | * @param runnable executed if a value is not present.
196 | * @return this, fluent API
197 | */
198 | Expected
73 | * The Observable will not call this method if it calls {@link #onError}.
74 | */
75 | void onCompleted();
76 |
77 | /**
78 | * Notifies the Observer that the Observable has hit an error condition.
79 | *
80 | * If the Observable calls this method, it will not thereafter call {@link #onNext} or
81 | * {@link #onCompleted}.
82 | *
83 | * @param e the exception encountered by the Observable
84 | */
85 | void onError(final Throwable e);
86 |
87 | /**
88 | * Provides the Observer with a new item to observe.
89 | *
90 | * The Observable may call this method 0 or more times. In the case of a scalar call {@link CallbackHandler#onResult(Result)}
91 | * it will get called once. In the case of {@link Stream#onNext(StreamResult)} the stream will get called many times.
92 | *
93 | * The {@code Observable} will not call this method again after it calls either {@link #onCompleted} or
94 | * {@link #onError}.
95 | *
96 | * @param t the item emitted by the Observable
97 | */
98 | void onNext(final T t);
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/io/advantageous/reakt/PromiseSupplier.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Copyright (c) 2016. Rick Hightower, Geoff Chandler
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | *
17 | */
18 |
19 | package io.advantageous.reakt;
20 |
21 | import io.advantageous.reakt.promise.PromiseHandler;
22 |
23 | import java.util.function.Supplier;
24 |
25 | /**
26 | * Represents an async supplier of results.
27 | *
28 | * Use this instead of the AsyncSupplier.
29 | *
30 | * @param
28 | * This was modeled after Vert.x AsyncResult and after the types of
29 | * results one would deal with in JavaScript.
30 | *
31 | * @param
30 | * This was modeled after Vert.x AsyncResult and after the types of results one would deal with in JavaScript.
31 | *
32 | * @param
12 | * A promise is a sort of deferred value.
13 | *
24 | * There is only one {@code then} Handler.
25 | *
38 | * There is only one thenExpect handler per promise.
39 | *
40 | * Unlike ES6, {@code thenExpect(..)} cannot be chained per se as it does not create a new promise,
41 | * but {@code whenComplete(..)}, and {@code }thenMap(...)} can be chained.
42 | *
43 | * This does not create a new promise.
44 | *
45 | * @param consumer executed if result has no error.
46 | * @return this, fluent API
47 | * @throws NullPointerException if result is present and {@code consumer} is
48 | * null
49 | */
50 | Promise
65 | * This allows use to set up the catchError and then before the method is async invoked.
66 | *
67 | * Example Remote Proxy Gen to support returning Reakt invokeable promise
68 | *
83 | * This is convenient if you are running your handler with an async lib that is not reporting or catching
84 | * exceptions as your code is running on their threads.
85 | *
86 | * If a result is sent, and there was no error, then handle the result as a value which could be null.
87 | *
88 | * There is only one thenSafeExpect or thenExpect handler per promise.
89 | * Once then is called all other then* handlers are safe.
90 | *
91 | * Unlike ES6, {@code thenExpect(..)} cannot be chained per se as it does not create a new promise,
92 | * but {@code whenComplete(..)}, and {@code }thenMap(...)} can be chained.
93 | *
94 | * This does not create a new promise.
95 | *
96 | * @param consumer executed if result has no error.
97 | * @return this, fluent API
98 | * @throws NullPointerException if result is present and {@code consumer} is
99 | * null
100 | */
101 | Promise
108 | * This is convenient if you are running your handler with an async lib that is not reporting or catching
109 | * exceptions as your code is running on their threads.
110 | *
111 | * If a result is sent, and there was no error, then handle the result as a value which could be null.
112 | *
113 | * There is only one thenSafe or then handler per promise.
114 | * Once then is called all other then* handlers are safe.
115 | *
116 | * Unlike ES6, {@code thenExpect(..)} cannot be chained per se as it does not create a new promise,
117 | * but {@code whenComplete(..)}, and {@code }thenMap(...)} can be chained.
118 | *
119 | * This does not create a new promise.
120 | *
121 | * @param consumer executed if result has no error.
122 | * @return this, fluent API
123 | * @throws NullPointerException if result is present and {@code consumer} is
124 | * null
125 | */
126 | Promise
34 | * A promise handler is both a {@code CallbackHandler} ({@link CallbackHandler}),
35 | * and a {@code Result} {@link io.advantageous.reakt.Result}.
36 | *
38 | * A promise is a sort of deferred value.
39 | *
40 | * @param
58 | * There is only one {@code then} Handler.
59 | *
73 | * If you want N handlers for when the promise gets called back use whenComplete instead of
74 | * {@code then} or {@code thenExpect}.
75 | *
76 | * There can be many {@code whenComplete} handlers.
77 | *
78 | * This does not create a new promise.
79 | *
80 | * @param doneListener doneListener
81 | * @return this, fluent API
82 | */
83 | PromiseHandler
88 | * There is only one thenExpect handler per promise.
89 | *
90 | * Unlike ES6, {@code thenExpect(..)} cannot be chained per se as it does not create a new promise,
91 | * but {@code whenComplete(..)}, and {@code }thenMap(...)} can be chained.
92 | *
93 | * This does not create a new promise.
94 | *
95 | * @param consumer executed if result has no error.
96 | * @return this, fluent API
97 | * @throws NullPointerException if result is present and {@code consumer} is
98 | * null
99 | */
100 | PromiseHandler
124 | * Hint: if you have to ask, the answer is no.
125 | *
126 | * @return true if it is invokable
127 | */
128 | default boolean isInvokable() {
129 | return this instanceof Invokable;
130 | }
131 |
132 | /**
133 | * Allows promises returned from, for example, proxy stubs for services methods to invoke the operation.
134 | *
135 | * This allows use to set up the catchError and then before the method is async invoked.
136 | *
137 | * Example Remote Proxy Gen to support returning Reakt invokeable promise
138 | *
223 | * This is convenient if you are running your handler with an async lib that is not reporting or catching
224 | * exceptions as your code is running on their threads.
225 | *
226 | * If a result is sent, and there was no error, then handle the result as a value which could be null.
227 | *
228 | * There is only one thenSafeExpect or thenExpect handler per promise.
229 | * Once then is called all other then* handlers are safe.
230 | *
231 | * Unlike ES6, {@code thenExpect(..)} cannot be chained per se as it does not create a new promise,
232 | * but {@code whenComplete(..)}, and {@code }thenMap(...)} can be chained.
233 | *
234 | * This does not create a new promise.
235 | *
236 | * @param consumer executed if result has no error.
237 | * @return this, fluent API
238 | * @throws NullPointerException if result is present and {@code consumer} is
239 | * null
240 | */
241 | default PromiseHandler
250 | * This is convenient if you are running your handler with an async lib that is not reporting or catching
251 | * exceptions as your code is running on their threads.
252 | *
253 | * If a result is sent, and there was no error, then handle the result as a value which could be null.
254 | *
255 | * There is only one thenSafe or then handler per promise.
256 | * Once then is called all other then* handlers are safe.
257 | *
258 | * Unlike ES6, {@code thenExpect(..)} cannot be chained per se as it does not create a new promise,
259 | * but {@code whenComplete(..)}, and {@code }thenMap(...)} can be chained.
260 | *
261 | * This does not create a new promise.
262 | *
263 | * @param consumer executed if result has no error.
264 | * @return this, fluent API
265 | * @throws NullPointerException if result is present and {@code consumer} is
266 | * null
267 | */
268 | default PromiseHandler
223 | *
227 | *
228 | * @param other an object to be tested for equality
229 | * @return {code true} if the other object is "equal to" this object
230 | * otherwise {@code false}
231 | */
232 | @Override
233 | public boolean equals(final Object other) {
234 | if (this == other) {
235 | return true;
236 | }
237 | if (!(other instanceof Expected)) {
238 | return false;
239 | }
240 | final ExpectedImpl> otherValue = (ExpectedImpl>) other;
241 | return Objects.equals(this.value, otherValue.value);
242 | }
243 |
244 | /**
245 | * Indicates whether some other object is "equal to" the value.
246 | * The other value is equal if Object.equals(value, other) returns true.
247 | */
248 | @Override
249 | public boolean equalsValue(final Object other) {
250 | return Objects.equals(this.value, other);
251 | }
252 |
253 | /**
254 | * Returns the hash code value of the present value, if any, or 0 (zero) if
255 | * no value is present.
256 | *
257 | * @return hash code value of the present value or 0 if no value is present
258 | */
259 | @Override
260 | public int hashCode() {
261 | return Objects.hashCode(this.value);
262 | }
263 |
264 | /**
265 | * Returns a non-empty string representation of this Expected suitable for
266 | * debugging. The exact presentation format is unspecified and may vary
267 | * between implementations and versions.
268 | *
269 | * @return the string representation of this instance
270 | */
271 | @Override
272 | public String toString() {
273 | return "Expected{" + "value=" + this.value + '}';
274 | }
275 | }
276 |
--------------------------------------------------------------------------------
/src/main/java/io/advantageous/reakt/impl/ResultImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Copyright (c) 2016. Rick Hightower, Geoff Chandler
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | *
17 | */
18 |
19 | package io.advantageous.reakt.impl;
20 |
21 | import io.advantageous.reakt.Expected;
22 | import io.advantageous.reakt.Result;
23 | import io.advantageous.reakt.exception.ResultFailedException;
24 |
25 | import java.util.function.Consumer;
26 |
27 | /**
28 | * The result of an async operation.
29 | *
69 | *
76 | *
77 | */
78 | void invoke();
79 |
80 | /**
81 | * If the thenSafeExpect handler throws an exception, this will report it as if it it was caught by catchError.
82 | *
70 | * employeeService.lookupEmployee("123")
71 | * .then((employee)-> {...})
72 | * .catchError(...)
73 | * .invoke();
74 | *
75 | *
139 | *
146 | *
147 | */
148 | default void invoke() {
149 | throw new UnsupportedOperationException("This is not an invokable promise.");
150 | }
151 |
152 |
153 | /**
154 | * Allows you to pass an existing promise as a handler.
155 | *
156 | * @param promise promise
157 | * @return this, fluent
158 | */
159 | default PromiseHandler
140 | * employeeService.lookupEmployee("123")
141 | * .then((employee)-> {...})
142 | * .catchError(...)
143 | * .invoke();
144 | *
145 | * >>> completeListeners = Expected.empty();
43 | private boolean safe;
44 |
45 | public static