How can I preserve clean code flow after going async with CompletableFuture? - java

I'm running into an issue with CompletableFutures. I have a JAX RS-based REST endpoint that reaches out to an API, and I need to make 3 sequential calls to this API. Current flow looks like this:
FruitBasket fruitBasket = RestGateway.GetFruitBasket("today");
Fruit chosenFruit = chooseFruitFromBasket(fruitBasket);
Boolean success = RestGateway.RemoveFromBasket(chosenFruit);
if (success) {
RestGateway.WhatWasRemoved(chosenFruit.getName());
} else {
throw RuntimeException("Could not remove fruit from basket.");
}
return chosenFruit
Of course, each of the calls to RestGateway.SomeEndpoint() is blocking because it does not use .async() in building my request.
So now let's add .async() and return a CompletableFuture from each of the RestGateway interactions.
My initial thought is to do this:
Fruit chosenFruit;
RestGateway.GetFruitBasket("today")
.thenCompose(fruitBasket -> {
chosenFruit = chooseFruitFromBasket(fruitBasket);
return RestGateway.RemoveFromBasket(chosenFruit);
})
.thenCompose(success -> {
if(success) {
RestGateway.WhatWasRemoved(chosenFruit);
} else {
throw RuntimeException("Could not remove fruit from basket.");
});
return chosenFruit;
Because this seems to guarantee me that execution will happen sequentially, and if a previous stage fails then the rest will fail.
Unfortunately, this example is simple and has many less stages than my actual use-case. It feels like I'm writing lots of nested conditionals inside of stacked .thenCompose() blocks. Is there any way to write this in a more sectioned/compartmentalized way?
What I'm looking for is something like the original code:
FruitBasket fruitBasket = RestGateway.GetFruitBasket("today").get();
Fruit chosenFruit = chooseFruitFromBasket(fruitBasket);
Boolean success = RestGateway.RemoveFromBasket(chosenFruit).get();
if (success) {
RestGateway.WhatWasRemoved(chosenFruit.getName()).get();
} else {
throw RuntimeException("Could not remove fruit from basket.");
}
return chosenFruit
But the calls to .get() are blocking! So there is absolutely no benefit from the asynchronous re-write of the RestGateway!
TL;DR - Is there any way to preserve the original code flow, while capturing the benefits of asynchronous non-blocking web interactions? The only way I see it is to cascade lots of .thenApply() or .thenCompose methods from the CompletableFuture library, but there must be a better way!
I think this problem is solved by await() in JavaScript, but I don't think Java has anything of that sort.

As the folks in the comments section mentioned, there's not much that can be done.
I will however close this off with a link to another stack that proved tremendously helpful, and solved another problem that I didn't explicitly mention. Namely, how to pass values forward from previous stages while dealing with this warning:
variable used in lambda expression should be final or effectively final.
Using values from previously chained thenCompose lambdas in Java 8
I ended up with something like this:
CompletableFuture<Boolean> stepOne(String input) {
return RestGateway.GetFruitBasket("today")
.thenCompose(fruitBasket -> {
Fruit chosenFruit = chooseFruitFromBasket(fruitBasket);
return stepTwo(chosenFruit);
});
}
CompletableFuture<Boolean> stepTwo(Fruit chosenFruit) {
return RestGateway.RemoveFromBasket(chosenFruit)
.thenCompose(success -> {
if (success) {
return stepThree(chosenFruit.getName());
} else {
throw RuntimeException("Could not remove fruit from basket.");
}
});
}
CompletableFuture<Boolean> stepThree(String fruitName) {
return RestGateway.WhatWasRemoved(fruitName);
}
Assuming that RestGateway.WhatWasRemoved() returns a Boolean.

Related

Conditionally include/exclude elements in builder

I have this bulider method:
public static QuoteDetails quoteDetailsForMA(String response) {
handleErrors(response);
try {
FullResponse quoteDetails = extractResponse(response);
Summary summary = summaryMA(quoteDetails);
List<PenaltyElement> penalties = retrievePenalties(quoteDetails);
return QuoteDetails.builder()
.priceSummary(summary)
.penalties(penalties)
.build();
} catch (Exception e) {
LOGGER.error(
"Exception thrown response: {}",
e.getMessage());
}
}
penalties may or may not be an empty list. If it is not empty I wish to execute the return statement as it currently is(with .penalties(penalties). However, If penalties is an empty list I wish to exclude it from my return. E.g. I wish to return this:
return QuoteDetails.builder()
.priceSummary(summary)
.build();
Is this possible and if so, how is it done?
The easiest technique is to make the .penalties(penalties)
method null and empty list tolerant.
Note, the authors of both of the other answers appear to love NullPointerExceptions.
Here is some example code (with assumptions):
private List<Penalty> penaltiesList;
public QuoteDetailsBuilder penalties(final List<Penalty> newValue)
{
if (CollectionUtils.isNotEmpty(newValue))
{
penaltiesList = newValue;
}
return this;
}
CollectionUtils is an apache utility for some null-safe collection functionality.
You can do it via the isEmpty() method to see if it's empty or not:
.penalties(penalties.isEmpty() ? null : penalties)
Two "obvious" solutions come to my mind:
The builder supports an empty list in the correct way. You could maybe implement your own builder to do that which is just a wrapper around the original and doesn't call the original method penalties if the parameter is an empty list.
Use if as you would regularly do for "conditional" handling:
QuoteDetailsBuilder builder = QuoteDetails.builder()
.priceSummary(summary);
if ((null != penalties) && !penalties.isEmpty()) {
builder = builder.penalties(penalties);
}
return builder.build();
(Of course in solution #2 the name of the builder class may vary depending on the implementation.)

Identify record that is culprit - coding practices

Is method chaining good?
I am not against functional programming that uses method chaining a lot, but against a herd mentality where people mindlessly run behind something that is new.
The example, if I am processing a list of items using stream programming and need to find out the exact row that resulted into throwing NullPointerException.
private void test() {
List<User> aList = new ArrayList<>();
// fill aList with some data
aList.stream().forEach(x -> doSomethingMeaningFul(x.getAddress()));
}
private void doSomethingMeaningFul(Address x) {
// Do something
}
So in the example above if any object in list is null, it will lead to NullPointerException while calling x.getAddress() and come out, without giving us a hook to identify a User record which has this problem.
I may be missing something that offers this feature in stream programming, any help is appreciated.
Edit 1:
NPE is just an example, but there are several other RuntimeExceptions that could occur. Writing filter would essentially mean checking for every RTE condition based on the operation I am performing. And checking for every operation will become a pain.
To give a better idea about what I mean following is the snippet using older methods; I couldn't find any equivalent with streams / functional programming methods.
List<User> aList = new ArrayList<>();
// Fill list with some data
int counter = 0;
User u = null;
try {
for (;counter < aList.size(); counter++) {
u = aList.get(counter);
u.doSomething();
int result = u.getX() / u.getY();
}
} catch(Exception e) {
System.out.println("Error processing at index:" + counter + " with User record:" + u);
System.out.println("Exception:" + e);
}
This will be a boon during the maintenance phase(longest phase) pointing exact data related issues which are difficult to reproduce.
**Benefits:**
- Find exact index causing issue, pointing to data
- Any RTE is recorded and analyzed against the user record
- Smaller stacktrace to look at
Is method chaining good?
As so often, the simple answer is: it depends.
When you
know what you are doing
are be very sure that elements will never be null, thus the chance for an NPE in such a construct is (close to) 0
and the chaining of calls leads to improved readability
then sure, chain calls.
If any of the above criteria isn't clearly fulfilled, then consider not doing that.
In any case, it might be helpful to distribute your method calls on new lines. Tools like IntelliJ actually give you advanced type information for each line, when you do that (well, not always, see my own question ;)
From a different perspective: to the compiler, it doesn't matter much if you chain call. That really only matters to humans. Either for readability, or during debugging.
There are a few aspects to this.
1) Nulls
It's best to avoid the problem of checking for nulls, by never assigning null. This applies whether you're doing functional programming or not. Unfortunately a lot of library code does expose the possibility of a null return value, but try to limit exposure to this by handling it in one place.
Regardless of whether you're doing FP or not, you'll find you get a lot less frustrated if you never have to write null checks when calling your own methods, because your own methods can never return null.
An alternative to variables that might be null, is to use Java 8's Optional class.
Instead of:
public String myMethod(int i) {
if(i>0) {
return "Hello";
} else {
return null;
}
}
Do:
public Optional<String> myMethod(int i) {
if(i>0) {
return Optional.of("Hello");
} else {
return Optional.empty();
}
Look at Optional Javadoc to see how this forces the caller to think about the possibility of an Optional.empty() response.
As a bridge between the worlds of "null represents absent" and "Optional.empty() represents absent", you can use Optional.ofNullable(val) which returns Empty when val == null. But do bear in mind that Optional.empty() and Optional.of(null) are different values.
2) Exceptions
It's true that throwing an exception in a stream handler doesn't work very well. Exceptions aren't a very FP-friendly mechanism. The FP-friendly alternative is Either -- which isn't a standard part of Java but is easy to write yourself or find in third party libraries: Is there an equivalent of Scala's Either in Java 8?
public Either<Exception, Result> meaningfulMethod(Value val) {
try {
return Either.right(methodThatMightThrow(val));
} catch (Exception e) {
return Either.left(e);
}
}
... then:
List<Either<Exception, Result>> results = listOfValues.stream().map(meaningfulMethod).collect(Collectors.toList());
3) Indexes
You want to know the index of the stream element, when you're using a stream made from a List? See Is there a concise way to iterate over a stream with indices in Java 8?
In your test() function you are creating an emptylist List<User> aList = new ArrayList<>();
And doing for each on it. First add some element to
aList
If you want to handle null values you can add .filter(x-> x != null) this before foreach it will filter out all null value
Below is code
private void test() {
List<User> aList = new ArrayList<>();
aList.stream().filter(x-> x != null).forEach(x -> doSomethingMeaningFul(x.getAddress()));
}
private void doSomethingMeaningFul(Address x) {
// Do something
}
You can write a black of code in streams. And you can find out the list item which might result in NullPointerException. I hope this code might help
private void test() {
List<User> aList = new ArrayList<>();
aList.stream().forEach(x -> {
if(x.getAddress() != null)
return doSomethingMeaningFul(x.getAddress())
else
system.out.println(x+ "doesn't have address");
});
}
private void doSomethingMeaningFul(Address x) {
// Do something
}
If you want you can throw NullPointerException or custom excption like AddressNotFoundException in the else part

Which is the best way to set/drop boolean flag inside lambda function

Say I have a currency rates loader returning isLoaded=true result only when all the rates are loaded successfully:
//List<String> listFrom = Stream.of("EUR", "RUB").collect(toList());
//List<String> listTo = Stream.of("EUR", "CNY").collect(toList());
boolean isLoaded = true;
final FixerDataProvider httpProvider = new FixerDataProvider(maxAttempts);
final List<CurrencyRatePair> data =
listFrom.stream()
.flatMap(from -> {
final List<CurrencyRatePair> result = httpProvider.findRatesBetweenCurrencies(from, listTo);
if (Objects.isNull(result) || result.size() == 0) {
isLoaded = false; //!!!Not working as ineffectively final!!!
}
return result.stream();
}).collect(Collectors.toList());
if (!isLoaded) {
return false;
}
// do smth with loaded data
return true;
Assignment isLoaded = false; inside lambda function is not allowed when isLoaded variable is not final or effectively final.
Which is the most elegant solution to set/drop boolean flag inside lambda expressions?
What do you think about AtomicBoolean and set(false) method as a possible approach?
You may be better off with an old-style loop, as others have suggested. It does feel like a bit of a programming faux pas to write lambdas with side-effects, but you're likely to find an equal number of developers who think it's fine too.
As for getting this particular lambda-with-side effects working, making isLoaded into an AtomicBoolean is probably your best bet. You could achieve the same effect by making isLoaded a boolean[] of size 1, but that seems less elegant than going with AtomicBoolean to me.
But seriously, try using an old-school loop instead too and see which one you like better.
If you use parallel stream, you must use AtomicBoolean. Because boolean[1] may not be safe in parallel scenario.
The java.util.stream javadoc states that
Side-effects in behavioral parameters to stream operations are, in general, discouraged, as they can often lead to unwitting violations of the statelessness requirement, as well as other thread-safety hazards.
That said, if you want to do it anyway, the solution you have identified with an AtomicBoolean will do the trick just fine.
Variables used within anonymous inner classes and lambda expression have to be effectively final.
You can use AtomicReference for your case, here is a similar snippet from ConditionEvaluationListenerJava8Test
public void expectedMatchMessageForAssertionConditionsWhenUsingLambdasWithoutAlias() {
final AtomicReference<String> lastMatchMessage = new AtomicReference<>();
CountDown countDown = new CountDown(10);
with()
.conditionEvaluationListener(condition -> {
try {
countDown.call();
} catch (Exception e) {
throw new RuntimeException(e);
}
lastMatchMessage.set(condition.getDescription());
})
.until(() -> assertEquals(5, (int) countDown.get()));
String expectedMatchMessage = String.format("%s reached its end value", CountDown.class.getName());
assertThat(lastMatchMessage.get(), allOf(startsWith("Condition defined as a lambda expression"), endsWith(expectedMatchMessage)));
}
Cheers !
If I right understand you will get isLoaded=false only in case if all off result lists will be empty (If result list is null you will get NPE in the next line so there is no any reason to do null check in this way). In this case your data list also will be empty and you don't need any boolean flags, just check if data.isEmpty() and return false if true.

Design pattern for incremental code

According to the business logic, the output of one of the method is used as an input to another. The logic has linear flow.
To emulate the behaviour, now there is a controller class which has everything.
It is very messy, too much loc and hard to modify. Also the exception handling is very complex. The individual method does some handling but the global exceptions bubble up and which involves a lot of try catch statements.
Does there exists a design pattern to address this problem?
Example Controller Class Code
try{
Logic1Inputs logic1_inputs = new Logic1Inputs( ...<some other params>... );
Logic1 l = new Logic1(logic1_inputs);
try{
Logic1Output l1Output = l.execute();
} catch( Logic1Exception l1Exception) {
// exception handling
}
Logic2Inputs logic2_inputs = new Logic2Inputs(l1Output);
Logic2 l2 = new Logic2(logic2_inputs);
try{
Logic2Output l2Output = l2.execute();
} catch( Logic2Exception l2Exception) {
// exception handling
}
Logic3Inputs logic3_inputs = new Logic3Inputs(l1Output, l2Output);
Logic3 l3 = new Logic3(logic2_inputs);
try{
Logic3Output l3Output = l3.execute();
} catch( Logic3Exception l3Exception) {
// exception handling
}
} catch(GlobalException globalEx){
// exception handling
}
I think this is called pipeline: http://en.wikipedia.org/wiki/Pipeline_%28software%29 This pattern is used for algorithms in which data flows through a sequence of tasks or stages.
You can search for a library that does this( http://code.google.com/p/pipelinepattern ) or try your own java implementation
Basically you have all you objects in a list and the output from one si passed to the next. This is a naive implementation but you can add generics and all you need
public class BasicPipelinePattern {
List<Filter> filters;
public Object process(Object input) {
for (Filter c : filters) {
try {
input = c.apply(input);
} catch (Exception e) {
// exception handling
}
}
return input;
}
}
public interface Filter {
public Object apply(Object o);
}
When faced with problems like this, I like to see how other programming languages might solve it. Then I might borrow that concept and apply it to the language that I'm using.
In javascript, there has been much talk of promises and how they can simplify not only asynchronous processing, but error handling. This page is a great introduction to the problem.
Then approach has been called using "thenables". Here's the pseudocode:
initialStep.execute().then(function(result1){
return step2(result1);
}).then(function(result2){
return step3(result3);
}).error(function(error){
handle(error);
}).done(function(result3){
handleResult(result3)
});
The advantage of this pattern is that you can focus on the processing and effectively handle errors in one place without needing to worry about checking for success at each step.
So how would this work in java? I would take a look at one of the promises/futures libraries, perhaps jdeferred. I would expect that you could put something like this together (assuming java 8 for brevity):
initialPromise.then( result1 -> {
Logic2 logic2 = new Logic2(new Logic2Inputs(result1));
return logic2.execute();
}).then(result2 -> {
Logic3 logic3 = new Logic3(new Logic3Inputs(result2));
return logic2.execute();
}).catch(exception -> {
handleException(exception)
}).finally( result -> {
handleResult(result);
});
This does, of course gloss over a hidden requirement in your code. You mention that in step 3 you need the output for both step 1 and step 2. If you were writing scala, there is syntactic sugar that would handle this for you (leaving out error handling for the moment):
for(result1 <- initialStep.execute();
Logic2 logic2 = new Logic2(Logic2Input(result1));
result2 <- logic2.execute();
Logic3 logic3 = new Logic3(Logic3Input(result1, result2));
result3 <- logic3.execute()) yield result3;
But since you don't have the ability here, then you are left to the choices of being refactoring each step to take only the output of the previous step, or nesting the processing so that result1 is still in scope when you need to set up step 3.
The classic alternative to this, as #user1121883 mentioned would be to use a Pipeline processor. The downside to this approach is that it works best if your input and output are the same type. Otherwise you are going to have to push Object around everywhere and do a lot of type checking.
Another alternative would be to expose a fluent interface for the pipeline. Again, you'd want to do some refactoring, perhaps to have a parameter-less constructor and a consistent interface for inputs and outputs:
Pipeline p = new Pipeline();
p.then(new Logic1())
.then(new Logic2())
.then(new Logic3())
.addErrorHandlder(e->handleError(e))
.complete();
This last option is more ideomatic java, but retains many of the advantages of the thenables processing, so it's probably the way that I would go.

Purpose of "return" statement in Scala?

Is there any real reason of providing the return statement in Scala? (aside from being more "Java-friendly")
Ignoring nested functions, it is always possible to replace Scala calculations with returns with equivalent calculations without returns. This result goes back to the early days of "structured programming", and is called the structured program theorem, cleverly enough.
With nested functions, the situation changes. Scala allows you to place a "return" buried deep inside series of nested functions. When the return is executed, control jumps out of all of the nested functions, into the the innermost containing method, from which it returns (assuming the method is actually still executing, otherwise an exception is thrown). This sort of stack-unwinding could be done with exceptions, but can't be done via a mechanical restructuring of the computation (as is possible without nested functions).
The most common reason you actually would want to return from inside a nested function is to break out of an imperative for-comprehension or resource control block. (The body of an imperative for-comprehension gets translated to a nested function, even though it looks just like a statement.)
for(i<- 1 to bezillion; j <- i to bezillion+6){
if(expensiveCalculation(i, j)){
return otherExpensiveCalculation(i, j)
}
withExpensiveResource(urlForExpensiveResource){ resource =>
// do a bunch of stuff
if(done) return
//do a bunch of other stuff
if(reallyDoneThisTime) return
//final batch of stuff
}
It is provided in order to accommodate those circumstances in which it is difficult or cumbersome to arrange all control flow paths to converge at the lexical end of the method.
While it is certainly true, as Dave Griffith says, that you can eliminate any use of return, it can often be more obfuscatory to do so than to simply cut execution short with an overt return.
Be aware, too, that return returns from methods, not function (literals) that may be defined within a method.
Here is an example
This method has lots of if-else statements to control flow, because there is no return (that is what I came with, you can use your imagination to extend it). I took this from a real life example and modified it to be a dummy code (in fact it is longer than this):
Without Return:
def process(request: Request[RawBuffer]): Result = {
if (condition1) {
error()
} else {
val condition2 = doSomethingElse()
if (!condition2) {
error()
} else {
val reply = doAnotherThing()
if (reply == null) {
Logger.warn("Receipt is null. Send bad request")
BadRequest("Coudln't receive receipt")
} else {
reply.hede = initializeHede()
if (reply.hede.isGood) {
success()
} else {
error()
}
}
}
}
}
With Return:
def process(request: Request[RawBuffer]): Result = {
if (condition1) {
return error()
}
val condition2 = doSomethingElse()
if (!condition2) {
return error()
}
val reply = doAnotherThing()
if (reply == null) {
Logger.warn("Receipt is null. Send bad request")
return BadRequest("Coudln't receive receipt")
}
reply.hede = initializeHede()
if (reply.hede.isGood)
return success()
return error()
}
To my eyes, the second one is more readable and even manageable than the first one. The depth of indentation (with well formatted code) goes deep and deep if you don't use a return statement. And I don't like it :)
I view return as a useful when writing imperative style code, which generally means I/O code. If you're doing pure functional code, you don't need (and should not use) return. But with functional code you may need laziness to get performance equivalent to imperative code that can "escape early" using return.

Categories