I want to create a class that can run a method until a condition about the return value is fulfilled.
It should look something like this
methodPoller.poll(pollDurationSec, pollIntervalMillis)
.method(dog.bark())
.until(dog -> dog.bark().equals("Woof"))
.execute();
My method poller look somewhat like this () // following GuiSim answer
public class MethodPoller {
Duration pollDurationSec;
int pollIntervalMillis;
public MethodPoller() {
}
public MethodPoller poll(Duration pollDurationSec, int pollIntervalMillis) {
this.pollDurationSec = pollDurationSec;
this.pollIntervalMillis = pollIntervalMillis;
return this;
}
public MethodPoller method(Supplier supplier) {
return this;
}
public MethodPoller until(Predicate predicate) {
return this;
}
}
But I am having a hard time going opn from here.
How can I implement a retry to a general method until a condition is fulfilled?
Thanks.
解决方案
Yes, this can easily be done in Java 7 and even cleaner using Java 8.
The parameter to your method method should be a java.util.function.Supplier and the parameter to your until method should be a java.util.function.Predicate.
You can then use method references or lambda expressions to create you Poller like so:
myMethodPoller.poll(pollDurationInteger, intervalInMillisecond)
.method(payment::getStatus)
.until (paymentStatus -> paymentStatus.getValue().equals("COMPLETED"))
.execute();
As a side note, if you're going to use Java 8, I'd recommend using java.time.Duration instead of an integer to represent the poll duration and the interval.
I'd also recommend looking into https://github.com/rholder/guava-retrying which is a library that you could perhaps use. If not, it could be a good inspiration for your API as it features a nice fluent API.
EDIT:
Following the update to the question, here is a simple implementation. I've left some parts for you to complete as TODOs.
import java.time.Duration;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class MethodPoller {
Duration pollDurationSec;
int pollIntervalMillis;
private Supplier pollMethod = null;
private Predicate pollResultPredicate = null;
public MethodPoller() {
}
public MethodPoller poll(Duration pollDurationSec, int pollIntervalMillis) {
this.pollDurationSec = pollDurationSec;
this.pollIntervalMillis = pollIntervalMillis;
return this;
}
public MethodPoller method(Supplier supplier) {
pollMethod = supplier;
return this;
}
public MethodPoller until(Predicate predicate) {
pollResultPredicate = predicate;
return this;
}
public T execute()
{
// TODO: Validate that poll, method and until have been called.
T result = null;
boolean pollSucceeded = false;
// TODO: Add check on poll duration
// TODO: Use poll interval
while (!pollSucceeded) {
result = pollMethod.get();
pollSucceeded = pollResultPredicate.test(result);
}
return result;
}
}
Sample use:
import static org.junit.Assert.assertTrue;
import java.util.UUID;
import org.junit.Test;
public class MethodPollerTest
{
@Test
public void test()
{
MethodPoller poller = new MethodPoller<>();
String uuidThatStartsWithOneTwoThree = poller.method(() -> UUID.randomUUID().toString())
.until(s -> s.startsWith("123"))
.execute();
assertTrue(uuidThatStartsWithOneTwoThree.startsWith("123"));
System.out.println(uuidThatStartsWithOneTwoThree);
}
}