Executing code after exception is thrown - java

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}
}

Related

Constructor in the Try/Catch block

The question is about the result of the below code. The answer is compilation error. However I really do not understand why we can't have constructor in try/catch block. I will put the the code below:
public class Test {
try {
public Test() {
System.out.println("GeeksforGeeks");
throw new Exception();
}
}
catch(Exception e) {
System.out.println("GFG");
}
public static void main(String [] args) {
Test test= new Test();
}
}
Because the assignments are statements and statements are allowed only inside blocks of code(methods, constructors, static initializers, etc.)
here's the clean code
public class Test {
public Test()throws Exception {
System.out.println("GeeksforGeeks");
throw new Exception();
}
public static void main(String [] args) {
try {
Test test= new Test();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Because a constructor is a declaration, not a statement.
Your constructor can be called by other code, but merely declaring it does not execute it; that’s what new Test() does. Nothing is executed merely by declaring the constructor, so there is nothing that can throw an exception. Thus, there is nothing to catch.
In more general syntax terms, statements which don’t evaluate to a value can only exist in constructors, methods, and initialization blocks.
You can, however, do this:
public static void main(String[] args) {
try {
Test test = new Test();
} catch (Exception e) {
System.out.println(e);
}
}
new Test() actually executes the constructor, which is why it may throw an exception and thus you can legally attempt to catch any exception it may throw. Syntactically, all of the above code is inside a method (the main method), which is allowed.

Unchecked ThrowingSupplier for lambdas

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();
}
}

Inheritance and Try-With-Resources

Suppose there are two classes implementing AutoCloseable Interface as below:
public class Closing1 implements AutoCloseable {
private boolean closed;
#Override
public void close() throws Exception {
if (closed) {
throw new Exception("Closed Already");
}
this.closed = true;
System.out.println("Closing1 closed");
}
public boolean isClosed() {
return closed;
}
}
and
public class Closing2 implements AutoCloseable {
private Closing1 cl1;
public Closing2(Closing1 cl1) {
this.cl1 = cl1;
}
#Override
public void close() throws Exception {
if(!cl1.isClosed()) {
throw new Exception("Closing1 not closed");
}
System.out.println("Closing2 closed");
}
}
I find that all variations with try with resources lead to an exception! Is there something I am missing here, or is it just the way TWR is designed?
try(Closing1 c1 = new Closing1();Closing2 c2 = new Closing2(c1)){
System.out.println("Done");
} //Exception while auto closing C2
or
try(Closing1 c1 = new Closing1();Closing2 c2 = new Closing2(c1)){
System.out.println("Done");
c1.close();
} // exception while auto closing c1
Try-with-resources will close the resources in the opposite order of their declaration. This means that c2.close() will be called first, which will throw the exception as you have coded it.
Start with try-with-resources first, https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
As the very first example shows already:
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
people will not necessarily name everything in the chain.
Unless you explicitly need c1 for something (other than closing), in real life your snippet would rather look like
try(Closing2 c2 = new Closing2(new Closing1())){
System.out.println("Done");
}
and you would not call c1.close() in the try-block for sure, as there would be no c1 at all.
Keeping this in mind, throwing an exception from c2 because the contained c1 is not closed, is totally wrong, actually c2 owns the Closing1 object and should invoke close() on it:
class Close1 implements AutoCloseable {
#Override
public void close() throws Exception {
System.out.println("Closing c1");
}
}
class Close2 implements AutoCloseable {
Close1 c1;
Close2(Close1 c1) {
this.c1=c1;
}
#Override
public void close() throws Exception {
System.out.print("Closing c1 from c2: ");
c1.close();
System.out.println("Closing c2");
}
}
void test() {
System.out.println("Before try block");
try(Close2 c2=new Close2(new Close1())) {
System.out.println("In try block");
}
catch(Exception ex) {
System.out.println("Exception: "+ex);
}
finally {
System.out.println("In finally block");
}
System.out.println("After try block");
}
However, if someone gives a name to c1, it will be closed twice, that is where the idempotency comes into the picture, as suggested by someone already:
System.out.println("Before try block");
try(Close1 c1 = new Close1(); Close2 c2 = new Close2(c1)){
System.out.println("In try block");
}
catch(Exception ex){
System.out.println("Exception: "+ex);
}
finally{
System.out.println("In finally block");
}
System.out.println("After try block");
As BufferedReader was mentioned already, this is the close() method it has:
public void close() throws IOException {
synchronized (lock) {
if (in == null)
return;
try {
in.close();
} finally {
in = null;
cb = null;
}
}
}
If it has in, it gets closed, and nulled (in a finally block, so it happens even if an exception occurs), and all in a thread-safe block. (cb is just an array of characters, it gets null-ed too, simplifying the life of the garbage collector a little). Because of nulling everything in the finally block, any extra calls to this same method will not do anything (apart from synchronizing on the lock for a moment).

Handle Exception after all lines have been finished execution without finally

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.

Synchronizing infinitely looped service's initialization part

I'm trying to implement a piece of code to synchronously start looped service in Java. The idea is, code under // STARTER comment should be considered as piece of Service.go() method, so if service fails to start, I want to re-throw the exception synchronously. That piece of code should only finish in case I've tried to start the thread, waited until its execution flow reached some point and next, if there are no problems, my go() method quits and thread goes on, or, if there were problems, I can re-throw the exception caught in thread's run() method from my go() method. Here's the solution that seems to work fine, but I'm curious if it's possible to make it a couple times shorter :-)
public class Program {
private static boolean started;
private static Throwable throwable;
public static void main(String[] args) {
final Object startedSetterLock = new Object();
Thread thread = new Thread() {
public void run() {
System.out.printf("trying to start...\n");
boolean ok;
Throwable t = null;
try {
init();
ok = true;
} catch(Exception e) {
ok = false;
t = e;
}
synchronized(startedSetterLock) {
started = ok;
throwable = t;
startedSetterLock.notifyAll();
}
if(!ok) {
return;
}
while(true) {
try {
System.out.printf("working...\n");
Thread.sleep(1000);
} catch(InterruptedException e) {
System.out.printf("interrupted\n");
}
}
}
private void init() throws Exception { throw new Exception(); } // may throw
};
// STARTER
synchronized(startedSetterLock) {
thread.start();
try {
startedSetterLock.wait();
} catch(InterruptedException e) {
System.out.printf("interrupted\n");
}
}
// here I'm 100% sure that service has either started or failed to start
System.out.printf("service started: %b\n", started);
if(!started) {
throwable.printStackTrace();
}
}
}
And also, there's a reason to have initialization code executed within that thread, so, please, don't advise running initialization code explicitly in go() method and then just passing all the stuff to the thread.
Thanks!
How about overriding the Thread.start() method?
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
while (true) {
try {
System.out.printf("working...\n");
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.printf("interrupted\n");
}
}
}
#Override
public synchronized void start() {
try {
init();
} catch (Exception e) {
throw new RuntimeException(e);
}
super.start();
}
private void init() throws Exception {
throw new Exception("test");
}
};
t.start();
}

Categories

Resources