AutoCloseable-ish method but runs only on catch - java

I would like to two have two different methods running in catch and final blocks. I have found AutoCloseable interface, but I need something to fire in case of exception only.
Like:
SomeService service = CreateService().andOpenTransaction()
try {
service.doSomeMessyThingsInsideDB();
} catch (Exception e) {
service.rollbackTransaction();
throw e;
} finally {
service.closeConnection();
}
Is there any way to make it simpler? As I said I am familiar with AutoCloseable, but it helps me only with finally block. I still cannot use it inside the catch.

Well you could define your own interface, and then some static runner method:
public interface ErrorHandlingCloseable extends AutoCloseable {
void run() throws Exception;
void onError(Exception e);
static void execute(ErrorHandlingClosable ehc) throws Exception {
try(ErrorHandlingClosable temp = ehc) {
ehc.run();
} catch(Exception e) {
ehc.onError(e);
throw e;
}
}
}
Which you then could then call like this:
SomeService service = CreateService().andOpenTransaction();
ErrorHandlingCloseable.execute(new ErrorHandlingCloseable() {
public void run() throws Exception { service.doSomeMessyThingsInsideDB(); }
public void onError(Exception e) { service.rollbackTransaction(); }
public void close() throws Exception { service.closeConnection(); }
});
But you see, it's still messy.
You could even implement this interface in your SomeService but then you're restricted that the run() method will always call doSomeMessyThingsInsideDB().
Another way but still similar would be to use Java8 and create a helper functional interface:
public interface ThrowingRunnable {
void run() throws Exception;
}
And then a static method somewhere:
public static void execute(ThrowingRunnable action,
ThrowingRunnable onCatch,
ThrowingRunnable onFinally) throws Exception {
try(AutoCloseable ao = onFinally) {
action.run();
} catch(Exception e) {
onCatch.run();
throw e;
}
}
The interesting part is probably this: try(AutoCloseable ao = onFinally), which "registers" your onFinally method to be called when finally is reached.
This could then be called like this:
execute(
service::doSomeMessyThingsInsideDB,
service::rollbackTransaction,
service::closeConnection
);

You said you are familiar with AutoCloseable, but you don't use it.
Have you considered using try-with-resources statement?
Your code can be simplified to:
try (SomeService service = CreateService().andOpenTransaction()) {
service.doSomeMessyThingsInsideDB();
} catch(exception e){
service.rollbackTransaction();
throw e;
}
Oracle has great doc for that, including examples.
Note: A try-with-resources statement can have catch and finally blocks just like an ordinary try statement. In a try-with-resources statement, any catch or finally block is run after the resources declared have been closed.
Answering your question, this is as simple as it can get.
If your class doesn't implement Closeable then you can either implement it or use finally.

First step: Handling the exception
You evidently want the exception handled before some close. Then you need inside a try-with-resources to handle the exception.
/** throws RuntimeException */
void process(Callable<Void> work, Consumer<Exception> onFail) {
try {
work.call();
} catch (Exception e) {
onFail(e);
}
}
try (SomeService service = CreateService().andOpenTransaction()) {
process(() -> service.doSomeMessyThingsInsideDB(),
e -> {
service.rollbackTransaction();
throw new IllegalStateException(e);
});
}
This is not very satisfactory, but again also integrating the AutoCloseable, might give too few use-cases.
Second step: with AutoCloseable
<SV extends AutoCloseable> void processAutoClosing(Supplier<SV> serviceFactory,
Callable<Void> work, Consumer<Exception> onFail) {
try (SV service = serviceFactory.get()) {
process(work, onFail);
}
}
processAutoClosing(...);

Related

How to handle Exception properly from a method?

