I found an example for how to create an observable object (ReactiveX):
static Observable<Integer> getDataSync(int i) {
return Observable.create((Subscriber<? super Integer> s) -> {
// simulate latency
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
s.onNext(i);
s.onCompleted();
});
}
But my project does not support Java 8 for lambda expression. I couldn't find example of how to use ReactiveX observable without lambda expression.
Are you just looking for the correct lambda-less syntax for what you are doing?
That would be:
static Observable<Integer> getDataSync(int i) {
return Observable.create(new Observable.OnSubscribe<Integer> {
#Override
public void call(Subscriber<? super Integer> s) {
// simulate latency
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
s.onNext(i);
s.onCompleted();
}
});
}
Related
I am trying to find out a way to avoid the kind of repetition below
try {
await().pollInterval(5, TimeUnit.SECONDS).pollDelay(500, TimeUnit.MILLISECONDS)
.atMost(30, TimeUnit.SECONDS).until(() -> {
// 1. methods in here
});
} catch (final Exception e) {
//TODO: can be handled internally
}
It happens in several places in my code, and I want to make it less repetitive, but I am not finding a way to do so. I thought about lambdas, but I don`t know much about it nor if it would fit in here.
Inside of it can be many different things, it is not the same for all nor they have the same inheritance.
public static void main(String... args) {
awaitUntil(() -> {
// payload 1
return true;
});
awaitUntil(() -> {
// payload 2
return true;
});
}
public static void awaitUntil(Callable<Boolean> conditionEvaluator) {
try {
Awaitility.await()
.pollInterval(5, TimeUnit.SECONDS)
.pollDelay(500, TimeUnit.MILLISECONDS)
.atMost(30, TimeUnit.SECONDS)
.until(conditionEvaluator);
} catch(Exception e) {
//TODO: can be handled internally
}
}
I am writing automated tests, and I want each to retry twice. So I wrote a method:
public void retry(int retries, Retryable retryable) {
for (int i = 0; i < retries; i++) {
try {
retryable.run();
break;
} catch (Exception e) {
log.warn(WARN_TEXT, retryable, (i + 1), e);
if (i == retries - 1) {
log.error(ERR_TEXT, retryable, retries, e);
retryable.handleException(e);
throw e;
}
}
}
}
public interface Retryable extends Runnable {
void handleException(Exception e);
}
Now I have couple of test methods, let's write 3 here:
#TestRailID(29828) // 1
#Test(description = "Try saving a filter without a name.",
groups = Group.PREPROD)
public void tryCreatingNoNameFilter() {
Retry.retry(2, new Retryable() {
#Override
public void handleException(Exception e) {
log.error(TEST_RUN_FAIL, 2);
}
#Override
public void run() {
userTriesCreatingNoNameFilter();
}
});
}
#TestRailID(31391) // 2
#Test(description = "Try saving a filter with too long name.",
groups = Group.PREPROD)
public void tryCreatingTooLongFilterName() {
Retry.retry(2, new Retryable() {
#Override
public void handleException(Exception e) {
log.error(TEST_RUN_FAIL, 2);
}
#Override
public void run() {
userTriesCreatingTooLongFilerName();
}
});
}
#TestRailID(29829) // 3
#Test(description = "Create and save a new filter.",
groups = Group.PREPROD)
public void createNewFilter() {
Retry.retry(2, new Retryable() {
#Override
public void handleException(Exception e) {
log.error(TEST_RUN_FAIL, 2);
}
#Override
public void run() {
userTriesCreatingNewFilter();
}
});
}
So we all can see that these methods differ only with run() method implemetation (single line).
How can I do it without copy pasting that long blocks of code?
Thank you in advacne :)
To reduce the repetitive blocks and number of lines (and make this overall look cleaner), you could:
Instead of extending Runnable, split up the exception handling and the run logic into two separate functional interfaces (see #FunctionalInterface):
#FunctionalInterface
interface ExceptionHandler {
void handleException(Exception e);
}
Runnable is in fact already a functional interface, so you can stick to this.
Then you can write these as lambdas:
Retry.retry(
2,
() -> userTriesCreatingTooLongFilerName(),
exception -> log.error(TEST_RUN_FAIL, 2)
);
As your exception handling seems to be the same for all calls, define it once:
var exceptionHandler = (ExceptionHandler) e -> log.error(TEST_RUN_FAIL, 2);
Retry.retry(2, () -> userTriesCreatingNoNameFilter(), exceptionHandler);
Retry.retry(2, () -> userTriesCreatingTooLongFilerName(), exceptionHandler);
Retry.retry(2, () -> userTriesCreatingNewFilter(), exceptionHandler);
// …
Further, alternative options:
Subclass your existing Retryable and pull up the common code.
Add a default implementation to your existing interface with the common code.
I have the below code
import java.util.function.BiConsumer;
public class ExceptionHandlingLambda {
public static void main(String[] args) {
int [] someNumbers = { 1, 2, 3, 4 };
int key = 2;
process(someNumbers, key, (v,k) -> {
try{
System.out.println(v/k);
}
catch(ArithmeticException e){
//handle exception
}
});
}
private static void process(int[] someNumbers, int key, BiConsumer<Integer, Integer> consumer) {
for (int i : someNumbers) {
//can put a try catch here but this is generic and we don't know what exception we are catching.
consumer.accept(i, key);
}
}
}
I am trying to handle some exception in a lambda. From above I have handled an exception within a lambda.
I think it makes my lambda look kind of messy.
I could also handle the exception in the process method but it would be generic and we wouldn't know what exception we are handling for.
Any other better way to handle this in lambda to have cleaner code? Any suggestions would be much appreciated.
After the suggestion from some great and kind minds I have an answer. Hope this helps someone.
process(someNumbers, key, wrapperLambda((v, k) -> System.out.println(v / k)));
//with method reference
process(someNumbers, key, ExceptionHandlingLambda::wrapperLambda);
A wrapper function for lambda which accepts a lambda and return a lambda with a try catch which makes it much cleaner.
private static BiConsumer<Integer, Integer> wrapperLambda(BiConsumer<Integer, Integer> consumer) {
//creating a new lambda and return.
// return (v,k) -> System.out.println(v+k); this would replace the lambda with addition lambda (v+k)
return (v, k) -> {
try {
consumer.accept(v, k); //execute whatever is passed in.
}
catch (ArithmeticException e) {
System.out.println("Exception caught in wrapper lambda");
}
};
}
Apply try catch in your process method and pass an additional argument to the method i.e. the exception class for which you want to handle the exception.
Process method would look like
private static void process(int[] someNumbers, int key, BiConsumer<Integer, Integer> consumer, Class<E> clazz) {
for (int i : someNumbers) {
try{
consumer.accept(i, key);
} catch(Exception ex) {
try {
E exCast = clazz.cast(ex);
System.err.println(
"Exception occured : " + exCast.getMessage());
} catch (ClassCastException ccEx) {
throw ex;
}
}
}
}
This way your lambda would not look messy and you can decide which exception to be handled at the time of calling.
I have a class that has many methods. All the methods throw one exception when data is not ready. In that case, I want to retry the method after a certain interval. So in catch, I need to add retry logic. The same logic i need to add for all methods.
Is there some way/pattern to execute same logic for all catch clause without copy paste
One way I could think of is to write my own Exception class and Throw that exception. And do this retry logic from My Exception class.
Is there any other better way to this?
class MyClass {
public void method1() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
public void method2() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
public void method3() {
try {
//do some logic
} catch (Exception e) {
//retry logic
//existing exception handling logic
}
}
}
EDIT:
class MyClass {
public void method1(int a, int b) {
try {
//do some logic
} catch (Exception e) {
Object args[] = {a,b};
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public void method2() {
try {
//do some logic
} catch (Exception e) {
Object args[] = null;
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public void method3(String abcd, int a) {
try {
//do some logic
} catch (Exception e) {
Object args[] = {abcd,a};
executeLater("method1",args);
//retry logic
//existing exception handling logic
}
}
public boolean executeLater(String methodName, Object args[]){
//Execute given method with the supplied args
return true;
}
}
Added code that shows what i would be doing in each catch clause
boolean processCompleted=false;
while(!processCompleted){
try{
doProcess();
processCompleted=true;
}catch(Exception e){
Thread.sleep(10000);
}
}
This might give you an idea. It keeps try to call doProcess until it doesn't throw exception. If any exception occurs, waits 10 seconds.
Well, you could extract the whole catch block content to a method and call that one, but this only works if your retry logic is not dependent on the specific method. And it also requires a try-catch in every method.
Instead, use functional programming to shorten it:
public class Playground
{
public static void main(String[] args)
{
new Playground().method2(1, 2);
new Playground().method1();
}
public void method1()
{
tryAndTryAgain(() -> {
// logic 1
System.out.println("no params");
throw new RuntimeException();
});
}
public void method2(int a, int b)
{
tryAndTryAgain(() -> {
// logic 2
System.out.println(a + " " + b);
throw new RuntimeException();
});
}
public static void tryAndTryAgain(Runnable tryThis)
{
try
{
tryThis.run();
}
catch (Exception e)
{
new Timer().schedule(new TimerTask()
{
#Override
public void run()
{
tryAndTryAgain(tryThis);
}
}, 1000);
// existing exception handling logic
}
}
}
The exact structure depends on your specfic implementation, but it should give you an idea how to structure it. The benefit is that all those methods can concentrate on the business logic, and the retry logic and exception handling are done in a util method. And that util method doesn't even need to know anything about parameters, methods, or anything, because all the business logic is contained in the Runnable.
I find myself writing over and over again:
Observable.create(new Observable.OnSubscribe</* some type */>() {
#Override
public void call(Subscriber<? super /* some type */> subscriber) {
try {
subscriber.onNext(/* do something */);
subscriber.onCompleted();
} catch (IOException e) {
subscriber.onError(e);
}
}
}).observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.newThread());
for network operations.
Is there any way to make it less repetative ?
The first create can be replaced by fromCallable.
Observable.fromCallable(() -> calculationReturnsAValue());
The application of schedulers can be achieved by creating a Transformer:
Transformer schedulers = o ->
o.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
and composing with it:
source.compose(schedulers);