Does a CompletableFuture completes on a re-thrown exception? - spring

I've just started using CompletableFuture and already loving it.
But one strange thing that appears to me while using a CompletableFuture is its method called "exceptionally"
Let's say I've a
CompletableFuture<?> cf1.
Now, once the data arrives, my code is applying some processing logic. In case of an exception, I make use of exceptionally method to rethrow MyCustomException
cf1
.thenApply(myData->Some Processing Logic)
.exceptionally(ex-> throw new MyCustomException())
cf.get();
Interestingly, the call to get method hangs indefinitely until I terminate the program. Does that mean that if a CompletableFuture re-throws an exception from the exceptionally block, the future will not be marked as complete? Do I need to explicity mark it as complete?

From docs the get method throws exception if the future completed exceptionally
ExecutionException - if this future completed exceptionally
So either you can return some value from exceptionally to identify the exception is thrown during thenApply and call get method for value
Second way, before calling get method you can make that future object completed using allOf, and check if the future is completed exceptionally
CompletableFuture.allOf(completableFuture);
completableFuture.isCompletedExceptionally(); //true

Heres a sample code that doesnot finish on throwing exception -
CompletableFuture<String> r1 = CompletableFuture.supplyAsync(() -> {
try{
Thread.sleep(1000);
throw new RuntimeException("blahh !!!");
}catch (Exception e) {
throw new RuntimeException(e);
}
});
CompletableFuture<String> r2 = CompletableFuture.supplyAsync(() -> "55");
CompletableFuture<String> r3 = CompletableFuture.supplyAsync(() -> "56");
CompletableFuture.allOf(r1, r2, r3).thenRun(() -> { System.out.println(Thread.currentThread()+" --- End."); });
Stream.of(r1, r2, r3).forEach(System.out::println);
try{
System.out.println(Thread.currentThread()+" --- SLEEPING !!!");
Thread.sleep(3000);
System.out.println(Thread.currentThread()+" --- DONE !!!");
} catch (Exception e) {
//e.printStackTrace();
}
Stream.of(r1, r2, r3).forEach(System.out::println);

Related

Sonar complaining logging or rethrowing the exception

I have the following below piece of code when I am running SonarQube for code quality check on it after integrating it with Maven.
However, Sonar is complaining that I should Either log or rethrow this exception.
What am I missing here? Can some one help me please.
Code
public ShippingResponse processShipping(ShippingRequest request) {
log.debug("Processing Reservation Request ....");
try{
return helper.processShippingMethod(request);
} catch (ServiceException serviceException) {
log.error(RESERVATION_EXCE, ExceptionUtils.getStackTrace(serviceException));
throw serviceException;
} catch (Exception e) {
throw new ServiceException(ErrorMessages.EPO_SM_ERR_03, e.getMessage());
}
}
The point that Sonar is trying to make is that you ideally print or keep the root cause of your exception, so basically the stack. You keep it by passing the exception object because if you only keep the message you lose all that information. To make sonar happy you either print the stack trace (log.error(ErrorMessages.EPO_SM_ERR_03, e)), or re-throw a new exception passing the Throwable object to the constructor.
So the ideal solution would be to use the ServiceException like this;
public class ServiceException extends Exception {
public ServiceException(String message, Throwable cause) {
super(message, cause);
}
}
throw new ServiceException(ErrorMessages.EPO_SM_ERR_03, e);

Unexplained `kotlinx.coroutines.JobCancellationException: Job was cancelled` with kotlin coroutines and spring WebClient?

I have a bit of code written using kotlin coroutines
suspend fun getData(request: Request): Response {
return try {
webClient.post()
.uri(path)
.body(BodyInserters.fromObject(request))
.retrieve()
.awaitExchange()
.awaitBody<Response>()
} catch (e: Exception) {
logger.error("failed", e)
throw Exception("failed", e)
}
}
I am calling this bit of code like
val response = withContext(Dispatchers.IO) {
client.getData(request)
}
In my logs i see this exception happening from time to time
kotlinx.coroutines.JobCancellationException: Job was cancelled but this does not allow me to find what actually went wrong. I assume one of the suspending extension functions (awaitExchange or awaitBody) failed but i am not sure of that.

grails application shuts down as a result of caught exception in init