Suppose, I have a method:
private void someMethod() {
try {
//Do something here
}
catch (NullPointerException ex) {
System.out.println("error");
}
}
Now, I want to use this method somewhere else:
private void newMethod() {
someMethod();
JOptionPane.showMessageDialog(null, "Exception didn't occur");
}
Now, I want that if exception occurs in someMethod(), then newMethod() will not advance further, I mean, the JOptionPane message will not be shown in this case.
What will be the best way to do that? I have found a way by throwing another NullPointerException in catch block of someMethod() and then handling that from newMethod(). The code below demonstrates that:
private void someMethod() {
try {
//Do something here
}
catch (NullPointerException ex) {
System.out.println("error");
throw new NullPointerException("error");
}
}
private void newMethod() {
try {
someMethod();
JOptionPane.showMessageDialog(null, "Exception didn't occur");
}
catch (NullPointerException ex) {
System.out.println("error");
}
}
But, by this method, I am facing some difficulties for other cases. I guess there are better ways to achieve that. Thanks anyway.
You don't need to handle the exception inside someMethod. Instead you can declare the exception in this method's throws clause (if it is a checked exception) and let newMethod handle it.
private void someMethod() throws SomeCheckedException {
//Do something here
}
In case of NullPointerException, you don't need to do above, as it is an unchecked exception. Don't catch it inside someMethod, instead have try-catch inside newMethod.
It is good practice if your function intend to throw exception make it part of function declaration. So recommendation is to change someMethod() to private void someMethod() throws <exception Name>.
Depends on your requirement you can handle the exception in same method and throw another exception, or re throw same exception and handle it in another function.
In case you are re-throwing the same exception syntax is as follows:
private void someMethod() throws WhateverException {
try {
//Do something here
}
catch (WhateverException e) {
throw e;
}
}

Java How to "Override" a catch block

I have a method. This method has a catch block.
// pseudo code
private void function() {
try {
// something
} catch(exception e) {
// error handling
}
}
This method is called in another class
In one scenario the class is implemented with its own catch block
// pseudo code
private void anotherFunction() {
try {
function();
} catch {
//another catch block
}
Now I just want to execute the code in the catch block where the function is called and don't call the catch block implemented in the class. Is there a way to do this or should I think about another approach?
A workaround is to move your logic to another method which doesn't handle that exception, but just passes it upwards e.g:
public void unsafeFunction() throws Exception{
// something
}
And then call that method from your both classes, where both handle the exception differently:
public void function(){
try {
unsafeFunction();
} catch(Exception e){
// error handling
}
}
And:
public void anotherFunction(){
try {
unsafeFunction();
} catch(Exception e){
// other error handling
}
}
That way you leave what should be done with the exception to the caller.
Another completly different approach is to use the java.util.function.Consumer interface from Java 8 and accept that in your function, the caller then can just pass the error-handler into it:
public void function(Consumer<? super Exception> errorHandler){
try{
// something
} catch(Exception e){
// delegate to handler
errorHandler.accept(e);
}
}
Which can then be used like this:
public void someFunction(){
function(e -> {
// error handling
});
}
And:
public void anotherFunction(){
function(e -> {
// other error handling
});
}
There must be a reason to catch the exception. Say that reason can be tested in a separate method:
private boolean testCircumstanceThrowingException() {
if (exceptionalCircumstance) {
return false;
} else {
return true;
}
}
then you can implement your original function as:
private void functionCatchingException(){
if (testCircumstanceThrowingException()) {
//error handling
}
function();
}
and
private void anotherFunction() {
if (testCircumstanceThrowingException()) {
//error handling
}
function();
}
this way, during the normal running of the application, no exceptions are thrown. And this is how it should be because exceptions are for exceptional circumstances. If you somehow get to a state where exceptions are expected then something is wrong.
You should only rely on excpetions if there is no other way. For instance, if your specific use of the function cannot test the exceptional circumstance and you're required to use function. Take a look at Lino's answer for possible workarounds.
Java purists will notice that you can simply do return exceptionalCircumstance; but this code was just intended to show that a function that tests for the exceptional circumstance may be required; the result may not even be a boolean.
Of course you may now want to rename functionCatchingException :)
In your first code snippet:
private void function() {
try {
// something
}
catch (Exception e) {
// error handling
throw e; // rethrow?
}
}
you basically have two options with Java. You can either swallow the exception, or you can rethrow it. If you swallow it, then the caller of this method won't see an exception. If you rethrow, then the caller would also get an exception.
If neither of these behaviors are what you really want, then you might want to rethink your design.
You can throw the exception to the caller method using the keyword throw:
private void function(){
try{
//something
} catch(Exception e){
//error handling
throw e;
}
}
Then your anotherFunction() catch block will be executed.
You can learn more from here: The Java Tutorials

Can't add a throws clause to overridden method causing me to have to return null

