I have created a small example of reading a text file and wrap the call with CompletableFuture.
public class Async {
public static void main(String[] args) throws Exception {
CompletableFuture<String> result = ReadFileUsingLambda(Paths.get("path/to/file"));
result.whenComplete((ok, ex) -> {
if (ex == null) {
System.out.println(ok);
} else {
ex.printStackTrace();
}
});
}
public static CompletableFuture<String> ReadFileUsingSupplier(Path file) throws Exception {
return CompletableFuture.supplyAsync(new Supplier<String>() {
#Override
public String get() {
try {
return new String(Files.readAllBytes(file));
} catch (IOException e) {
e.printStackTrace();
return "test";
}
}
}, ForkJoinPool.commonPool());
}
public static CompletableFuture<String> ReadFileUsingLambda(Path file) throws Exception {
return CompletableFuture.supplyAsync(() -> {
try {
return new String(Files.readAllBytes(file));
} catch (IOException e) {
e.printStackTrace();
return "test";
}
} , ForkJoinPool.commonPool());
}
}
This code returns nothing. It executes and "nothing happens", no errors or output. If I call ReadFileUsingSupplier instead of ReadFileUsingLambda then I get the file content printed in the console!
To me this doesn't make sense because a lambda is a shorthand for writing an inline function and it shouldn't change the behaviour but in this example it does apparently.
I think it's just a matter of execution timing - the lambda may take a little more to execute, allowing the program to exit before you are done reading the file.
Try this:
add a Thread.sleep(1000); as the first statement within the try block in ReadFileUsingSupplier and you won't see any output
add a Thread.sleep(1000); at the end of your main when using ReadFileUsingLambda and you will see the expected output
To make sure your main doesn't exit before the future is completed, you can call:
result.join();
As noted, you need to result.join() in either case to avoid the main thread exiting too quickly.
It seems that there's a penalty for using lambdas vs anonymous closures while the JVM warms up, thereafter the performance is the same. I found this information at on another SO thread - which in turn links a performance study by Oracle.
As a sidenote it's not a great idea to Thread.sleep() to fix weird timing issues, ever. Figuring out the cause and applying the appropriate measures would be much clearer when re-read by you or by others, e.g.
System.out.println(result.get(5, TimeUnit.SECONDS));
This enables you to ditch the .join(), too.
Related
I just found the following code, it supplies an asynchronous task but immediately get the result (so if I understand correctly, it blocks the current thread until the result is available).
Is it efficient ?
public String myMethod() {
CompletableFuture<String> futur = CompletableFuture.supplyAsync(() -> {
// my long call to an external API
return "theResult";
});
try {
return future.get(FUTURE_TIMEOUT_DURATION, TimeUnit.MINUTES);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
If the timeout is handled correctly in the call to the external API, do I need this completable futur ?
Is it ok to simplify the code like this ?
public String myMethod() {
// my long call to an external API
return "theResult";
}
If you doesn't expect any problem with timeout you most probably can remove code related to feature.
There is possibility that code use some threadlocal variables or otherwise relies on being executed in separate thread.
I don't know about you guys but, for me it become very annoying when I see a piece of code that is repeated and I came across the following scenario when using Services that throw exception. As shown below, in each CompletableFuture block I have to do exception handling and that part is basically repeated over and over depending on how many completable futures you are going to have.
CompletableFuture<Void> future1Of15 = CompletableFuture.supplyAsync(() -> {
List<SomePojo> somePojos = null;
try {
somePojos = someServiceThatThrowsException.getAll(SomePojo.class);
} catch (SomeException e) {
//Handle the exception
e.printStackTrace();
}
return somePojos;
}).thenAcceptAsync(result -> //do something with the result);
CompletableFuture<Void> future2Of15 = CompletableFuture.supplyAsync(() -> {
List<OtherPojo> otherPojos = null;
try {
otherPojos = someServiceThatThrowsException.getAll(OtherPojo.class);
} catch (SomeException e) {
//Handle the exception
e.printStackTrace();
}
return otherPojos;
}).thenAcceptAsync(result -> //do something with the result);
Now repeat the above x number of times and you notice that, the try/catch block is repeated. In my case, I have around 15-20 such calls.
Is there a way that I could turn the above into 1 or 2 lines of code? In order words stop repeating myself with regards to exception handling inside the supplyAsync lambda?
Just add a method to your class that does all of the repeated code, and takes a Consumer<List<?>> as an argument to pass to thenAcceptAsync on the last line.
private CompletableFuture<Void> getAndAcceptAsync(Consumer<List<?>> resultProcessor) {
return CompletableFuture.supplyAsync(() -> {
List<SomePojo> somePojos = null;
try {
somePojos = someServiceThatThrowsException.getAll(SomePojo.class);
} catch (SomeException e) {
//Handle the exception
e.printStackTrace();
}
return somePojos;
}).thenAcceptAsync(resultProcessor);
}
You can then call this as many times as you need to.
future1Of15 = getAndAcceptAsync(result-> { do something } );
future2Of15 = getAndAcceptAsync(result-> { do something else } );
There are patterns for handling effects like e.g. failure in functional programming. One such pattern is the Try monad for which e.g. vavr provides an implementation in java.
Those patterns abstract a lot of boilerplate away from you via declarative apis:
CompletableFuture
.supplyAsync(() -> Try.of(() -> methodThatThrows()))
.thenAccept(res -> System.out.println(res));
Or if you aren't bound to using CompletableFuture, you may choose to use the Future monad to further reduce boilerplate code:
Future.of(() -> methodThatThrows())
.onComplete(result -> System.out.println(result));
Either way, what you end up with as the result of that Future<T> is a Try<T>, which can be either a Success<T> or a Failure which you can deal with accordingly.
I do not claim that this is the only approach or the most effective approach, I am sharing the solution that helped me DRY and it might or might not work for you. If you have a better solution, please share it.
I created the following utility method
#Component
public class CompletableFutureUtil {
#Autowired
private SomeGenericServiceThatThrowsException genericService;
public <T> CompletableFuture<Collection<T>> fireupCompletableFutureAsynchronously(Class<T> type) {
CompletableFuture<Collection<T>> future = CompletableFuture.supplyAsync(() -> {
Collection<T> mystery = null;
try {
mystery = genericService.list(type);
} catch (SomeException e) {
e.printStackTrace();
//Handle the exception
}
return mystery;
});
return future;
}
}
And now I can reuse the above utility method in the following way after autowiring it
#Autowired private CompletableFutureUtil futureUtil;
The calls basically become one to two lines max
futureUtil.fireupCompletableFutureAsynchronously(SomePojo.class)
.thenAcceptAsync(result -> //do something with result);
futureUtil.fireupCompletableFutureAsynchronously(OtherPojo.class)
.thenAcceptAsync(result -> //do something with result);
Happy DRY+ing
I use AsyncRestTemplate to make resttemplate asynchronously.
These methods should wait all asyncresttemplate processes till done, And It will return reviewContent.
Problem is callback methods are not working, before the entire method works done. So I can't take proper return value of optionName and membershipGradeCode and reviewType should be included in reviewContent.
Could someone explain what am I missing now?
rev#1
Success callback methods change the state of reviewContent, Could it be a problem?
public ReviewContent getRepresentativeReviewContent(Long dealNo, Long categoryNo, String setId) {
Optional<Map<String, Object>> review = Optional.ofNullable(boardApi.getRepresentativeReviewContent(dealNo));
if (review.isPresent()) {
Long memberNo = Long.valueOf(review.get().get("memberNo").toString());
ReviewContent reviewContent = new ReviewContent();
ListenableFuture<ResponseEntity<Map>> optionInfo = dealApi.asyncGetDealOption(Long.valueOf(review.get().get("optionNo").toString()));
optionInfo.addCallback(success -> {
try {
reviewContent.setOptionName((String) ((Map<String, Object>) success.getBody().get("data")).get("dealTitle"));
} catch (Exception e) {
reviewContent.setOptionName(null);
}
}, failure -> LOGGER.error("asyncGetDealOption", failure.getStackTrace()));
ListenableFuture<ResponseEntity<Map>> gradeInfoOfThisMember = mktApi.asyncGetMembershipGradeOfThisMember(memberNo);
gradeInfoOfThisMember.addCallback(success -> {
try {
reviewContent.setMembershipGradeCode((Integer) ((Map<String, Object>) success.getBody().get("data")).get("grade"));
} catch (Exception e) {
reviewContent.setMembershipGradeCode(0);
}
},
failure -> {
reviewContent.setMembershipGradeCode(0);
LOGGER.error("asyncGetMembershipGradeOfThisMember", failure.getStackTrace());
});
ListenableFuture<ResponseEntity<ReviewType>> reviewTypeByCategoryNo = boardApi.asyncGetReviewTypeByCategoryNo(categoryNo, setId);
reviewTypeByCategoryNo.addCallback(success -> {
try {
reviewContent.setReviewType(success.getBody());
} catch (Exception e) {
reviewContent.setReviewType(null);
}
},
failure -> {
reviewContent.setReviewType(null);
LOGGER.error("asyncGetReviewTypeByCategoryNo", failure.getStackTrace());
});
reviewContent.setReviewCount((Integer) review.get().get("reviewCount"));
reviewContent.setReviewAvgScore((Double) review.get().get("reviewAvgScore"));
reviewContent.setContents((String) review.get().get("contents"));
reviewContent.setCreateDt((String) review.get().get("createdDt"));
reviewContent.setUpdateDt((String) review.get().get("updatedDt"));
reviewContent.setMemberSrl(memberNo);
reviewContent.setTitle((String) review.get().get("title"));
reviewContent.setAccountSrl(Long.valueOf(review.get().get("accountNo").toString()));
reviewContent.setMemberId((String) review.get().get("memberId"));
reviewContent.setAccountSrl(Long.valueOf(review.get().get("accountNo").toString()));
boolean isApiExecutionDone = false;
while (!isApiExecutionDone) {
if (gradeInfoOfThisMember.isDone() && optionInfo.isDone() && reviewTypeByCategoryNo.isDone()) {
isApiExecutionDone = true;
}
}
return reviewContent;
}
return new ReviewContent();
}
So your problem is that the callbacks set properties on the object returned by your method. However, they are also executed asynchronously, and are not part of the done status of the Future: they are themselves executed once the Future is done, concurrently with the code in the getRepresentativeReviewContent method. Since the method returns as soon as all Futures are done, the properties aren't (all) set as they should.
Moreover, you didn't show the code for your ReviewContent object, but I'm pretty sure it doesn't declare the optionType, membershipGradeCode or reviewType fields as volatile. Since there are no barriers (such as synchronized blocks or Locks) in the method, there's no guarantee in the Java Memory Model that the values set in the callbacks (i.e. in other threads) would be seen in the thread executing the getRepresentativeReviewContent method.
Callbacks should only be used for side-effects outside of your main execution path, since it's hard to coordinate with them: you would have to use things like a CountDownLatch to make sure they have all executed, that would make the code even more complex.
Just wait for the asynchronous results in a straight-forward way (the code is untested though):
try {
// Not sure why you need to catch Exception here?
// If it's for flow control (absent entry in a Map), it's a bad practice.
// Just check it instead of catching NullPointerException.
reviewContent.setOptionName((String)
((Map<String, Object>) optionInfo.get().getBody().get("data"))
.get("dealTitle"));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LOGGER.error("asyncGetDealOption", e);
reviewContent.setOptionName(null);
} catch (CancellationException | ExecutionException e) {
LOGGER.error("asyncGetDealOption", e);
reviewContent.setOptionName(null);
}
Another option is to compose the Futures, such as what can be done with Guava's Futures.transform to actually get the string you need out of the complete response, so you can just call get() on that composed Future to set your property. You'd still have to managed the errors, though.
This question already has answers here:
Does a finally block always get executed in Java?
(51 answers)
Closed 6 years ago.
I'm aware of headaches that involve returning in try/catch/finally blocks - cases where the return in the finally is always the return for the method, even if a return in a try or catch block should be the one executed.
However, does the same apply to System.exit()? For example, if I have a try block:
try {
//Code
System.exit(0)
}
catch (Exception ex) {
//Log the exception
}
finally {
System.exit(1)
}
If there are no exceptions, which System.exit() will be called? If the exit was a return statement, then the line System.exit(1) would always (?) be called. However, I'm not sure if exit behaves differently than return.
The code is in an extreme case that is very difficult, if not impossible, to reproduce, so I can't write a unit test. I'm going to try to run an experiment later today, if I get a few free minutes, but I'm curious anyway, and perhaps someone on SO knows the answer and can provide it before or in case I can't run an experiment.
No. System.exit(0) doesn't return, and the finally block is not executed.
System.exit(int) can throw a SecurityException. If that happens, the finally block will be executed. And since the same principal is calling the same method from the same code base, another SecurityException is likely to be thrown from the second call.
Here's an example of the second case:
import java.security.Permission;
public class Main
{
public static void main(String... argv)
throws Exception
{
System.setSecurityManager(new SecurityManager() {
#Override
public void checkPermission(Permission perm)
{
/* Allow everything else. */
}
#Override
public void checkExit(int status)
{
/* Don't allow exit with any status code. */
throw new SecurityException();
}
});
System.err.println("I'm dying!");
try {
System.exit(0);
} finally {
System.err.println("I'm not dead yet!");
System.exit(1);
}
}
}
Simple tests including catch too reveal that if system.exit(0) does not throw a security exception, it will be the last executed statement (catch and finally are not executed at all).
If system.exit(0) does throw a security exception, catch and finally statements are executed. If both catch and finally contain system.exit() statements, only statements preceding these system.exit() statements are executed.
In both cases decribed above, if the try code belongs to a method called by another method, the called method does not return.
More details here (personal blog).
Other answers have covered how the catch and finally blocks don't run if System.exit exits the JVM without throwing a SecurityException, but they don't show what happens in a "try-with-resources" block to the resources: Are they closed?
According to the JLS, Section 14.20.3.2:
The effect of the translation is to put the resource specification "inside" the try statement. This allows a catch clause of an extended try-with-resources statement to catch an exception due to the automatic initialization or closing of any resource.
Furthermore, all resources will have been closed (or attempted to be closed) by the time the finally block is executed, in keeping with the intent of the finally keyword.
That is, resources will be closed before a catch or finally block runs. What if they are closed somehow even if catch and finally don't run?
Here's some code to demonstrate that the resources in a "try-with-resources" statement aren't closed either.
I use a simple subclass of BufferedReader that prints a statement before calling super.close.
class TestBufferedReader extends BufferedReader {
public TestBufferedReader(Reader r) {
super(r);
}
#Override
public void close() throws IOException {
System.out.println("close!");
super.close();
}
}
Then I set up the test case of calling System.exit in the try-with-resources statement.
public static void main(String[] args)
{
try (BufferedReader reader = new TestBufferedReader(new InputStreamReader(System.in)))
{
System.out.println("In try");
System.exit(0);
}
catch (Exception e)
{
System.out.println("Exception of type " + e.getClass().getName() + " caught: " + e.getMessage());
}
finally
{
System.out.println("finally!");
}
}
Output:
In try
Therefore, not only do catch and finally blocks not run, a "try-with-resources" statement won't get a chance to close its resources if System.exit succeeds.
finally block will be executed no matter what....even if try block throws any throwable(exception or error).....
only case finally block does not execute...is when we call System.exit() method..
try{
System.out.println("I am in try block");
System.exit(1);
} catch(Exception ex){
ex.printStackTrace();
} finally {
System.out.println("I am in finally block!!!");
}
It will not execute finally block. The program will be terminated
after System.exit() statement.
If you consider this behaviour problematic, and you need fine control over your System.exit calls, then the only thing you can do is wrap the System.exit functionality in your own logic. If we do that, we can get finally blocks executed and get resources closed as part of our exit flow.
What I'm considering doing is wrapping the System.exit call & functionality in my own static method. In my implementation of exit I would throw a custom subclass of Throwable or Error, and implement a custom Uncaught exception handler with Thread.setDefaultUncaughtExceptionHandler to handle that exception. Thus my code becomes:
//in initialization logic:
Thread.setDefaultUncaughtExceptionHandler((thread, exception) -> {
if(exception instanceof SystemExitEvent){
System.exit(((SystemExitEvent)exception).exitCode);
}
})
// in "main flow" or "close button" or whatever
public void mainFlow(){
try {
businessLogic();
Utilities.exit(0);
}
finally {
cleanUpFileSystemOrDatabaseConnectionOrWhatever();
}
}
//...
class Utilities {
// I'm not a fan of documentaiton,
// but this method could use it.
public void exit(int exitCode){
throw new SystemExitEvent(exitCode);
}
}
class SystemExitEvent extends Throwable {
private final int exitCode;
public SystemExitEvent(int exitCode){
super("system is shutting down")
this.exitCode = exitCode;
}
}
This strategy has the added "benefit" of making this logic testable: to test that the method containing our "main flow" actually requests the system to exit, all we have to do is catch a throwable and assert that is the write type. For example, a test for our business logic wrapper might look like:
//kotlin, a really nice language particularly for testing on the JVM!
#Test fun `when calling business logic should business the business`(){
//setup
val underTest = makeComponentUnderTest(configureToReturnExitCode = 42);
//act
val thrown: SystemExitEvent = try {
underTest.mainFlow();
fail("System Exit event not thrown!")
}
catch(event: SystemExitEvent){
event;
}
//assert
assertThat(thrown.exitCode).isEqualTo(42)
The major downside to this strategy is that it is a way of getting functionality out of exception flow, which often has unintended consequences. The most obvious one, in this case, is that anywhere you've written try { ... } catch(Throwable ex){ /*doesnt rethrow*/ } will have to be updated. In the case of libraries that have custom execution contexts, they will need to be retrofitted to also understand this exception.
On balance, this seems like a good strategy to me. Does anybody else here think so?
In example below, if System.exit(0) is before the exception line, the program will be terminated normally, so the FINALLY will not execute.
If the System.exix(0) is the last line of the try block, here we have 2 scenarios
when exception is present then finally block is executed
when exception is not present then finally block is not executed
.
package com.exception;
public class UserDefind extends Exception {
private static int accno[] = {1001,1002,1003,1004,1005};
private static String name[] = {"raju","ramu","gopi","baby","bunny"};
private static double bal[] = {9000.00,5675.27,3000.00,1999.00,1600.00};
UserDefind(){}
UserDefind(String str){
super(str);
}
public static void main(String[] args) {
try {
//System.exit(0); -------------LINE 1---------------------------------
System.out.println("accno"+"\t"+"name"+"\t"+"balance");
for (int i = 0; i < 5; i++) {
System.out.println(accno[i]+"\t"+name[i]+"\t"+bal[i]);
//rise exception if balance < 2000
if (bal[i] < 200) {
UserDefind ue = new UserDefind("Balance amount Less");
throw ue;
}//end if
}//end for
//System.exit(0);-------------LINE 2---------------------------------
}//end try
catch (UserDefind ue)
{
System.out.println(ue);
}
finally{
System.out.println("Finnaly");
System.out.println("Finnaly");
System.out.println("Finnaly");
}
}//end of main
}//end of class
I am using the java Microsoft Translator API and am experiencing a problem where the Translator becomes stuck; doesn't translate and doesn't throw any exceptions. I have tried using the Future method to detect a timout, but even that doesn't do anything. The code stops without any exceptions. Here is my code. Is there anything wrong and what can I do to fix it.
import com.memetix.mst.language.Language;
import com.memetix.mst.translate.Translate;
public class Translate
{
public static String translate (String word)
{
Translate.setClientId("My ID");
Translate.setClientSecret("My Secret");
ExecutorService executor = Executors.newCachedThreadPool();
Callable<String> task = new Callable<String>()
{
public String call()
{
try
{
String translatedWord = Translate.execute(currentWord, Language.FRENCH, Language.ENGLISH);
return translatedWord;
}
catch (Exception e)
{
return "I don't know";
}
}
};
Future<String> future = executor.submit(task);
try
{
String result = future.get(5, TimeUnit.SECONDS);
System.out.println(result);
return result;
}
catch (Exception e)
{
System.out.println("failed");
future.cancel(true);
return "I don't know";
}
}
public static void main (String args[])
{
String frenchWord = "Bonjour";
String englishWord = translate(frenchWord);
System.out.println(englishWord);
}
}
When I replace the translate line in the call method, it all works well. However, Translate.execute(...) seems to be causing the problem.
Catch & log Throwable, not just Exception. Those Executor/ ThreadPoolExecutor things do a poor job of logging failures & errors thrown out, that will kill a thread & never explain why.
Oh, and when you catch an Exception -- log it. Otherwise the next programmer who works on your code will have to have you whipped for your sins. Even e.printStackTrace( System.out) is a thousand times better than nothing.
Does the Translator work even once? "Stuck" would imply that it did, but you're not clear. Be clear.
Try getting a stack dump in your debugger, or pressing Ctrl-Break in the console (it doesn't kill the program). Odds it won't tell you anything because a ClassNotFound has killed the thread-pool, but you might as well try.