简体   繁体   中英

Generic method implementation with type checking in Java Futures and Callable

I am trying to add a custom cache layer using HazelCast, but I am not sure how to implement the method below

public <T> CompletionStage<T> getOrElseUpdate(String key, Callable<CompletionStage<T>> callable, int expiration)

Below is my full class. The contract of the above method is to find item based on key from cache else execute the block and return a completion stage with added item in it.

I have tried few ways of doing it, but lot of type erasure errors and non-conversion of Callable<CompletionStage<T>> has had me confused.

import akka.Done;
import com.hazelcast.core.IMap;
import play.cache.AsyncCacheApi;

import java.util.concurrent.*;

import static java.util.concurrent.CompletableFuture.runAsync;
import static java.util.concurrent.CompletableFuture.supplyAsync;

public class MyAsyncCache<T> implements AsyncCacheApi {

    IMap<String, T> internalMapCache;

    @Override
    public <T> CompletionStage<T> get(String key) {
        return supplyAsync( () -> {
            T t = (T) internalMapCache.get(key);
            return t;});

    }

    @Override
    public <T> CompletionStage<T> getOrElseUpdate(String key, Callable<CompletionStage<T>> callable, int expiration) {

        supplyAsync( () -> {
            T t = (T) internalMapCache.get(key);
            if(t == null){
                //callable.call()
            }else {
                return t;
            }
        }

        );
    }

    @Override
    public <T> CompletionStage<T> getOrElseUpdate(String key, Callable<CompletionStage<T>> block) {

    }

    @Override
    public CompletionStage<Done> set(String key, Object value, int expiration) {
        return set(key,value);
    }

    @Override
    public CompletionStage<Done> set(String key, Object value) {
        return supplyAsync( () -> {
            internalMapCache.set(key, value);
            return Done.getInstance();
        });
    }

    @Override
    public CompletionStage<Done> remove(String key) {
        return supplyAsync( () -> {
           internalMapCache.remove(key);
            return Done.getInstance();
        });
    }

    @Override
    public CompletionStage<Done> removeAll() {
        return supplyAsync( () -> {
            internalMapCache.clear();
            return Done.getInstance();
        });
    }

}

Any help, leads to resolve this will greatly be appreciated.


Update

  1. Removed the type from the class MyAsyncCache<T> doesn't need to be generic at that level so its only MyAsyncCache now
  2. I have added my implementation of the method getOrElseUpdate as below but I have a feeling it can be improved yet.

The method updated as below:

@Override
public <T> CompletionStage<T> getOrElseUpdate(String key, Callable<CompletionStage<T>> callable, int expiration) {
    CompletableFuture<T> uCompletableFuture = supplyAsync(() -> {
        T obj;
        if (!mapBased.containsKey(key)) {
            try {
                Future<CompletionStage<T>> submit = Executors.newSingleThreadExecutor()
                                                             .submit(callable);
                obj = submit.get().toCompletableFuture().get();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        } else {
           obj = (T) mapBased.get(key);
        }
        return obj;
    });
    return uCompletableFuture;
}

How can I improve on the above method ?

T in

public class MyAsyncCache<T> implements AsyncCacheApi {

and T in

public <T> CompletionStage<T> get(String key) {

are different. Use different letters for them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM