I have functions with the same param and response type like;
public ResponseType functionA(ParamType) throws Exception1
public ResponseType functionB(ParamType) throws Exception1
and I call these functions from different places with the same repeating try/catch block. Is there any way to reduce the duplicate code?
try{
return functionA(obj);
} catch (Exception1 e) { .... }
catch (Exception2 e) { .... }
catch (Exception3 e) { .... }
try{
return functionB(obj);
} catch (Exception1 e) { .... }
catch (Exception2 e) { .... }
catch (Exception3 e) { .... }
I have tried to create a function like below, but I am getting
Exception e1 is never thrown in try block
as expected.
public ResponseType callFunction(Function<ParamType, ResponseType> function, ParamType obj) {
try{
return function.apply(obj)
}catch (Exception1 e) { .... }
catch (Exception2 e) { .... }
catch (Exception3 e) { .... }
}
The issue is that Function.apply is not declared to throw any exceptions, so it is not generally possible to throw checked exceptions from an implementation, or to catch a checked exception from it at a call site. (Ignoring unusual workarounds as mentioned in the comments.)
However, Java does not restrict lambda expressions to only be used with standard functional interfaces, so the best approach when you need to handle specific exception types is to create your own.
#FunctionalInterface
interface MyFunction {
ResponseType apply(ParamType param) throws Exception1, Exception2, Exception3;
}
This can be used in a similar way to java.util.function.Function:
public ResponseType callFunction(MyFunction function, ParamType obj) {
try{
return function.apply(obj);
}
catch (Exception1 e) { throw new RuntimeException("Exception1"); }
catch (Exception2 e) { throw new RuntimeException("Exception2"); }
catch (Exception3 e) { throw new RuntimeException("Exception3"); }
}
(Modified to throw runtime exceptions in the catch blocks so that this will compile)
The calling code is identical to any standard functional interface:
callFunction(this::functionA, obj);
callFunction(this::functionB, obj);
or, equivalently:
callFunction(param -> functionA(param), obj);
callFunction(param -> functionB(param), obj);
Related
I have a code that invokes an external API via EJB and that API occasionally leaks an exception that is not part of the client kit, therefore resulting in ClassNotFoundException.
I have a try-catch block surrounding the call:
try {
thirdPartyLibrary.finalInvokeMethod();
} catch (SomeException exception) {
//Do something
} catch(
..
} catch (Exception exception) {
if (exception instanceof ClassNotFoundException) {
log.error("....");
}
}
I want to avoid using instanceof in catch, but if I add a separate catch clause for ClassNotFoundException, the compiler produces an error "Unreachable catch block", since thirdPartyLibrary.finalInvokeMethod(); doesn't throw ClassNotFoundException.
Is there a better way to address the issue?
I've found a workaround. I've wrapped the thirdPartyLibrary.finalInvokeMethod(); in another method that throws the checked exception. So I got a dedicated catch clause without a compiler error.
private someMethod() {
try {
callExternalAPI();
} catch (SomeException exception) {
//Do something
} catch(
..
} catch (ClassNotFoundException exception) {
log.error("....");
//Do something
} catch (Exception exception) {
//Do something
}
}
private void callExternalAPI() throws ClassNotFoundException {
thirdPartyLibrary.finalInvokeMethod();
}
I have a lot of custom exceptions that I'm throwing in a specific cases in the code, and I'd like to have one catch block at the bottom of the method to handle them all.
All the exceptions are children of the Exception class CribbageException, so I'd like to have:
public void myMethod(){
if (whatever){
throw new CardException();
}
if (something else){
throw new InvalidCardException();
}
if (scenario 3){
throw new TwoCardsException();
}
catch (CribbageException e) {
System.out.println(e.getMessage());
}
}
But I'm getting a catch without try error.
Is there any way to use this type of exception handling?
Wrap all the throws inside a single try.
public void myMethod(){
try {
if (whatever){
throw new CardException();
}
if (something else){
throw new InvalidCardException();
}
if (scenario 3){
throw new TwoCardsException();
}
}
catch (CribbageException e) {
System.out.println(e.getMessage());
}
}
when I debug the below code, there is an SmbException and goes catch block line sb.append(pLogger.reportError(pStr, e));, but it does not go into the method reportError().
what is the reason behind this. please advise if any changes.
try {
sfos = new SmbFileOutputStream(sFile);
} catch (SmbException e) {
sb.append(pLogger.rError(pathStr, e));
}
below is rError() method
public String rError(String pxString,Exception e){
String errorToMailStr=null;
abcd="Verifying # "+pxString+"::Error ["+e.getMessage()+"]";
logger.debug("Error when verifying # "+pxString+":Error ["+gMsg(e)+"]");
return abcd;
}
at line logger.debug("Issue "+pxString+":Error ["+gMsg(e)+"]");
is going to below method and ends.
public abstract class ReflectiveCallable {
public Object run() throws Throwable {
try {
return runReflectiveCall();
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
Based on what you have revealed here, there is a problem in getExceptionMsg()
I'm working on some server-side code that wraps all exceptions before passing them to the client side, due to this all client facing methods have the following code
try{
DoSomething();
} catch (ExceptionA e) {
throw new CustomException(AType, e);
} catch (ExceptionB e) {
throw new CustomException(BType, e);
} catch (Exception e) {
throw new CustomException(Unexpected, e);
}
to have this repeated in every method seems to violate the DRY principle and I was wondering what the best way to refactor it would be. For instance I was thinking a wrapper method such as:
private void wrapException(Exception e) {
if (e instanceof ExceptionA) {
throw new CustomException(AType, e);
}
etc...
Take a look at AspectJ soften exception.
Also look at Guava's Throwables.
There is also Lamboks sneaky exception.
The other option is to use Anonymous object instances aka closures.
public abstract class Wrapper {
public void execute() {
try {
// do some boiler plate before
this.wrap();
// do some boiler plate after.
} catch (ExceptionA | ExceptionB ex) {
Type t = determineType(ex);
throw new CustomException(t, ex);
}
}
public void abstract wrap();
}
Now in your code you do something like:
new Wrapper() {
public void wrap() {
DoSomething();
}
}.execute()
This is possible in Java7 and up:
http://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html
Copy-paste example from above doc:
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
This is one way to go about it:
Exception caughtEx = null;
String extraInfo = null;
try{
DoSomething();
} catch (ExceptionA e) {
caughtEx = e;
extraInfo = AType;
} catch (ExceptionB e) {
caughtEx = e;
extraInfo = BType;
} catch (Exception e) { // catching Exception is usually a bad idea, just let it bubble up without catching...
caughtEx = e;
extraInfo = Unexpected;
}
if (caughtEx != null) throw new CustomException(extraInfo, caughtEx);
What's better between several ChildException catch blocks and one Exception catch block? By better, I mean in a good-practices way.
To illustrate:
public static void main(String[] args) {
System.out.println(Main.isNonsense1(null)); // false <- bad
System.out.println(Main.isNonsense2(null)); // NullPointerException <- good
}
// More readable, less precise
public static boolean isNonsense1(String className) {
try {
Class.forName(className);
String.class.getConstructor(String.class);
className.getBytes("UTF-8");
MessageDigest.getInstance("SHA-1").wait();
return true;
} catch (Exception e) {
return false;
}
}
// Less readable, more precise
public static boolean isNonsense2(String className) {
try {
Class.forName(className);
String.class.getConstructor(String.class);
className.getBytes("UTF-8");
MessageDigest.getInstance("SHA-1").wait();
return true;
} catch (ClassNotFoundException e) {
return false;
} catch (NoSuchMethodException e) {
return false;
} catch (SecurityException e) {
return false;
} catch (UnsupportedEncodingException e) {
return false;
} catch (NoSuchAlgorithmException e) {
return false;
} catch (InterruptedException e) {
return false;
}
}
This is related to this question: Catch multiple exceptions at once?
The answer there is good. The key is that if you catch Exception then you should handle each of the cases that you are aware of and throw all the rest. That is, simply catching Exception in your example and returning false would not be a good idea. You may inadvertently catch some exception you didn't mean to.
Using your example, here is my suggested code:
public static boolean isNonsense2(String className) {
try {
Class.forName(className);
String.class.getConstructor(String.class);
className.getBytes("UTF-8");
MessageDigest.getInstance("SHA-1").wait();
return true;
} catch (Exception e) {
if (e instanceof ClassNotFoundException
|| e instanceof NoSuchMethodException
|| e instanceof SecurityException
|| e instanceof UnsupportedEncodingException
|| e instanceof NoSuchAlgorithmException
|| e instanceof InterruptedException) {
return false;
} else {
throw e;
}
}
}
I think there is no complete clear answer. In your case I would code it like this:
public static boolean isNonsense1(String className) {
if(slassname==null) throw new IllegalArgumentException("className must not be null");
try {
Class.forName(className);
String.class.getConstructor(String.class);
className.getBytes("UTF-8");
MessageDigest.getInstance("SHA-1").wait();
return true;
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("provided class " + className + " not found");
} catch (Exception e) {
return false;
}
}
For my flavor, throwing a NullPointerException is always bad, thats why I throw the IllegalArgumentException
If you are not interested in handling the exception (which you should as per best practices) don't bother with the explicit catches. The whole point of being able to handle specific exceptions is to enable you to handle them correctly.