I have an grails 2.4.5 application that runs the init closure from bootstrap.groovy upon startup. It may throw an exception or it may not, but in either case, the application must continue running. What actually happens is during init() the app can't communicate with the server, a SocketTimeoutException is thrown by the underlying library and is then caught by my code. The caught exception unexpectedly causes the application to invoke destroy() and the application shuts down which I don't want. I expected that since the exception is caught, nothing wrong should be reported, and the application should remain running.
Here's the code using the RestTemplate library that causes the application to be destroyed. Without this code it remains running. The exception is caught and printed and then the app shuts down.
init = { servletContext ->
try {
// Send a post request
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", auth);
headers.add(HttpHeaders.CONTENT_TYPE, "application/json");
HttpEntity entity = new HttpEntity(headers);
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectTimeout(10000);
httpRequestFactory.setReadTimeout(10000);
RestTemplate rt = new RestTemplate(httpRequestFactory);
ResponseEntity<String> rtString = rt.exchange(ME_URL + '/apps/register', HttpMethod.POST, entity, String.class);
} catch (Exception e) {
// don't rethrow
println e.getMessage(); // gets here, app is shutdown
}
}
I assumed this has something to do with the library I used (RestTemplate) so I also tried using the Unirest library. This also catches the exception but shuts down the application instead of continuing.
init = {
try {
res = Unirest
.post(ME_URL + '/apps/register')
.header('Authorization', auth)
.header('Content-Type', 'application/json')
.body([clientId: CLIENT_ID])
.asObject(Map.class);
} catch (Exception e) {
// don't rethrow
println e.getMessage(); // gets here, app is shutdown
}
}
Now I began to think that maybe exceptions are leaking from init(), so I tried to manually throw an exception on purpose to test this theory. I tried just a base Exception as well as the SocketTimeoutException that the previous two libraries threw. This is interesting because I've proven that this exception doesn't somehow "leak" out of grails init closure. This code below does NOT cause the application to shutdown and it remains running, which is what I want.
init = {
try {
throw new java.net.SocketTimeoutException("fake exception");
} catch (Exception e) {
// don't rethrow
println e.getMessage(); // gets here, but app continues
}
}
Generally the only thing printed out in the error log is a stacktrace for a java.net.SocketTimeoutException, and my own instrumentation code to show that destroy() is indeed being called.
2017-01-09 12:01:51,825 [localhost-startStop-1] ERROR StackTrace -
Full Stack Trace: XXX.YYY.ZZZ.AAA.GatewayException:
java.net.SocketTimeoutException: Read timed out at
XXX.YYY.ZZZ.registerApp(GatewayService.groovy:83) at
XXX.YYY.ZZZ.initApp(GatewayService.groovy:50) at
XXX.YYY.ZZZ.init(GatewayService.groovy:39) at
XXX.YYY.ZZZ.slientInit(GatewayService.groovy:30) at
XXX.YYY.ZZZ.BBB(Initializer.groovy:88) at
BootStrap$_closure1.doCall(BootStrap.groovy:17) at
grails.util.Environment.evaluateEnvironmentSpecificBlock(Environment.java:327)
at
grails.util.Environment.executeForEnvironment(Environment.java:320)
at
grails.util.Environment.executeForCurrentEnvironment(Environment.java:296)
at java.util.concurrent.FutureTask.run(FutureTask.java:266) at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745) Caused by:
com.mashape.unirest.http.exceptions.UnirestException:
java.net.SocketTimeoutException: Read timed out at
com.mashape.unirest.http.HttpClientHelper.request(HttpClientHelper.java:143)
at
com.mashape.unirest.request.BaseRequest.asObject(BaseRequest.java:80)
at XXX.YYY.ZZZ.registerApp(GatewayService.groovy:71) ... 12 more
What I am looking for is:
Why this is happening
What I can do to fix this problem
If there's nothing I can do to fix my existing code, what is a workaround? Workarounds that I've tried: using PostContext annotation and also afterPropertiesSet method after extending InitializingBean. These two solutions do not work, as the init code I use will eventually use GORM, so GORM must be running at the time the code runs. During these two hooks, GORM is not ready (Or so that error messages say).
I am using grails 2.4.5.
One more thing: I have eliminated all my code in init except for the code you see above, so I am fairly sure that these REST calls getting exceptions is directly responsible for the application shutting down.
Any help greatly appreciated. Thanks!

ExecutorService for Runtime.exec in Spring Boot the right way

I want to use Java ExecutorService in a Spring Boot application.
Multiple module of the application is called as #Scheduled.
This module calls a Process to get a result from an external application using Runtime.exec. The process is supposed to get a result which is processed by java
This method can be called as part of a Scheduled thread as well as part of a request and response which can be called 24/7 . Multiple instances of the method can be running at a time.
Is it optimum to use ExecutorService defined as a local variable like this or some other method is recommended.
The requirement is that Java should not be infinitely waiting to get a result. It should be timed out.
Here is the method called
public String getExternalInformation(String applicationPath, String command, int noOfTries)
{
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future;
boolean taskExecuted=false;
int trialNumber=0;
String response = "";
while((!taskExecuted)&&(trialNumber<noOfTries))
{
trialNumber++;
log.info("Starting Trial: "+trialNumber);
future= executor.submit(new TestProcessTask(applicationPath,command));
try {
System.out.println("Started Information Fetching ");
response=future.get(3, TimeUnit.MINUTES);
taskExecuted =true;
} catch (TimeoutException e) {
future.cancel(true);
System.out.println("Timed out!");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdownNow();
return response;
}
The call() method of the TestProcessTask will call the Runtime.exec and parse the returning OutputStream.
I implemented Async in Spring as suggested by M. Deinum
Using the same Future methods and got it working.,

Grails UnexpectedRollbackException in Controller

My Grails Service calls a plugin which throws a runtime exception. In my case, I don't care about the exception, so it is swallowed.
MyGrailsService {
def myMethod {
...
try {
//callPlugin
} catch (Exception ex) {
...
}
}
}
All fine, exception is caught and processing continues. However, in my Controller, I have a catch (Throwable t) block, which I am not expecting to get executed because the exception is swallowed. It turns out the catch (Throwable t) block is executed because Grails throws a a org.springframework.transaction.UnexpectedRollbackException
which of course I do not want it to do. I guess I am getting this because the exception the plugin throws is runtime, so Grails rolls back the Transaction.
I don't want this UnexpectedRollbackException being thrown.
Any tips?
What i would have done is
class MyService{
static transactional = false
def myMethod {
...
try {
//callPlugin
} catch (Exception ex) {
...
}
}
#Transactional(readOnly = true)
def someMethod {
// Some code here
}
}
The above code will make all the methods in the service non transactional and we will explicitly make the methods transactional which we want.
However once more thing can be a point to be taken care of, the method of the plugin you are calling, that method can itself be a transactional method, which on error may get rolled back and throw a UnexpectedRollbackException. So you have to check it once if the plugin method is transactional.

Resources