I am currently working with an AsyncTask and in the doInBackground method runs a piece of code which requires a certain exception to be handled. Since the doInBackground method is overridden, I can't add a throws clause to the method. I have inserted a try-catch method which catches the exception but since my method returns a Summoner object, I had to include a return null; statement and I find my code still executing this statement.
My experience with AsyncTask is pretty limited so if you require more information or I'm overlooking something here, feel free to point it out.
public class GetSummonerData extends AsyncTask<String, Void, Summoner>
{
#Override
protected void onPreExecute()
{
Button button = (Button) findViewById(R.id.btnSearch);
button.setText("Loading...");
}
#Override
protected Summoner doInBackground(String... asyncParams)
{
try
{
String summonerName = asyncParams[1];
RiotApi api = new RiotApi("api-key");
Map<String, Summoner> summoners = null;
//The following line of code will call the API
summoners = api.getSummonersByName(Region.valueOf(asyncParams[0]), summonerName);
//stage 1
return summoners.get(summonerName);
}
catch (RiotApiException e)
{
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Summoner result)
{
//stage 2
startNewIntent(result);
}
}
public void startNewIntent(Summoner summoner)
{
Intent intent = new Intent(this, ProfileActivity.class);
intent.putExtra("summoner", summoner);
startActivity(intent);
}
At stage 1, the summoners variable holds 1 Summoner object. At stage 2 the returned result in onPostExecute equals null. Why is the return null executed even though there is a return statement within the try block?
The reason return null is executed is because an exception has been thrown during the try-catch block. This causes all remaining execution of the try block to be aborted (including the return statement) and the catch block to be executed instead.
Once the catch block exits the return null after it is then executed since execution continues as normal.
Try this simple code:
public class Class1 {
public Class1() {
super();
}
public String fetchString(int i) {
try {
int j = 1/i;
return "passed";
}
catch(Exception ex) {
ex.printStackTrace();
}
return null;
}
public static void main(String[] args) {
Class1 class1 = new Class1();
System.out.println(class1.fetchString(1));
System.out.println(class1.fetchString(0));
}
}
You will realize that when exception is thrown, it is caught, and hence the return statement in "Try" block is never called/executed. (exception is thrown at 1/i when i =0).
Same is happening with your code.
Regarding your other observation, you can't add any new exception to the method you are implementing of interface. Check following example.
public interface myinterface
{
public void foo();
}
Now consider this
public class Ximpl implements myinterface
{
public void foo() throws IOException
{
}
}
Now if client has a code like
myinterface varx = new Ximpl();
//he can do that
varx.foo(); //without putting it in try catch block. (Remember polymorphism)??
If you really want to throw an exception in catch block, create an instance of Runtime Exception, which need not to be declared.
You can use this trick, Wrap the exception in a RuntimeException and rethrow it. Like this
try {
Files.createDirectories(Paths.get(""));
} catch (IOException ex) {
throw new RuntimeException(ex);
}
In this way you don't need to return null.
You can even create your own version of exception that extends RuntimeException. That way you don't need to add it to method signatures and don't force other to catch it. Just like this
public class MyValidationException extends RuntimeException {
}

Java: Is it possible to make try/catch shorter?

For example:
try {
Thread.sleep(333);
} catch (InterruptedException e) {
e.printStackTrace();
}
can I use the above try/catch in some kind of way using a created method like trySleep(Thread.sleep(333)); that'll do the exact same as the original try?
A example of use:
public class Test implements Runnable {
public Test() {
Thread thisThread = new Thread(this);
thisThread.start();
}
#Override
public void run() {
while (true){
System.out.println("Testing");
trySleep(Thread.sleep(333));
}
}
public void trySleep(/*Thread object*/){
//Code for try/catch
}
public static void main(String[] args) {
new Test();
}
}
Of course the above code won't compile, it's just for the question.
The reason I want this kinda thing is because I find the try/catch things to be so messy and is quiet annoying to read.
You could wrap Thread.sleep in a function that re-throws any exception as a runtime exception (or any uncaught exception).
public static void trySleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted during sleep", e);
}
}
I don't get the question. If you add the three lines into the trySleep-method Body, you get a method, which will let the Thread sleep.
So the answer is yes.
By the way:
You wrote an endless sleeping loop
Yes, you can do this, but not exactly the way you describe it now. Wherever you use Thread.sleep() you will have to catch InterruptedException, so you would have to enclose the call in the method like this:
public void trySleep(long ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
e.printStackTrace(); //handle exception here
}
}
You can call this method like this: trySleep(333)
It is sometimes better to just add a throws declaration to your method though or to re-throw a more meaningful exception, unless you know that this is the location where it makes most sense to catch the exception.
You could wrap your sleeping code in another method as you sugested.
public static void trySleep(Thread target, long millis){
try{
target.sleep(millis);
} catch(InterruptedException e) {
System.err.println("Exception Occurred while trying to sleep!");
}
}
You probably shoud do this, in fact, as making code modular is the right way to go.
One important thing I think you really need to consider (in addition to the answers to how to do this properly), is to understand what code you're calling.
In your code:
#Override
public void run() {
while (true){
System.out.println("Testing");
trySleep(Thread.sleep(333));
}
}
Particularly this line:
trySleep(Thread.sleep(333));
You're basically saying
Call the method Thread.sleep() with a value of 333.
Whatever value Thread.sleep() returns, pass that to another method.
But the Javadocs say it's a void method.
Also in your code:
public void trySleep(/*Thread object*/){
//Code for try/catch
}
You should check this stackoverflow post out for why this is not good practice (as you'll be trying to invoke a static method on an instance object).
Others have answered your question on this, but I highly recommend brushing up on these areas as it indicates you may likely be missing critical knowledge of some important concepts.
You can use java 8's lambda expressions to do something similar to this:
#FunctionalInterface
interface InterruptedExceptionRunnable {
void run() throws InterruptedException;
}
void trySleep(InterruptedExceptionRunnable exRunnable) {
try {
exRunnable.run();
} catch(InterruptedException ex) {
ex.printStackTrace();
}
}
which allows you to write this:
trySleep(()->Thread.sleep(333));
Yes, you can do basically this with Java 8 lambdas.
class Example {
#FunctionalInterface
interface InterruptableRunnable {
void run() throws InterruptedException;
}
static void tryRun(InterruptableRunnable r) {
try {
r.run();
} catch(InterruptedException ie) {
ie.printStackTrace();
}
}
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
// passing a lambda
tryRun( () -> Thread.sleep(333) );
}
});
t.start();
// passing a method reference
tryRun(t::join);
}
}

