Java Generics Lambda Compilation Error - java

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);
}
)
);

Related

Returning a Supplier<T> in java

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");

Java : Combine several completable futures in a chain

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...

How do you transform a CompletableFuture of one type to another?

I currently convert my CompletableFuture<X> to CompletableFuture<Void> as shown below but I was wondering if there was a better way.
#Override
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
return realChannel.write(engineToSocketData).thenApply(c -> empty());
}
public Void empty() {
return null;
}
You're effectively trying to transform the completed value of your CompletableFuture into a value of type Void. Presumably you want to propagate any exception if that future was completed exceptionally.
CompletableFuture provides thenApply for this basic transformation, but other methods can also be used.
In your case, you'll want to ignore the value from the source future and return null, since null is the only possible value for the type Void. However, there needs to be some hint for the compiler that you're targeting the type Void.
Either be explicit by providing an explicit type argument to the invocation of thenApply
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
return realChannel.write(engineToSocketData).<Void> thenApply(c -> null);
}
or be explicit by casting to the appropriate type in the lambda expression
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
return realChannel.write(engineToSocketData).thenApply(c -> (Void) null);
}
Your solution achieves the same result, since the value is known to be of the correct type, but it involves an extra method invocation
#Override
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
return realChannel.write(engineToSocketData).thenApply(c -> empty());
}
All of these solutions will propagate the exception, if any, of the origial CompletableFuture.
Thank you to Luis, you could also just use thenAccept with a Consumer doing nothing:
public CompletableFuture<Void> packetEncrypted(ByteBuffer engineToSocketData) {
return realChannel.write(engineToSocketData).thenAccept(c -> {}):
}
The behavior is the same for any other type. thenApply lets you perform any Function on the result of a CompletableFuture.
For example, I can have a future that's meant to complete with String that's meant to be converted to an Integer.
public static void main(String[] args) throws Exception {
CompletableFuture<String> futureLine = CompletableFuture.supplyAsync(() -> "1234");
CompletableFuture<Integer> theNumber = futureLine.thenApply(Integer::parseInt);
System.out.println(theNumber.get());
}
thenApply receives the completed value and transforms it by passing it to an invocation of Integer#parseInt(String). Since parseInt has a return type of int, the return type of thenApply is inferred to CompletableFuture<Integer>.

Is there a class in java 8 that implements a "null-terminated" stream without having to roll my own?

Or is there a better way to do this that I'm missing? I'd like to create a stream based on a Supplier (which are normally infinite), but have the stream terminate when the supplier returns null. I made this myself, but it seems like a fair amount of work to accomplish a pretty simple concept.
public class NullTerminatedStreamFactory {
static int characteristics = Spliterator.ORDERED | Spliterator.DISTINCT;
public static<T> Stream<T> makeNullTerminatedStream(Supplier<T> supplier) {
return StreamSupport.stream(new NullTerminatedSpliteratorFromSupplier<>(supplier, Long.MAX_VALUE, characteristics), false);
}
static class NullTerminatedSpliteratorFromSupplier<T> extends Spliterators.AbstractSpliterator<T> {
public NullTerminatedSpliteratorFromSupplier(Supplier<T> supplier, long est, int additionalCharacteristics) {
super(est, additionalCharacteristics);
this.supplier = supplier;
}
public Supplier<T> supplier;
#Override
public boolean tryAdvance(Consumer<? super T> action) {
T next = supplier.get();
if (next != null) {
action.accept(next);
return true;
}
return false;
}
}
}
For the record, I'm using it like this, to basically create a Stream from a BlockingQueue:
NullTerminatedStreamFactory.makeNullTerminatedStream(() -> {
try {
BlockingQueue<Message> queue = getBlockingQueue();
return queue.poll(1, TimeUnit.SECONDS);
} catch (Exception e) {
log.error("Exception while trying to get message from queue", e);
}
return null;
});
You've already found a perfectly valid hand-made implementation.
As mentioned in the comments, Java 9 seems to add a takeWhile(Predicate) method. Until then, you could use a third-party library that implements something like takeWhile():
jOOλ
jOOλ has limitWhile(), which does the same thing:
Seq.generate(supplier).limitWhile(Objects::nonNull);
(disclaimer, I work for the company behind jOOλ)
Javaslang
Javaslang implemented their own Stream class, which is inspired by the Scala collections, and thus has takeWhile()
Stream.gen(supplier).takeWhile(Objects::nonNull);
Functional Java
Functional Java also ship with their own Stream implementation, that has a takeWhile() method:
Stream.fromFunction(i -> supplier.get()).takeWhile(o -> o != null);

