I'm new to functional programming (and Java) and I want to create something nice using it, but cannot figure out how.
I'm using BiConsumer (java.util.function.BiConsumer) for calls to the server.
I'm trying to write a code which send some request to server with existing data (calling Public createSomeTask()), only if it fails, the connector will perform a retry only once.
The code is async, Private createSomeTask() calls updateTaskStage() as well.
The problem is that I have many calls in the connector (many createSomeTask()) with current implementation, the code not looks good and I'm sure there is a way to do it better using Functional interfaces or extending the BiConsumer or any other nice way in Java 8 lile , reflection, method invoke etc.
See the code below. I hope someone can help me with that.
//Main
public class Main {
public static void main(String[] args) throws InterruptedException {
Connector connector = new Connector();
connector.createSomeTask("started",(response, error)->{
});
}
}
//Connector Class
import java.util.function.BiConsumer;
public class Connector {
static String taskStage = null;
public void createSomeTask(final String taskName,
final BiConsumer<ServerResponse, ServerError> consumer) {
createSomeTask(taskName, true, consumer);
}
private void createSomeTask(final String taskName,
boolean retry,
final BiConsumer<ServerResponse, ServerError> consumer) {
updateTaskStage((newStage, error)->{
if(error!=null) {
if (retry) {
createSomeTask(taskName, false, consumer); //The 'recursive' retry call
return;
} else {
consumer.accept(null, error);//only after second failure
return;
}
}
consumer.accept(new ServerResponse(),null);
});
}
//re-uses existing task or starting a new one when the current is null / failed
private void updateTaskStage(final BiConsumer<String, ServerError> consumer) {
if(taskStage ==null || taskStage != "failed")
consumer.accept(taskStage,null);
else
{
taskStage = "started";
consumer.accept(taskStage,null);
}
}
class ServerResponse{}
class ServerError{}
}
There is no reason to check the
retry
flag in the consumer, as you can compose a function doing the right thing before passing it toupdateTaskStage
:First, a function is created passing a translation of the back-end’s response to the provided consumer.
Then, only if
retry
istrue
, the function is composed with another function which will do a second try in the error case. For the second attempt, the direct function can be passed toupdateTaskStage
, removing the need for recursion.As it seems that the
retry
parameter wasn’t supposed to be an option, but only part of your attempt of solving the problem, you can now get rid of it, when always performing one retry is intended: