How could I wrote a ThrowingSupplier with an unchecked method that could replace this part of code? I have really no idea how to start with it should it be an interface or rather a class.
try {
// get connection with the database
connection = dataSource.getConnection();
} catch (Exception e) {
throw new UndeclaredThrowableException(e);
}
What I would like to get is something like
Connection connection = ThrowingSupplier.unchecked(dataSource::getConnection).get();
Any ideas how should it looks like? I am not sure if it should be an interface or a class I tried to wrote that, but then I could not create a static method unchecked and I would not to create new instance of that.
If I understand correctly, this is what you want:
public class ThrowingSupplier {
public static <T> Supplier<T> unchecked(Callable<T> callable) {
return () -> {
try {
return callable.call();
}
catch (Exception e) {
throw new UndeclaredThrowableException(e);
}
};
}
// example usage:
public static void main(String[] args) {
DataSource dataSource = null;
Connection connection = ThrowingSupplier.unchecked(dataSource::getConnection).get();
}
}
Related
I need methodA2 also gets executed even though there is an exception by methodA1(). Here I have added only two methods as methodA1() and methodA2(). Let's say there are many methods. In that case also, the solution should be able to applicable.
class A {
String methodA1() throws ExceptionE {
// do something
}
String methodA2() throws ExceptionE {
// do something
}
}
class C extends A {
String methodC() throws ExceptionE2 {
try {
methodA1();
methodA2();
} catch (ExceptionE e) {
throw new ExceptionE2();
}
}
}
Please note that there can be many methods invoked with methodA1, methodA2. In that case having multiple try, catch, finally will look ugly.. So are there any other methods to do that?
I need to store error information in a log file. In methodA1(), methodA2() ... information in each tag is get validated. what I want is having all the error information in log file. Once exception throws it will generate log file. So I will miss validation information from other tags. So we can't go for finally approach.
You can use a loop with Java 8 lambdas:
interface RunnableE {
void run() throws Exception;
}
class Example {
public static void main(String[] args) {
List<RunnableE> methods = Arrays.asList(
() -> methodA1(),
() -> methodA2(),
() -> methodA3()
);
for (RunnableE method : methods) {
try {
method.run();
} catch (Exception e) {
// log the exception
}
}
}
private static void methodA1() throws Exception {
System.out.println("A1");
}
private static void methodA2() throws Exception {
System.out.println("A2");
}
private static void methodA3() throws Exception {
System.out.println("A3");
}
}
Please note that the interface is needed only when methods throw checked exception. If they were throwing only runtime exceptions, you could use java.lang.Runnable instead.
No other way. If each method can throw exception, but you want to continue execution of remaining methods anyway, then each method call must be in its own try-catch block.
Example:
List<Exception> exceptions = new ArrayList<>();
try {
methodA1();
} catch (Exception e) {
exceptions.add(e);
}
try {
methodA2();
} catch (Exception e) {
exceptions.add(e);
}
try {
methodA3();
} catch (Exception e) {
exceptions.add(e);
}
if (! exceptions.isEmpty()) {
if (exceptions.size() == 1)
throw exceptions.get(0);
throw new CompoundException(exceptions);
}
You will of course have to implement the CompoundException yourself.
I have a lambda expression, which can throw a IOException:
Function<String, List<String>> readFile = path-> {
try {
return Files.readAllLines(
Paths.get((String) path), Charset.forName("UTF-8"));
} catch (IOException e) {
return null;
}
};
I would like to write the same lambda expression without using the try {} catch {} block, so that the exception would be rethrown to the enclosing function:
public static void main(String[] args) throws IOException {
Function<String, List<String>> readFile = path-> {
try {
return Files.readAllLines(
Paths.get((String) path), Charset.forName("UTF-8"));
} catch (IOException e) {
return null;
}
};
}
The only problem is that I cannot define my own interfaces/classes and I can only use interfaces provided by Java APIs.
Would that be possible?
If you want to rethrow the excepion, you can use RuntimeException.
Add this to your catch body.
throw new RuntimeException(e);
Since Function.apply does not throw checked exceptions, you cannot do it ...
... in a legal way. However, you can consider "sneaky throw" if you can take the risk
interface FunctionX<T,R, X extends Exception> extends Function<T,R>
{
R applyX(T t) throws X;
#Override
default R apply(T t)
{
try
{
return applyX(t);
}
catch (Exception x)
{
throw Util.sneakyThrow(x);
}
}
public static <T,R,X extends Exception>
FunctionX<T,R,X> of(FunctionX<T,R,X> f){ return f; }
}
// Util.java
public static RuntimeException sneakyThrow(Throwable t)
{
throw Util.<RuntimeException>sneakyThrow0(t);
}
#SuppressWarnings("unchecked")
private static <T extends Throwable> T sneakyThrow0(Throwable t) throws T
{
throw (T)t;
}
Usage example
Function<String, List<String>> readFile = FunctionX.of( path-> {
return Files.readAllLines(
Paths.get(path), Charset.forName("UTF-8"));
} );
readFile.apply("/no-file");
I have made this abstract class to automatically retry network calls if some exception is thrown.
I take care to not retry after InterruptedException &
UnknownHostException.
I retry 5 times. After each failure
I perform an exponential back off, starting from 300ms going upto
1500ms.
public abstract class AutoRetry {
private Object dataToReturn = null;
public Object getDataToReturn() {
return this.dataToReturn;
}
public AutoRetry() {
short retry = -1;
while (retry++ < StaticData.NETWORK_RETRY) {
try {
Thread.sleep(retry * StaticData.NETWORK_CALL_WAIT);
this.dataToReturn = doWork();
break;
} catch (InterruptedException | UnknownHostException e) {
e.printStackTrace();
this.dataToReturn = null;
return;
} catch (IOException e) {
e.printStackTrace();
}
}
}
protected abstract Object doWork() throws IOException;
}
I use it as follows :
final Object dataAfterWork = new AutoRetry() {
#Override
protected Object doWork() throws IOException {
return; //a network call which returns something
}
}.getDataToReturn();
So is this implementation good/correct ?
EDIT
moved to https://codereview.stackexchange.com/questions/87686
This looks pretty good, but I would split the running task from the retry. Also use generics, don't just throw Object about.
Use a Java 8 lambda and the return of the method:
public static <T> Optional<T> doWithRetry(final Supplier<T> t) {
for (int retry = 0; retry <= StaticData.NETWORK_RETRY; ++retry) {
try {
Thread.sleep(retry * StaticData.NETWORK_CALL_WAIT);
return Optional.of(t.get());
} catch (InterruptedException | UnknownHostException e) {
LOGGER.log(Level.SEVERE, "Call failed.", e);
return Optional.empty();
} catch (IOException e) {
LOGGER.log(Level.WARNING, "Call failed. Retry.", e);
}
}
LOGGER.log(Level.SEVERE, "Call failed. Retries exceeded.");
return Optional.empty();
}
Also, use a real logger, not printStackTrace...
Usage:
final String data = doWithRetry(() -> {
//do stuff
});
If your lambda needs to throw an exception, you'll need to define your own #FunctionalInterface:
#FunctionalInterface
interface StuffDoer<T> {
T doStuff() throws Exception;
}
And use that in the method signature, you'll need to handle generic Exception.
Pre-Java 8 usage:
final String data = doWithRetry(new StuffDoer<T>() {
#Override
public T get() throws Exception {
return null;
}
});
So I have a bit of situation here with my design and was wondering whether I could
get some feedback.
public class Class1 {
public void eatFish(){}
}
public class Class2 {
public void eatBacon(){
// some nasty code here to cause an exception
}
}
public class Class3 {
public void eatFruit(){}
}
public InvokeAllClasses() {
public static void main(String[] args) {
Class1 c1 = new Class1();
Class2 c2 = new Class2();
Class3 c3 = new Class3();
c1.eatFish();
c2.eatBacon();
c3.eatFruit();
}
}
See the problem here in InvokeAllClasses is that, because c2.eatBacon();
blows up, c3.eatFish() would not be executed. Is there a way to still execute
c3 although c2 blew up?
Update
After thinking more about, I guess I could wrap each call in a try...catch block but that is just messy.
Put the try...catch in the method defintion:
public void eatBacon(){
try{
// some nasty code here to cause an exception
} catch(Exception e){
//do something
}
}
This won't look as bad as putting it when you call the method. If you know where exactly in the code the exception could be happening, then only surround those statements.
You could handle the exceptions within the methods themselves so they aren't thrown back up to the calling method, but other than try/catch/finally blocks, there isn't a good practice way to ignore exceptions.
Unless you are sure that you will never have to handle any exceptions thrown by those methods, it might be better to avoid swallowing all of them at the source.
It's been a while since I wrote Java code and I could not try and compile it, but the idea is to create an object which has the responsability to execute tasks and swallow any exceptions.
It may look like:
public class SilentExecutor {
List<Runnable> tasks;
public SilentExecutor(List<Runnable) tasks) {
this.tasks = tasks == null? new List<Runnable>() : tasks;
}
public void execute() {
for (Runnable task : this.tasks) silentlyExecute(task);
}
private void silentlyExecute(Runnable task) {
try { task.run(); }
catch (Exception e) {}
}
}
Then your code could be something like:
new SilentExecutor(Arrays.asList(
() -> { c1.eatFish(); },
() -> { c2.eatBacon(); },
() - > { c3.eatFruit(); }
)).execute();
Why not just catch the exception and move on? I honestly don't think it will be messy.
Make your method to throw an exception.
public InvokeAllClasses() throws Exception {
public static void main(String[] args) {
Class1 c1 = new Class1();
Class2 c2 = new Class2();
Class3 c3 = new Class3();
try{
c1.eatFish();
}catch(Exception e){System.out.println("Oh noes! There was something wrong!!!")}
finally{
c2.eatBacon();
c3.eatFruit();
}
}
As you can see. The "finally" statement will force your code to perform no matter if the statement inside the try fails or throws an exception.
There are two approaches you could take. The first option is to ignore the exceptions completely.
try {
c1.eatFish();
} catch(Exception e) {//Ignore}
try {
c2.eatBacon();
} catch(Exception e) {//Ignore}
try {
c3.eatFruit();
} catch(Exception e) {//Ignore}
If you want the exception to be thrown in the end, you can put the result into a variable and then throw it at the end or use the finally clause.
try {
c1.eatFish();
finally {
try {
c2.eatBacon();
} finally {
c3.eatFruit();
}
}
If you are looking for something more readable, you could wrap the method calls.
public static void main(String[] args) {
Class1 c1 = new Class1();
Class2 c2 = new Class2();
Class3 c3 = new Class3();
callEatFishIgnoringException(c1);
callEatBaconIgnoringException(c2);
callEatFruitIgnoringException(c3);
}
private static void callEatFishIgnoringException(Class1 c1) {
try {c1.eatFish()} catch (Exception e) {//Ignore}
}
private static void callEatBaconIgnoringException(Class2 c2) {
try {c2.eatBacon()} catch (Exception e) {//Ignore}
}
private static void callEatFruitIgnoringException(Class3 c3) {
try {c3.eatFruit()} catch (Exception e) {//Ignore}
}
My Java application requires a retry logic on remote calls failures.
These remote calls are:
scattered all over the application
pertain to different Remote Service classes.
Also, the retry logic may have varying retry interval and varying retry attempts.
I need a generic retry() implementation which can make appropriate method calls depending on from where it is called. Below is a simple code illustration of I am looking for. I know we can attempt to do this using java reflection, but, is there a framework or an open source available somewhere which is read-to-use?
try {
ClassA objA = remoteServiceA.call(paramA1, paramA2, ...);
} catch (Exception e){
ClassA objA = (ClassA)retry(remoteService, listOfParams, ..); // generic method call
}
..
try {
ClassB objB = remoteServiceB.call(paramB1, paramB2, ...);
} catch (Exception e){
ClassA objB = (ClassB)retry(remoteService, listOfParams, ..); // generic method call
}
As already suggested, you should use AOP and Java annotations. I would recommend a read-made mechanism from jcabi-aspects (I'm a developer):
#RetryOnFailure(attempts = 3, delay = 5)
public String load(URL url) {
return url.openConnection().getContent();
}
Read also this blog post: http://www.yegor256.com/2014/08/15/retry-java-method-on-exception.html
Update: Check RetryFunc from Cactoos.
This is a book example of where aspectj (or aop in general) can be used, see 8.2.7 Example in Spring documentation and 5 Reasons Java Developers Should Learn and Use AspectJ.
Basically an aspect intercepts all calls to given methods (specified using annotation, naming convention, whatever) and retries.
Assume you have a method, that need to retied at every 500ms and upto 5 times.
Current class:
public class RemoteCaller{
Service serviceCaller;
public void remoteCall(String message) {
serviceCaller.updateDetails( this.message);
return null;
}
}
Modified approach:
public class RetriableHelper<T> implements Callable<T> {
private Callable<T> task;
private int numberOfRetries;
private int numberOfTriesLeft;
private long timeToWait;
public RetriableHelper(int numberOfRetries, long timeToWait, Callable<T> task) {
this.numberOfRetries = numberOfRetries;
numberOfTriesLeft = numberOfRetries;
this.timeToWait = timeToWait;
this.task = task;
}
public T call() throws Exception {
while (true) {
try {
return task.call();
} catch (InterruptedException e) {
throw e;
} catch (CancellationException e) {
throw e;
} catch (Exception e) {
numberOfTriesLeft--;
if (numberOfTriesLeft == 0) {
throw e;
}
Thread.sleep(timeToWait);
}
}
}
}
Backend system/remote call class:
public class RemoteCaller{
Service serviceCaller;
public void remoteCall(String message) {
class RemoteCallable implements Callable<Void> {
String message;
public RemoteCallable( String message)
{
this.message = message;
}
public Void call() throws Exception{
serviceCaller.updateDetails( this.message);
return null;
}
}
RetriableHelper<Void> retriableHelper = new RetriableHelper<Void>(5, 500, new RemoteCallable( message));
try {
retriableHelper.call();
} catch (Exception e) {
throw e;
}
}
}
enter link description here Spring has a retry annotation which servers the purpose
Step 1: Add following dependency to your POM
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.1.5.RELEASE</version>
</dependency>
Step 2: Enabling Spring Retry
To enable Spring Retry in an application, we need to add the #EnableRetry annotation to our #Configuration class:
Ex:
#Configuration
#EnableRetry
public class AppConfig { ... }
Step 3: To add retry functionality to methods, #Retryable can be used:
Ex:
#Service
public interface MyService {
#Retryable(
value = { SQLException.class },
maxAttempts = 2,
backoff = #Backoff(delay = 5000))
void retryService(String sql) throws SQLException;
...
}
Step 4.The #Recover annotation is used to define a separate recovery method when a #Retryable method fails with a specified exception:
Ex:
#Service
public interface MyService {
...
#Recover
void recover(SQLException e, String sql);
}
See Url for more details : http://www.baeldung.com/spring-retry
where do you get the services from? use a factory to Proxy the service you get from the original factory. The proxy can then implement the retry transparently. See the java Proxy/ProxyGenerators in reflection.
If you are using spring , then better go with Aspects.
Otherwise, below sample solution can work:
public class Test
{
public static void main(String[] args) throws Exception
{
Test test = new Test();
test.toRunFirst("Hello! This is normal invocation");
runWithRetry(test, "toRunFirst", "Hello! This is First, called with retry");
runWithRetry(test, "toRunSecond", "Hello! This is Second, called with retry");
}
public void toRunFirst(String s) {
System.out.println(s);
}
public void toRunSecond(String s) {
System.out.println(s);
}
public static Object runWithRetry(Object obj, String methodName, Object... args) throws Exception
{
Class<?>[] paramClass = new Class<?>[args.length];
for(int i=0; i< args.length; i++) {
paramClass[i] = args[i].getClass();
}
Method method = obj.getClass().getDeclaredMethod(methodName, paramClass);
int retryCount = 2;
for(int i=0; i< retryCount; i++) {
try {
return method.invoke(obj, args);
}
catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
}
I did not find what I needed so there is mine.
The main feature is that it throws the type of Exception you need when maxRetries is reached so you can catch it in the call.
import org.apache.log4j.Logger;
public class TaskUtils {
public static <E extends Throwable> void retry(int maxRetries, Task<E> task) throws E {
retry(maxRetries, 0, null, task);
}
public static <E extends Throwable> void retry(int maxRetries, long waitTimeMs, Logger logger, Task<E> task) throws E {
while (maxRetries > 0) {
maxRetries--;
try {
task.run();
} catch (Exception e) {
if (maxRetries == 0) {
try {
throw e;
} catch (Exception ignored) { // can't happen but just in case we wrap it in
throw new RuntimeException(e);
}
}
if (logger != null)
logger.warn("Attempt " + maxRetries + " failed", e);
try {
Thread.sleep(waitTimeMs);
} catch (InterruptedException ignored) {
}
}
}
}
public interface Task<E extends Throwable> {
void run() throws E;
}
}
Usage :
TaskUtils.retry(3, 500, LOGGER, () -> stmClickhouse.execute(
"ALTER TABLE `" + database + "`.`" + table.getName() + "` ON CLUSTER " + clusterName + allColumnsSql
));
add it into pom.xml
<dependency>
<groupId>org.deking.utils</groupId>
<artifactId>retry</artifactId>
<version>0.0.2-SNAPSHOT</version>
</dependency>
new Retry<String>()
.maxOperationWaitTime(30_000)//Max operation wait time during a single operation
.retryIntervalTime(1_000)//Interval time between two operations
.maxRetryTimes(3)//Retry times when operation failed(or timeout) at the first time
.operation(() -> {
//your operation
return "success!";
})
.judgement(t -> (t == null || t.isEmpty()))//add your judgement whether the operation should be retry(Operation should return a value)
.execute();
If you want add retry config annotation on method,and call it:
class RetryTests{
#RetryConfig( maxRetryTimes=1)
public static String TestAnnotation() {
return "aaa";
}
public static void main(String[] args) {
try {
new Retry<String>()
.of(RetryTest.class.getMethod("TestAnnotation"),null)
.judgement(r -> r.equals("aaa"))
.execute();
} catch (NoSuchMethodException | SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}