Iam writing the Integration test cases and i was stuck at point where i was not able to mock the
CompletableFuture.join()
Firstly,
I will make an async call and add all the responses to list
#Async("AsyncTaskExecutor")
public <T> CompletableFuture<ResponseEntity<T>> callCarrierPost(
ServiceConfig serviceConfig, Class<T> responseType, ExecutionContext executionContext,
AdapterContext adapterContext) {
ResponseEntity<T> responseEntity = carrierInvoker.postForObject(
serviceConfig, responseType, executionContext, adapterContext);
return CompletableFuture.completedFuture(responseEntity);
}
Once the async call is made then i will process the responses of the async calls like below,
private <T> List<ResponseEntity<T>> processResponseFutureList(List<CompletableFuture<ResponseEntity<T>>> responseEntityFutureList) {
List<ResponseEntity<T>> responseEntityList = new ArrayList<>();
responseEntityFutureList.forEach(responseEntityFuture -> {
try {
responseEntityList.add(responseEntityFuture.join());
} catch (CompletionException ex) {
if (ex.getCause() instanceof HttpStatusCodeException) {
HttpStatusCodeException httpStatusCodeException = ((HttpStatusCodeException) ex.getCause());
ResponseEntity<T> response = new ResponseEntity<>((T) httpStatusCodeException.getResponseBodyAsString(),
httpStatusCodeException.getResponseHeaders(),
httpStatusCodeException.getStatusCode());
responseEntityList.add(response);
} else if (ex.getCause() instanceof ResourceAccessException &&
ex.getCause().getCause() instanceof SocketTimeoutException) {
responseEntityList.add(getErrorResponseEntity(HttpStatus.SERVICE_UNAVAILABLE,
TimeOutException.Code.PROVIDER_TIME_OUT.getVal(), ex.getMessage()));
} else {
responseEntityList.add(getErrorResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR,
InternalServerException.Code.INTERNAL_M2_BROKER_ERROR.getVal(), ex.getMessage()));
}
}
});
return responseEntityList;
}
From processResponseFutureList method, Iam trying to mock the response of the completableFuture.join() to cover all the exceptional scenarios
So i tried to mock completableFuture, but no luck, it was not throwing an exception with below changes, instead it gives the original response.
#MockBean
private CompletableFuture completableFuture;
Mockito.when(completableFuture.join())
.thenReturn(new ResourceAccessException("I/O error on /uri", new SocketTimeoutException("Read Timeout")));
Iam actually new to testing and also never got an chance to work with CompletableFuture
Can someone help to mock the CompletableFuture.join() to throw an exception.
In general, don't mock types you don't own. In particular, CompletableFuture is an enormous API with very complicated semantics and I can't recommend mocking it. (Your team's opinion may vary, but CompletableFuture's large and non-encapsulated API is known as a design issue, particularly in how a CompletableFuture can be controlled from outside its source.)
Furthermore, join will never return a ResourceAccessException, nor throw one directly. Futures represent the result of some other asynchronous process, probably on another thread; if that process throws a ResourceAccessException, then as in the code you posted, join will throw a CompletionException with a getCause() value that is the underlying ResourceAccessException.
In Java 9 or better, you can use failedFuture as a static factory, passing in the raw ResourceAccessException because the real CompletableFuture implementation will wrap it for you:
// You'll probably need to specify your generics here, but I can't see
// enough of your test to fill them in realistically.
CompletableFuture</* ... */> completableFuture
= CompletableFuture.failedFuture(new ResourceAccessException(
"I/O error on /uri",
new SocketTimeoutException("Read Timeout")));
In Java 8, in absence of a static factory as in the SO question "CompletableFuture already completed with an exception", just create a real CompletableFuture and complete it exceptionally (taking advantage of the aforementioned external-control design issue):
CompletableFuture</* ... */> completableFuture
= new CompletableFuture</* ... */>();
completableFuture.completeExceptionally(
new ResourceAccessException(/*...*/));
Related
I'm trying to get into CompletableFuture class for a project I'm running, and I got to some question here:
There is the following method: it tries to find a conversation by its ID or hash; and, if not found, it throws an exception. So far, so good.
public ConversationOutput getConversationByIdOrHash(String conversationIdOrHash)
throws ConversationNotFoundException {
Conversation conversation = this.conversationRepository.getByIdOrHash(conversationIdOrHash);
if (conversation == null) {
throw new ConversationNotFoundException(conversationIdOrHash);
}
return this.modelMapper.map(conversation, ConversationOutput.class);
}
Note that I am throwing ConversationNotFoundException from my method signature. My SpringBoot controller is reacting to this exception and it's all working fine since the beginning.
What I'm trying to do is to make this to a CompletableFuture return and actually throwing an exception, something similar to:
public CompletableFuture<ConversationOutput> getConversationByIdOrHashAsync(String conversationIdOrHash)
throws ConversationNotFoundException {
return CompletableFuture.supplyAsync(() -> this.getConversationByIdOrHash(conversationIdOrHash));
}
I've seen posts where people use exceptionally to handle exceptions, but what I really want to do is to throw it to my controller and let it handle it. Any suggestions of how can I make it?
Thank you all!
The question is do you care about the result of CompletableFuture.
CompletableFuture is like a special task and it is processed on other thread. If you don't invoke .join() you won't receive the results of CompletableFuture. This method also will propagate the exception if any occured. However it waits for CompletableFuture to finish and blocks the request.
However, there is no way to get exceptions from the inside of the CompletableFuture without waiting, you have to treat it like other task.
You can pass the completed future in case of a success, and failed future along with your custom exception.
public CompletableFuture<ConversationOutput> getConversationByIdOrHashAsync(String conversationIdOrHash) {
try {
return CompletableFuture.completedFuture(this.getConversationByIdOrHash(conversationIdOrHash));
} catch (ConversationNotFoundException e) {
return CompletableFuture.failedFuture(e);
}
}
and then at your controller level you can handle the exception.
final CompletableFuture<ConversationOutput> future = getConversationByIdOrHashAsync("idOrHash");
future.whenComplete((r, e) -> {
if (e != null) {
if (e instanceof ConversationNotFoundException) {
//handling
}
}
});
There is pretty heavy use of io.vertx.core.Future in the vertx ecosystem:
https://vertx.io/docs/apidocs/io/vertx/core/Future.html
An example of using Vertx Future is here:
private Future<Void> prepareDatabase() {
Future<Void> future = Future.future();
dbClient = JDBCClient.createShared(vertx, new JsonObject(...));
dbClient.getConnection(ar -> {
if (ar.failed()) {
LOGGER.error("Could not open a database connection", ar.cause());
future.fail(ar.cause()); // here
return;
}
SQLConnection connection = ar.result();
connection.execute(SQL_CREATE_PAGES_TABLE, create -> {
connection.close();
if (create.failed()) {
future.fail(create.cause()); // here
} else {
future.complete();
}
});
});
return future;
}
I was under the impression that io.vertx.core.Future had something to do with java.util.concurrent.Future, but it appears that it doesn't. As you can see the way to tell a Vertx future to fail is to call it's fail() method.
On the other hand, we have CompletableFuture which is an implementation of the java.util.concurrent.Future interface:
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html
I don't see a fail method on the CompletableFuture, I only see "resolve()".
So my guess is that the only way to fail a CompletableFuture is to throw an Exception?
CompletableFuture<String> f = CompletableFuture.supplyAsync(() -> {
throw new RuntimeException("fail this future");
return "This would be the success result";
});
besides throwing an error, is there a way to "fail" a CompletableFuture?
In other words, using a Vertx Future, we just call f.fail(), but what about with a CompletableFuture?
CompletableFuture encourages you to throw exceptions from supplyAsync() method to describe failures.
As mentioned in the comments, there's also completeExceptionally() method, which you can use in case you have a Future at hand, and would like to fail it.
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#completeExceptionally-java.lang.Throwable-
Since Java9, there's also CompletableFuture.failedFuture(Throwable ex) construct, if you want to return an already failed future.
https://docs.oracle.com/javase/9/docs/api/java/util/concurrent/CompletableFuture.html#failedFuture-java.lang.Throwable-
I have dozens of methods that I want to wrap with the same try/catch handling. I think lambdas can help me out here, but I'm having difficulty figuring out the syntax.
Here's the context of what I'm trying to achieve.
method1(..., result -> method2(result, ...));
method2 is a handler for the results of method1. I would like to wrap method2 with a common try/catch statement that's common to a large number of handlers, without having to copy/paste the statement to all handlers.
Note: These are unchecked exceptions.
*edit - Concrete example of what I'm trying to do.
I'm using Vert.x, and they use a common design pattern of Handlers. Here's an example of their SQL interface
query(String sql, Handler<AsyncResult<ResultSet>> resultHandler)
Handler is a simple 1 function interface:
void handle(E event)
So basically, the query defined in "sql" is executed, and the results are sent to the resultHandler. Here would be an example of this in use:
connection.query("SELECT * from table1", asyncResult -> {
// do something with results
}
The above uses their documentation's standard coding style. I personally prefer to handle the results in named functions various reasons, so it changes to:
connection.query("SELECT * from table1", asyncResult -> method1(asyncResult));
void method1(AsyncResult<ResultSet> asyncResult) {
// do something with results
}
I do not have control over the query() interface, so I'm stuck with this pattern. I'm not sure if Tagir's solution will work in this context, but I'll play around with it in the morning.
*edit2 - I should note that I'm trying to wrap method1 in the above example in the exception wrapper, so ideally, I'd add the wrapper call inside the query() call. So what I'm looking for is something like:
connection.query("SELECT * from table1", wrap(asyncResult -> method1(asyncResult)));
Obviously, I can't use it that way, because it'll evaluate the original lambda as a parameter, but conceptually, that's where I want the wrapping to be added.
You may use Runnable functional interface to implement the method which handles exceptions:
public static void handleExceptions(Runnable r) {
try {
r.run();
}
catch(RuntimeException ex) {
ex.printStackTrace();
}
}
And call it like this:
handleExceptions(() -> method2(foo, bar));
If your method2 produces a result, you should determine what will be the default result in case if exception occurred (and you don't rethrow it in the handler). You may use the Supplier functional interface for such case:
public static <T> T handleExceptions(Supplier<T> r, T defaultValue) {
try {
return r.get();
}
catch(RuntimeException ex) {
ex.printStackTrace();
return defaultValue;
}
}
And call like this:
// set result to null if exception occurred
result = handleExceptions(() -> method2(foo, bar), null);
Or
// do not modify the result if exception occurred
result = handleExceptions(() -> method2(foo, bar), result);
I am trying to find out whether it is possible to create Java dynamic proxy to automatically close Autocloseable resources without having to remember of embedding such resources with try-resources block.
For example I have a JedisPool that has a getResource method which can be used like that:
try(Jedis jedis = jedisPool.getResource() {
// use jedis client
}
For now I did something like that:
class JedisProxy implements InvocationHandler {
private final JedisPool pool;
public JedisProxy(JedisPool pool) {
this.pool = pool;
}
public static JedisCommands newInstance(Pool<Jedis> pool) {
return (JedisCommands) java.lang.reflect.Proxy.newProxyInstance(
JedisCommands.class.getClassLoader(),
new Class[] { JedisCommands.class },
new JedisProxy(pool));
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try (Jedis client = pool.getResource()) {
return method.invoke(client, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw e;
}
}
}
Now each time when I call method on Jedis (JedisCommands) this method is passed to proxy which gets a new client from the pool, executes method and returns this resource to the pool.
It works fine, but when I want to execute multiple methods on client, then for each method resource is taken from pool and returned again (it might be time consuming). Do you have any idea how to improve that?
You would end up with your own "transaction manager" in which you normally would return the object to the pool immediately, but if you had started a "transaction" the object wouldn't be returned to the pool until you've "committed" the "transaction".
Suddenly your problem with using try-with-resources turns into an actual problem due to the use of a hand-crafted custom mechanism.
Using try with resources pros:
Language built-in feature
Allows you to attach a catch block, and the resources are still released
Simple, consistent syntax, so that even if a developer weren't familiar with it, he would see all the Jedis code surrounded by it and (hopefully) think "So this must be the correct way to use this"
Cons:
You need to remember to use it
Your suggestion pros (You can tell me if I forget anything):
Automatic closing even if the developer doesn't close the resource, preventing a resource leak
Cons:
Extra code always means extra places to find bugs in
If you don't create a "transaction" mechanism, you may suffer from a performance hit (I'm not familiar with [jr]edis or your project, so I can't say whether it's really an issue or not)
If you do create it, you'll have even more extra code which is prone to bugs
Syntax is no longer simple, and will be confusing to anyone coming to the project
Exception handling becomes more complicated
You'll be making all your proxy-calls through reflection (a minor issue, but hey, it's my list ;)
Possibly more, depending on what the final implementation will be
If you think I'm not making valid points, please tell me. Otherwise my assertion will remain "you have a 'solution' looking for a problem".
I don’t think that this is going into the right direction. After all, developers should get used to handle resources correctly and IDEs/compilers are able to issue warnings when autoclosable resources aren’t handled using try(…){}…
However, the task of creating a proxy for decorating all invocations and the addition of a way to decorate a batch of multiple action as a whole, is of a general nature, therefore, it has a general solution:
class JedisProxy implements InvocationHandler {
private final JedisPool pool;
public JedisProxy(JedisPool pool) {
this.pool = pool;
}
public static JedisCommands newInstance(Pool<Jedis> pool) {
return (JedisCommands) java.lang.reflect.Proxy.newProxyInstance(
JedisCommands.class.getClassLoader(),
new Class[] { JedisCommands.class },
new JedisProxy(pool));
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try (Jedis client = pool.getResource()) {
return method.invoke(client, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
public static void executeBatch(JedisCommands c, Consumer<JedisCommands> action) {
InvocationHandler ih = Proxy.getInvocationHandler(c);
if(!(ih instanceof JedisProxy))
throw new IllegalArgumentException();
try(JedisCommands actual=((JedisProxy)ih).pool.getResource()) {
action.accept(actual);
}
}
public static <R> R executeBatch(JedisCommands c, Function<JedisCommands,R> action){
InvocationHandler ih = Proxy.getInvocationHandler(c);
if(!(ih instanceof JedisProxy))
throw new IllegalArgumentException();
try(JedisCommands actual=((JedisProxy)ih).pool.getResource()) {
return action.apply(actual);
}
}
}
Note that the type conversion of a Pool<Jedis> to a JedisPool looked suspicious to me but I didn’t change anything in that code as I don’t have these classes to verify it.
Now you can use it like
JedisCommands c=JedisProxy.newInstance(pool);
c.someAction();// aquire-someaction-close
JedisProxy.executeBatch(c, jedi-> {
jedi.someAction();
jedi.anotherAction();
}); // aquire-someaction-anotherAction-close
ResultType foo = JedisProxy.executeBatch(c, jedi-> {
jedi.someAction();
return jedi.someActionReturningValue(…);
}); // aquire-someaction-someActionReturningValue-close-return the value
The batch execution requires the instance to be a proxy, otherwise an exception is thrown as it’s clear that this method cannot guarantee a particular behavior for an unknown instance with an unknown life cycle.
Also, developers now have to be aware of the proxy and the batch execution feature just like they have to be aware of resources and the try(…){} statement when not using a proxy. On the other hand, if they aren’t, they lose performance when invoking multiple methods on a proxy without using the batch method, whereas they let resources leak when invoking multiple methods without try(…){}on an actual, non-proxy resource…
AFAIK submitting Callable/Runnable to ExecutorService is the way to go if I want to execute resource-heavy code in parallel. Hence my method structure:
public class ServiceClass {
protected final ExecutorService executorService = Executors.newCachedThreadPool();
public Future<Result> getResult(Object params) {
if (params == null) {
return null; // In situations like this the method should fail
}
// Do other fast pre-processing stuff
return executorService.submit(new CallProcessResult(params));
}
private class CallProcessResult implements Callable<Result> {
private Object params;
public CallProcessResult(Object params) {
this.params = params;
}
#Override
public Result call() throws Exception {
// Compute result for given params
// Failure may happen here too!
return result;
}
}
}
public class Result {
...
}
I have marked 2 spots in the code above in which failures can happen. The options available for error handling are quite different for those 2 cases.
Before submitting the task there can be issues like invalid parameters, some fast pre-processing code that may fail.
I see several ways to signify failure here:
In case of invalid params supplied to getResult return null immediately. In this case I'll have to check if getResult returned null every time I call it.
Throw checked exceptions instead of the above.
Instantiate a Future<Result> that returns null on get() request. I would do that with Apache Commons ConcurrentUtils.constantFuture(null). In this case I would expect getResult to always return some non-null Future<Result>. I like this option more, because it is consistent with the second case.
During task execution I can expect serious errors like lack of memory, corrupted files, unavailable files etc.
I suppose the better option in my case is to return null, because the result of the task is an object.
Also, I could throw checked exceptions and handle them in ThreadPoolExecutor.afterExecute (as suggested by NiranjanBhat). See Handling exceptions from Java ExecutorService tasks
Which is the better practice (in both cases)?
Perhaps there is a different way to do this or a design pattern I should use?
I would suggest that for failure during task processing, you simply throw an appropriate exception. Don't add any special handling for this in the executor. What will happen is that it will be captured, and stored in the Future. When the Future's get method is called, it will throw an ExecutionException, which the caller of get can then unpack and handle. This is essentially how normal exception handling is transposed into the Callable/Future paradigm. This looks like this:
Future<Result> futureResult = serviceClass.getResult("foo");
try {
Result result = futureResult.get();
// do something with result
}
catch (ExecutionException ee) {
Throwable e = ee.getCause();
// do something with e
}
Given that the caller of get has to have this handling of ExecutionExceptions, you could then take advantage of that to deal with failure during submission. To do this, you could construct a Future that is like Apache Commons's constantFuture, but which throws a given exception rather than returns a given value. I don't think there's anything like that in the JDK, but it's simple (if tedious) to write:
public class FailedFuture<T> implements Future<T> {
private final Throwable exception;
public FailedFuture(Throwable exception) {
this.exception = exception;
}
#Override
public T get() throws ExecutionException {
throw new ExecutionException(exception);
}
#Override
public T get(long timeout, TimeUnit unit) throws ExecutionException {
return get();
}
#Override public boolean cancel(boolean mayInterruptIfRunning) { return false; }
#Override public boolean isCancelled() { return false; }
#Override public boolean isDone() { return true; }
}
This is somewhat dodgy - you're taking a failure during a synchronously-called method, and making it look like a failure during the asynchronously-called method. You're shifting the burden of handling the error from the code that actually caused it to some code that runs later. Still, it does mean you can have all the failure handling code in one place; that might be enough of an advantage to make this worthwhile.
You can use afterExecute method. This is defined in the ThreadPoolExecutor, which you will need to override.
This method is called after the execution of each task is completed. You will get the task instance in this callback method. You can record the errors in some variable in your task and access it in this method.