Is there a standard JDK interface which a method like void run() throws Exception?

What I want is a standard JDK class that look like this:
interface ExplodingRunnable {
void run() throws Exception;
}
Callable is no good, because its call() method is required to return a value, but I need a void.
Runnable is no good, because its run() method doesn't declare throws Exception.
I sort of need a combination of the two. Any ideas?
EDIT: I should have mentioned that I tried Callable<Void> but it requires you to define a method:
public Void call() {
// run your code;
return null; // ugly!
}
I'm looking for something a bit nicer.
Why do I want this?
I'm implementing a standard why of catching "will never happen" Exceptions (they will never happen, but various APIs define their methods throwing Exceptions) and throwing any Exceptions that might occur by wrapping them in an (unchecked) RuntimeException, so the caller can simply pass a "ExplodingRunnable" in and not have to code loads of perfunctory try/catch blocks that will never be exercised.
FINAL EDIT It looks like what I was looking for doesn't exist. The accepted answer is the closest to "correct", but it looks like there is no solution to answer the question as asked.
Could you just use Callable<Void>?
An interface with only one method, which returns void and throws Exception.
Among all java and javax classes, only one fits that description:
package java.lang;
public interface AutoCloseable
{
void close() throws Exception;
}
Well... the word "close" has many meanings...
You want to surround a bunch of statements with some extra handling, there is no sin to define your own interface here. You may find that your API requires users to learn 4 new phrases
Util.muckException( new ExplodingRunnable() { public void run() throws Exception
^1 ^2 ^3 ^4
You can actually cut down two, and user code would look like this
new MuckException(){ public void run() throws Exception
{
statement_1;
...
statement_n;
}};
public abstract class MuckException
{
public abstract run() throws Exception;
public MuckException()
{
try{ run(); }
catch(Exception e){ throw new Error(e); }
}
}
Just use Callable, ignore the return value and document things as ignoring the returned value and recommend returning null. Just because you can return something does not mean you have to.
I would just use Callable<Void> and learn to love it. ;)
You can have the checked exception not declared with the following.
Runnable runs = new Runnable() {
public void run() {
try {
// do something
} catch(Exception e) {
// rethrows anything without the compiler knowing.
// the method is deprecated but can be used on the current thread.
Thread.currentThread().stop(e);
}
}
});
Future future = executorService.submit(run);
try {
future.get();
} catch (ExecutionException ee) {
Throwable e = ee.getCause(); // can be the checked exception above.
}
and not have to code loads of perfunctory try/catch blocks that will never be exercised.
I had the same issue and fixed it a little differently
// Exceptions class
public RuntimeException wrap(Exception e) {
return e instanceof RuntimeException ? ((RuntimeException)e) : new RuntimeException(e);
}
// user code
try {
foo.bar();
} catch (Exception e) {
throw Exceptions.wrap(e);
}

Categories

Resources