I'd like to have a method to send a request and then receive a response over UDP.
Here is what I've developed for the moment :
public <T extends ObjectSerializable, U extends ObjectDeserializable>
CompletableFuture<Object> execute(T request, U response)
{
var resultFuture = sender.asyncSend(request); /*CompletableFuture<Void>*/
resultFuture.thenAccept((nullObj) -> {
try {
receiver.asyncReceive(response).get(); /*CompletableFuture<Void>*/
}catch (Exception e) {
throw new FutureExecutionException(e.getMessage());
}
}).thenRun(() -> {
System.out.println("Send->Receive finished");
});
return resultFuture;
}
The question is : do I have to wait for the future inside .thenAccept ? Is it guaranteed that .thenRun will be executed after receiver.asyncReceive would finish?
Am I doing the right way combining CompletableFutures like this?
Here is a solution that looks fine
public <T extends ObjectSerializable, U extends ObjectDeserializable>
CompletableFuture<Void> execute(T request, U response)
{
return sender.asyncSend(request)
.thenCompose( result -> receiver.asyncReceive(response))
.thenRun( () -> System.out.println("Send-Receive finished"));
}
This would be a lot easier if your execute would take a Class<U> as argument. Then you could pass that class to receiver.asyncReceive. Internally, you could (assuming such a class has a default constructor) create an instance and populate it with all the fields. This is rather easy via :
clazz.getConstructor().newInstance()
Then your code would return a CompletableFuture<Response>, so your method would become something like:
public <T extends ObjectSerializable, U extends ObjectDeserializable>
CompletableFuture<U> execute(T request, Class<U> response){
return sender.asyncSend(request)
.thenCompose(nothing -> receiver.asyncReceive(response));
}
I am also not sure your asyncSend is supposed to return a CompletableFuture<Void> either, may be this one can take a Class<U> as a parameter too and return the proper type as CompletableFuture<U>, but then you do not need asyncReceive, I guess...
Related
I was going through the resilience4j code to find out how they implement the decorators, I can see Supplier/Consumer functional interfaces. i am still trying to understand on how to utilize these interfaces while coding. My question is based on this method,
static <T> Supplier<Future<T>> decorateFuture(Bulkhead bulkhead, Supplier<Future<T>> supplier) {
return () -> {
if (!bulkhead.tryAcquirePermission()) {
final CompletableFuture<T> promise = new CompletableFuture<>();
promise.completeExceptionally(BulkheadFullException.createBulkheadFullException(bulkhead));
return promise;
}
try {
return new BulkheadFuture<>(bulkhead, supplier.get());
} catch (Throwable e) {
bulkhead.onComplete();
throw e;
}
};
Have couple of questions,
Is it returning a Supplier<Future> because of its defined as a lambda?
How do these decorators are constructed, please can someone provide a simple example,
Supplier<String> decoratedSupplier = Bulkhead
.decorateSupplier(bulkhead, () -> "This can be any method which returns: 'Hello");
I'm trying to implement a simple promise system in java. I'm doing it for special purpose so please don't recommend any libraries.
I have a problem when I try to implement a thenApply() method which takes a Function as parameter, similar to what CompletableFuture has and therefore returns a promise with another type.
The promise interface:
public interface Promise<T> {
Promise<T> then(Consumer<T> handler);
<U> Promise<U> thenApply(Function<T, U> handler);
}
My implementation so far:
public class PromiseImpl<T> implements Promise<T> {
private List<Consumer<T>> resultHandlers = new ArrayList<>();
public PromiseImpl(CompletableFuture<T> future) {
future.thenAccept(this::doWork);
}
#Override
public Promise<T> then(Consumer<T> handler) {
resultHandlers.add(handler);
return this;
}
#Override
public <U> Promise<U> thenApply(Function<T, U> handler) {
// How to implement here??? I don't have the result yet
handler.apply(?);
}
private void onResult(T result) {
for (Consumer<T> handler : resultHandlers) {
handler.accept(result);
}
}
private Object doWork(T result) {
onResult(result);
return null;
}
}
The problem is that I don't know the result of my initial future in the thenApply() method, so I cannot call my handler. Also, I don't want to call future.get() because this method is blocking.
How could I make this work?
The real problem is in the design of your Promise type. It is holding a set of callbacks, all of which are to be invoked on completion. This is a fundamental problem (limiting generic functionality around the return type of thenApply's function). This can be resolved by changing your Promise implementation to return a new promise whenever a handler is registered, instead of returning this, such that each promise object will have its own handler to invoke.
In addition to solving this, it's a better design for functional-style programming, as you can make your Promise objects immutable.
I would change the interface to be:
interface Promise<T> {
<U> Promise<U> thenApply(Function<T, U> handler);
Promise<Void> thenAccept(Consumer<T> consumer);
}
The "chaining" of callbacks can then be done around the future objects to which chained Promise instances have references. So the implementation can look like:
class PromiseImpl<T> implements Promise<T> {
private CompletableFuture<T> future;
public PromiseImpl(CompletableFuture<T> future) {
this.future = future;
}
#Override
public <U> Promise<U> thenApply(Function<T, U> function) {
return new PromiseImpl<>(this.future.thenApply(function));
}
#Override
public Promise<Void> thenAccept(Consumer<T> consumer) {
return new PromiseImpl<>(this.future.thenAccept(consumer));
}
private void onResult(T result) {
this.future.complete(result);
}
private Object doWork(T result) {
onResult(result);
return null;
}
}
And using that can be as simple as:
Promise<String> stringPromise = new PromiseImpl<>(new CompletableFuture<String>());
Promise<Long> longPromise = stringPromise.thenApply(str -> Long.valueOf(str.length()));
Promise<Void> voidPromise = stringPromise.thenAccept(str -> System.out.println(str));
EDIT:
Regarding Michael's comment about retrieving the value: that was not added as it wasn't in the original Promise API. But it's easy enough to add:
T get(); //To the interface
And implemented with:
public T get() {
//try-catch
return this.future.get();
}
Note: this is starting to look more and more like a duplication of CompletableFuture, which raises the question of why do this at all. But assuming there will be additional Promise-like methods in this interface, the method would be wrapping the future API.
If you need to use the same Promise object with a list of call backs, then you have no choice but to parameterize the Promise interface with both Function concrete type parameters:
public interface Promise<T, U>
And U wouldn't be able to be a method generic parameter on then or thenApply.
If you want to keep the rest of your class the same and just implement the thenApply method, you have to make a new CompletableFuture since that's the only way you currently have to construct a new Promise:
#Override
public <U> Promise<U> thenApply(Function<T, U> handler) {
CompletableFuture<U> downstream = new CompletableFuture<>();
this.then(t -> downstream.complete(handler.apply(t)));
return new PromiseImpl<>(downstream);
}
If you can add a private no-argument constructor for PromiseImpl, you can avoid making a new CompletableFuture:
#Override
public <U> Promise<U> thenApply(Function<T, U> handler) {
PromiseImpl result = new PromiseImpl();
this.then(t -> result.doWork(handler.apply(t)));
return result;
}
But really what you should do if you want to implement your own API on top of CompletableFuture is use the decorator pattern and wrap a CompletableFuture instance as a private variable in PromiseImpl.
You can return some anonymous class that extends your PromiseImpl and overrides onResult so handlers accept the result of applying mapper function. Do not forget to call the parent onResult so parent handlers will be called.
When executing async CompletableFuture, the parent threadcontext and moreover the org.slf4j.MDC context is lost.
This is bad as I'm using some kind of "fish tagging" to track logs from one request among multiple logfiles.
MDC.put("fishid", randomId())
Question: how can I retain that id during the tasks of CompletableFutures in general?
List<CompletableFuture<UpdateHotelAllotmentsRsp>> futures =
tasks.stream()
.map(task -> CompletableFuture.supplyAsync(
() -> businesslogic(task))
.collect(Collectors.toList());
List results = futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
public void businesslogic(Task task) {
LOGGER.info("mdc fishtag context is lost here");
}
The most readable way I solved this problem was as below -
---------------Thread utils class--------------------
public static Runnable withMdc(Runnable runnable) {
Map<String, String> mdc = MDC.getCopyOfContextMap();
return () -> {
MDC.setContextMap(mdc);
runnable.run();
};
}
public static <U> Supplier<U> withMdc(Supplier<U> supplier) {
Map<String, String> mdc = MDC.getCopyOfContextMap();
return (Supplier) () -> {
MDC.setContextMap(mdc);
return supplier.get();
};
}
---------------Usage--------------
CompletableFuture.supplyAsync(withMdc(() -> someSupplier()))
.thenRunAsync(withMdc(() -> someRunnable())
....
WithMdc in ThreadUtils would have to be overloaded to include other functional interfaces which are accepted by CompletableFuture
Please note that the withMdc() method is statically imported to improve readability.
At the end I created a Supplier wrapper retaining the MDC. If anyone has a better idea feel free to comment.
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor) {
return CompletableFuture.supplyAsync(new SupplierMDC(supplier), executor);
}
private static class SupplierMDC<T> implements Supplier<T> {
private final Supplier<T> delegate;
private final Map<String, String> mdc;
public SupplierMDC(Supplier<T> delegate) {
this.delegate = delegate;
this.mdc = MDC.getCopyOfContextMap();
}
#Override
public T get() {
MDC.setContextMap(mdc);
return delegate.get();
}
}
My solution theme would be to (It would work with JDK 9+ as a couple of overridable methods are exposed since that version)
Make the complete ecosystem aware of MDC
And for that, we need to address the following scenarios:
When all do we get new instances of CompletableFuture from within this class? → We need to return a MDC aware version of the same rather.
When all do we get new instances of CompletableFuture from outside this class? → We need to return a MDC aware version of the same rather.
Which executor is used when in CompletableFuture class? → In all circumstances, we need to make sure that all executors are MDC aware
For that, let's create a MDC aware version class of CompletableFuture by extending it. My version of that would look like below
import org.slf4j.MDC;
import java.util.Map;
import java.util.concurrent.*;
import java.util.function.Function;
import java.util.function.Supplier;
public class MDCAwareCompletableFuture<T> extends CompletableFuture<T> {
public static final ExecutorService MDC_AWARE_ASYNC_POOL = new MDCAwareForkJoinPool();
#Override
public CompletableFuture newIncompleteFuture() {
return new MDCAwareCompletableFuture();
}
#Override
public Executor defaultExecutor() {
return MDC_AWARE_ASYNC_POOL;
}
public static <T> CompletionStage<T> getMDCAwareCompletionStage(CompletableFuture<T> future) {
return new MDCAwareCompletableFuture<>()
.completeAsync(() -> null)
.thenCombineAsync(future, (aVoid, value) -> value);
}
public static <T> CompletionStage<T> getMDCHandledCompletionStage(CompletableFuture<T> future,
Function<Throwable, T> throwableFunction) {
Map<String, String> contextMap = MDC.getCopyOfContextMap();
return getMDCAwareCompletionStage(future)
.handle((value, throwable) -> {
setMDCContext(contextMap);
if (throwable != null) {
return throwableFunction.apply(throwable);
}
return value;
});
}
}
The MDCAwareForkJoinPool class would look like (have skipped the methods with ForkJoinTask parameters for simplicity)
public class MDCAwareForkJoinPool extends ForkJoinPool {
//Override constructors which you need
#Override
public <T> ForkJoinTask<T> submit(Callable<T> task) {
return super.submit(MDCUtility.wrapWithMdcContext(task));
}
#Override
public <T> ForkJoinTask<T> submit(Runnable task, T result) {
return super.submit(wrapWithMdcContext(task), result);
}
#Override
public ForkJoinTask<?> submit(Runnable task) {
return super.submit(wrapWithMdcContext(task));
}
#Override
public void execute(Runnable task) {
super.execute(wrapWithMdcContext(task));
}
}
The utility methods to wrap would be such as
public static <T> Callable<T> wrapWithMdcContext(Callable<T> task) {
//save the current MDC context
Map<String, String> contextMap = MDC.getCopyOfContextMap();
return () -> {
setMDCContext(contextMap);
try {
return task.call();
} finally {
// once the task is complete, clear MDC
MDC.clear();
}
};
}
public static Runnable wrapWithMdcContext(Runnable task) {
//save the current MDC context
Map<String, String> contextMap = MDC.getCopyOfContextMap();
return () -> {
setMDCContext(contextMap);
try {
return task.run();
} finally {
// once the task is complete, clear MDC
MDC.clear();
}
};
}
public static void setMDCContext(Map<String, String> contextMap) {
MDC.clear();
if (contextMap != null) {
MDC.setContextMap(contextMap);
}
}
Below are some guidelines for usage:
Use the class MDCAwareCompletableFuture rather than the class CompletableFuture.
A couple of methods in the class CompletableFuture instantiates the self version such as new CompletableFuture.... For such methods (most of the public static methods), use an alternative method to get an instance of MDCAwareCompletableFuture. An example of using an alternative could be rather than using CompletableFuture.supplyAsync(...), you can choose new MDCAwareCompletableFuture<>().completeAsync(...)
Convert the instance of CompletableFuture to MDCAwareCompletableFuture by using the method getMDCAwareCompletionStage when you get stuck with one because of say some external library which returns you an instance of CompletableFuture. Obviously, you can't retain the context within that library but this method would still retain the context after your code hits the application code.
While supplying an executor as a parameter, make sure that it is MDC Aware such as MDCAwareForkJoinPool. You could create MDCAwareThreadPoolExecutor by overriding execute method as well to serve your use case. You get the idea!
With that, your code would look like
List<CompletableFuture<UpdateHotelAllotmentsRsp>> futures =
tasks.stream()
new MDCAwareCompletableFuture<UpdateHotelAllotmentsRsp>().completeAsync(
() -> businesslogic(task))
.collect(Collectors.toList());
List results = futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList());
public UpdateHotelAllotmentsRsp businesslogic(Task task) {
LOGGER.info("mdc fishtag context is not lost here");
}
You can find a detailed explanation of all of the above here in a post about the same.
YES, Twitter Future did this correctly. They have a class Local.scala that Future.scala knows about.
The fix is for java authors to fix this issue so your Local state travels through ALL libaries that use CompletableFutures. Basically, Local.scala is used by Future and internally uses a ThreadLocal up until .thenApply or .thenAccept and it will capture state and transfer it when needed to the next one on and on. This works through all third party libraries with ZERO 3rd party library changes.
Here is more but poke Java Authors to fix their stuff...
http://mail.openjdk.java.net/pipermail/core-libs-dev/2017-May/047867.html
until then, MDC will NEVER work through 3rd party libraries.
My SO post on this
Does CompletableFuture have a corresponding Local context?
i'm trying to implement a non-blocking DAO layer for my application developing in play framework(2.5.4). It gives me error in deleteById()
no instance(s) of variable(s) U exists so that void conforms to U
abstract class BaseDao<E extends BaseModel> {
JPAApi jpaApi;
private Class<E> entityClazz;
BaseDao(JPAApi jpaApi, Class<E> entityClazz) {
this.jpaApi = jpaApi;
this.entityClazz = entityClazz;
}
public CompletionStage<E> save(E entity) {
return CompletableFuture.supplyAsync(() -> {
jpaApi.em().persist(entity);
return entity;
});
}
public CompletionStage<Optional<E>> findById(String id) {
return CompletableFuture.supplyAsync(() -> Optional.ofNullable(jpaApi.em().find(entityClazz, id))
);
}
public void deleteById(String id) {
findById(id).thenApply(
result -> result.ifPresent(
//HERE IS WHERE MY IDE COMPLAINTS
entity -> {
entity.setActive(false);
save(entity);
}
)
);
}
}
Any help or suggestion would be appreciated.
Just to understand why there's an error
Optional.ifPresent() takes a Consumer, which returns void
CompletionStage.thenApply() takes a Function<T, U>. The return type U must match the return type of the body of the lambda - in this case Optional.ifPresent().
void is a primitive type and doesn't have a boxed equivalent so the compiler is stumped.
One thing which you could do would be to convert the expression lambda to a block lambda that returns some kind of a value.
e.g.
findById(id).thenApply(
result -> {
result.ifPresent(
entity -> {
entity.setActive(false);
save(entity);
}
);
return 1;
}
);
That should allow the compiler to tie together the types - thenApply() will be taking a Function returning an Integer, while ifPresent() is still able to take a Consumer returning void.
Alternatively, and probably preferably, you could use the thenAccept() method on CompletionStage(), which accepts a Consumer rather than a Function...
findById(id).thenAccept(
result -> result.ifPresent(
entity -> {
entity.setActive(false);
save(entity);
}
)
);
I am trying to achieve a behavior similar to that of an event bus. For my requirements, a PublishSubject seems suitable.
The subject emits items representing a result of some global operation, which might resolve successfully or fail in case of an exception. I can't use onNext() for success events and onError() with the Throwable in case of an error, since once onError() is invoked the subject terminates and any future subscribers will get no emissions apart from an onError() one.
Right now the way I see it I have to create a class representing the event, and optionally referencing a Throwable in case of an error. This however seems unwise, as one would have to handle errors inside onNext().
How would you go about it?
Creating a generic class wrapping events is a way to go. Say we call it ResponseOrError class, it should basically contain two fields
private T data;
private Throwable error;
and two simple factory methods :
public static <T> ResponseOrError<T> fromError(Throwable throwable) {
return new ResponseOrError<>(throwable);
}
public static <T> ResponseOrError<T> fromData(T data) {
return new ResponseOrError<>(data);
}
to remove some boilerplate code you can provide Transformer to make Observable of ResponseOrError type.
public static <T> Observable.Transformer<T, ResponseOrError<T>> toResponseOrErrorObservable() {
return new Observable.Transformer<T, ResponseOrError<T>>() {
#Override
public Observable<ResponseOrError<T>> call(final Observable<T> observable) {
return observable
.map(new Func1<T, ResponseOrError<T>>() {
#Override
public ResponseOrError<T> call(final T t) {
return ResponseOrError.fromData(t);
}
})
.onErrorResumeNext(new Func1<Throwable, Observable<? extends ResponseOrError<T>>>() {
#Override
public Observable<? extends ResponseOrError<T>> call(final Throwable throwable) {
return Observable.just(ResponseOrError.<T>fromError(throwable));
}
});
}
};
}
then you can use it like that :
final Observable<ResponseOrError<ImportantData>> compose = mNetworkService
.getImportantData()
.compose(ResponseOrError.<ImportantData>toResponseOrErrorObservable());
and now you can easily map result depending on success or failure or even provide another Transformer returning mapped Observable< T> instead of Observable< ResponseOrError< T>>