How to invoke generic methods with runtime type information?

My program stores types of parameters mapped to the operation that accepts this type of parameter.
When using an explicit type to retrieve a stored operation, invoking the operation's method with an object of the given type as parameter is no problem.
However, when using a type that is only implicitly known, invoking the operation's method results in an error:
public class StoredArgumentTypeProblem {
static class Operation<T> {
T apply(T arg) {
return arg;
}
}
static class OperationContainer {
private Map<Class<?>, Operation<?>> storedOperations = new HashMap<>();
public <T> void put(Class<T> argType, Operation<T> opp) {
storedOperations.put(argType, opp);
}
public Class<?> getSomeStoredKey() {
return storedOperations.keySet().iterator().next();
}
public <T> Operation<T> get(Class<T> type) {
// unchecked cast, but should work given restrictions on put.
return (Operation<T>)storedOperations.get(type);
}
}
public void test() {
OperationContainer container = new OperationContainer();
container.put(Integer.class, new Operation<Integer>());
container.get(Integer.class).apply(new Integer(1234));
Class<?> keyType = container.getSomeStoredKey();
// ERROR: method apply in Operation<T> cannot be applied to given types
container.get(keyType).apply(keyType.cast(new Integer(5678)));
}
}
Of course, from Java's point of view the error is completely justified; capture #1 of '?' has nothing to do with capture #2 of '?'. But we humans can see that in this case invoking 'apply(…)' with an argument cast by keyType would work.
Is it possible to 'fool' Java and somehow dynamically apply the stored operation?
Using some type of casting? Using an Annotation? Any other ideas? …
This issue is related to limitations of wildcard capture. Wildcards essentially work like independent type parameters, and there's no way to express a relationship between them. As a workaround, you can use a "capture helper" method, which uses an actual type parameter to express that relationship:
private <T> void apply(
OperationContainer container,
Class<T> keyType,
Object argument
) {
T castArgument = keyType.cast(argument);
Operation<T> operation = container.get(keyType);
operation.apply(castArgument);
}
public void test() {
OperationContainer container = new OperationContainer();
container.put(Integer.class, new Operation<Integer>());
container.get(Integer.class).apply(new Integer(1234));
Class<?> keyType = container.getSomeStoredKey();
apply(container, keyType, new Integer(5678));
}
When writing the question above, the following solution occured to me.
To solve problems caused by generics and reflection …
use more reflection!
Given Operation and OperationContainer defined as above use Class.getMethod(…) and Method.invoke(…):
public void test() {
OperationContainer container = new OperationContainer();
container.put(Integer.class, new Operation<Integer>());
container.get(Integer.class).apply(new Integer(1234));
Class<?> keyType = container.getSomeStoredKey();
// ERROR: method apply in Operation<T> cannot be applied to given types
// container.get(keyType).apply(keyType.cast(new Integer(5678)));
Operation<?> storedOpp = container.get(keyType);
try {
storedOpp.getClass().getMethod("apply", keyType).invoke(storedOpp, keyType.cast(new Integer(5678)));
} catch (IllegalAccessException | IllegalArgumentException |
InvocationTargetException | NoSuchMethodException ex) {
throw new Error(ex);
}
}

Categories

Resources