How can I refactor below catch block I am using java11
Code
public String methodName(ClassRequest request, Destination ABC) {
try {
<Some Code Here>
} catch (Exception e) {
log.error("error", ABC, e);
if(e instanceof ABCRestException ||
(ABC == PREM && (e instanceof HttpServerErrorException || e instanceof HttpClientErrorException))) {
throw e;
} else if(e instanceof HttpServerErrorException) {
throw new ABCRestException(request.getAId(), "unexpected_error", "Some Message", e, INTERNAL_SERVER_ERROR);
} else if(e instanceof HttpClientErrorException) {
throw new ABCRestException(request.getAId(), "missing_field", "Some Message", e, BAD_REQUEST);
} else {
throw new ABCRestException(request.getAId(), "unexpected_error", "Some Massage", e, INTERNAL_SERVER_ERROR);
}
}
}
How I can refactor this code Means catch block
you just need two catch blocks like this
public String methodName(ClassRequest request, Destination ABC) {
try {
<Some Code Here>
} catch (HttpServerErrorException e) {
log.error("error", ABC, e);
if (ABC == PREM){
throw e;
}else{
throw new ABCRestException(request.getAId(), "unexpected_error", "Some Message", e, INTERNAL_SERVER_ERROR);
}
} catch (HttpClientErrorException e){
if (ABC == PREM){
throw e;
}else{
throw new ABCRestException(request.getAId(), "missing_field", "Some Message", e, BAD_REQUEST);
}
}
}
If you want to reuse some logic, you can write a private method and invoke it inside the catch block
If two or more exceptions share the same exact logic you can also use a multi-catch which will catch various exceptions in the same block
try{
codeGoesVroomVroomAndThrows()
}catch(ExceptionA | ExceptionB e){
//do something
}
Related
private WebElement findElementByXpath(WebDriver driver, String xpath) throws WebElementNotFoundException, HopelessAccountException {
WebElement element = null;
try {
element = new WebDriverWait(driver, Duration.ofSeconds(dirationInSeconds))
.until(ExpectedConditions.elementToBeClickable(By.xpath(xpath)));
} catch (TimeoutException timeoutException) {
loggingService.timeMark("findElementByXpath", "TimeoutException");
throw new WebElementNotFoundException();
} catch (UnhandledAlertException alertException) {
loggingService.timeMark("findElementByXpath", "alertException");
final String LIMITS_EXHAUSTED_MESSAGE = "Not enough limits!";
String message = alertException.getMessage();
if (message.contains(LIMITS_EXHAUSTED_MESSAGE)){
throw new HopelessAccountException(); // Attention.
}
} catch (Exception e) {
// Mustn't be here.
loggingService.timeMark("findElementByXpath", e.getMessage());
driver.quit();
System.out.println("QUIT!");
System.exit(0);
}
loggingService.timeMark("findElementByXpath", "end. Xpath: " + xpath);
return element;
}
Please, have a look at the line that I commented as "Attention".
I have caught the exception where there is not enough limits any more. And I throw the exception that the account is hopeless.
But it is immediately caught by just after the next few lines. Namely where I commented "Mustn't be here".
I would like to preserve this catching any exception. At least for debugging purpose.
Could you help me understand whether I can both throw HopelessAccountException and preserve the "catch Exception" block?
You can always modify your Exception block to rethrow e if it is an instance of HopelessAccountException:
} catch (Exception e) {
if (e instanceof HopelessAccountException) throw e; // preserves original stack trace
// Mustn't be here.
loggingService.timeMark("findElementByXpath", e.getMessage());
driver.quit();
System.out.println("QUIT!");
System.exit(0);
}
However as #fishinear indicates, in your posted code the Exception block would not be reached as a result of the throw of throw new HopelessAccountException() - if your actual code looked more like:
try {
try {
System.out.println("In A()");
// do something to cause an exception E3 (e.g. UnhandledAlertException)
throw new E3();
} catch (E3 e3) { // UnhandledAlertException
System.out.println("In E3 catch");
throw new E1(); // HopelessAccountException
}
} catch (Exception e) {
System.out.println("In Exception catch");
if (e instanceof E1) throw e; // rethrow HopelessAccountException
System.out.println("e: "+e);
}
Then the test-and-rethrow is possible.
Then when you rip out your debugging "try block" your code would behave the same (for the HopelessAcountException).
in your code that calls findElementByXpath(…) you could catch the broad Exception type there. This means in your findElementByXpath(…) method you could just handle the known exceptions and anything else could be captured in calling code
I’m using Javassist (3.25.0-GA) and Java 8 with a custom Agent to transform bytecode and add print statements to existing catch{} clauses. This works for simple cases, but has a problem with the compiled bytecode of the try-with-resources syntax.
Here is a basic example of what I'm trying to do and the results when it works correctly on standard try/catch blocks:
// before byte code manipulation
public void methodWithCatchClause() {
try {
throwsAnException();
} catch (Exception ex) {
handleException(ex);
}
}
// after byte code manipulation
public void methodWithCatchClause() {
try {
throwsAnException();
} catch (Exception ex) {
System.out.println("CATCH CLAUSE!"); // added by Javassist
handleException(ex);
}
}
The logic I'm using to transform the bytecode is inspired by another SO post [0]:
// from https://stackoverflow.com/questions/51738034/javassist-insert-a-method-at-the-beginning-of-catch-block
ControlFlow cf = new ControlFlow(ctMethod); // ctMethod == methodWithCatchClause()
for (ControlFlow.Block block : cf.basicBlocks()) {
ControlFlow.Catcher catchers[] = block.catchers();
for (int i = 0; i < catchers.length; i++) {
ControlFlow.Catcher catcher = catchers[i];
ControlFlow.Block catcherBlock = catcher.block();
int position = catcherBlock.position();
int lineNumber = ctMethod.getMethodInfo().getLineNumber(position);
ctMethod.insertAt(lineNumber + 1, "System.out.println(\"CATCH CLAUSE!\");");
}
}
But this code breaks in conjunction with the try-with-resources syntax. As a concrete example this code:
public void tryWithResources() {
try (TestAutoClosable test = new TestAutoClosable()) {
test.doStuff();
} catch (Exception ex) {
handleException(ex);
}
}
Turns into this after code generation:
public void tryWithResources() {
try {
TestAutoClosable test = new TestAutoClosable();
Throwable var2 = null;
try {
System.out.println("CATCH CLAUSE!");
test.doStuff();
} catch (Throwable var12) {
var2 = var12;
throw var12;
} finally {
if (test != null) {
if (var2 != null) {
try {
test.close();
} catch (Throwable var11) {
var2.addSuppressed(var11);
}
} else {
test.close();
}
}
}
} catch (Exception var14) {
System.out.println("CATCH CLAUSE!");
System.out.println("CATCH CLAUSE!");
System.out.println("CATCH CLAUSE!");
// this goes on for 15 more entries...
this.handleException(var14);
}
}
This of course is causing "CATCH CLAUSE!" to be printed multiple times in odd places. It might be helpful to mention that empty catch clauses, regardless of try/catch syntax, break in a similar fashion (maybe the underlying cause is related?).
I would expect something closer to this as the end result:
public void tryWithResources() {
try {
TestAutoClosable test = new TestAutoClosable();
Throwable var2 = null;
try {
test.noop();
} catch (Throwable var12) {
System.out.println("CATCH CLAUSE!");
var2 = var12;
throw var12;
} finally {
if (test != null) {
if (var2 != null) {
try {
test.close();
} catch (Throwable var11) {
var2.addSuppressed(var11);
}
} else {
test.close();
}
}
}
} catch (Exception var14) {
this.handleException(var14);
}
}
I'm trying to figure out if I have a simple error in my code or if my approach is entirely wrong. I would appreciate any help with the matter. Thanks in advance.
[0] Javassist: insert a method at the beginning of catch block
How can I evaluate an exception? I mean this:
try{
catch(Exception ex){
if(ex == IOException){ //Error
System.out.println("IOException caught: " + ex.toString());
}
else if(){
}
....
}
I known there are other ways to achieve this. I just want to know if it's possible to compare an Exception "ex" to a defined Exception such as IOException.
The best practice would be to add different catch statements for each Exception you need to catch, in inverted class hierarchy order (narrower to broader).
try {
// TODO
}
catch(IOException ioe) {
}
catch(Exception e) {
}
Otherwise, you can always use instanceof.
catch(Exception ex) {
if (ex instanceof IOException) {
}
}
Notes
The latter can be slightly more useful with Java 7 styled multiple-exception catch blocks, e.g. catch (IOException | PatternSyntaxException ex).
As Codebender mentions, you can match the exact class instead of using instanceof by employing the following idiom:
if (ex.getClass().equals(IOException.class)).
The instanceof keyword is more powerful than exact class comparison, but may perform slower.
For instance, new FileNotFoundException() instanceof IOException returns true, because FileNotFoundException is a child class of IOException.
You can do more than one catch statements:
try
{
//code
}catch(IOException e)
{
//Code
}
catch (NoSuchFieldException e) {
//Code
}
....
Also, you can do it like this:
try {
//Code
} catch( IOException | NoSuchFieldException ex ) {
//Code
}
If you want to use the same code with more than one catch exceptions.
I expect it will be helpful for you!
You can use the instanceof operator. But keep in mind that you will check from the most specific to the most general.
Because a FileNotFoundException is also an IOException.
try{
//do stuff
}catch(Exception ex){
if(ex instanceof FileNotFoundException){
System.out.println("FileNotFoundException caught: " + ex.toString());
}else if(ex instanceof IOException){
System.out.println("IOException caught: " + ex.toString());
}
}
But a cleaner solution will be
try{
//do stuff
}catch(IOException ioe){
//handle IOException
}catch(Exception e){
//handle Exception
}
Is it possible to catch all exceptions of a method, except for a specific one, which should be thrown?
void myRoutine() throws SpecificException {
try {
methodThrowingDifferentExceptions();
} catch (SpecificException) {
//can I throw this to the next level without eating it up in the last catch block?
} catch (Exception e) {
//default routine for all other exceptions
}
}
/Sidenote: the marked "duplicate" has nothing to do with my question!
void myRoutine() throws SpecificException {
try {
methodThrowingDifferentExceptions();
} catch (SpecificException se) {
throw se;
} catch (Exception e) {
//default routine for all other exceptions
}
}
you can do like this
try {
methodThrowingDifferentExceptions();
} catch (Exception e) {
if(e instanceof SpecificException){
throw e;
}
}
Suppose I have a class defining a big block of work to be done, that can produce several checked Exceptions.
class WorkerClass{
public Output work(Input input) throws InvalidInputException, MiscalculationException {
...
}
}
Now suppose I have a GUI of some sort that can call this class. I use a SwingWorker to delegate the task.
Final Input input = getInput();
SwingWorker<Output, Void> worker = new SwingWorker<Output, Void>() {
#Override
protected Output doInBackground() throws Exception {
return new WorkerClass().work(input);
}
};
How can I handle the possible exceptions thrown from the SwingWorker? I want to differentiate between the Exceptions of my worker class (InvalidInputException and MiscalculationException), but the ExecutionException wrapper complicates things. I only want to handle these Exceptions - an OutOfMemoryError should not be caught.
try{
worker.execute();
worker.get();
} catch(InterruptedException e){
//Not relevant
} catch(ExecutionException e){
try{
throw e.getCause(); //is a Throwable!
} catch(InvalidInputException e){
//error handling 1
} catch(MiscalculationException e){
//error handling 2
}
}
//Problem: Since a Throwable is thrown, the compiler demands a corresponding catch clause.
catch (ExecutionException e) {
Throwable ee = e.getCause ();
if (ee instanceof InvalidInputException)
{
//error handling 1
} else if (ee instanceof MiscalculationException e)
{
//error handling 2
}
else throw e; // Not ee here
}
You could use an ugly (smart?) hack to convert the throwable into an unchecked exception. The advantage is that the calling code will receive whatever exception was thrown by your worker thread, whether checked or unchecked, but you don't have to change the signature of your method.
try {
future.get();
} catch (InterruptedException ex) {
} catch (ExecutionException ex) {
if (ex.getCause() instanceof InvalidInputException) {
//do your stuff
} else {
UncheckedThrower.throwUnchecked(ex.getCause());
}
}
With UncheckedThrower defined as:
class UncheckedThrower {
public static <R> R throwUnchecked(Throwable t) {
return UncheckedThrower.<RuntimeException, R>trhow0(t);
}
#SuppressWarnings("unchecked")
private static <E extends Throwable, R> R trhow0(Throwable t) throws E {
throw (E) t;
}
}
Try/multi-catch:
try {
worker.execute();
worker.get();
} catch (InterruptedException e) {
//Not relevant
} catch (InvalidInputException e) {
//stuff
} catch (MiscalculationException e) {
//stuff
}
Or with the ExecutionException wrapper:
catch (ExecutionException e) {
e = e.getCause();
if (e.getClass() == InvalidInputException.class) {
//stuff
} else if (e.getClass() == MiscalculationException.class) {
//stuff
}
}
Or if you want exceptions' subclasses to be treated like their parents:
catch (ExecutionException e) {
e = e.getCause();
if (e instanceof InvalidInputException) {
//stuff
} else if (e instanceof MiscalculationException) {
//stuff
}
}