filpa
filpa

Reputation: 3604

Custom Exception Dispatcher in Spring Boot Application for response logic

I have a Spring Boot application that has the following approximate structure:

Api is an interface that looks like this:

public interface Api {
    public String methodOne(...) throws ExceptionOne, ExceptionTwo, ExceptionThree;

    ... 

    public int methodN(...) throws ExceptionOne, ExceptionThree, ExceptionFour;
}

ApiImpls is the request controller (in reality there is a second layer, but this should suffice for this example). There, I do something like the following right now:

@Controller
public class ApiImpl {

    public String methodOne(...) {

        try {
            // do stuff that can yield an exception
        }
        catch(ExceptionOne e) {
            // set proper response code and return values
        }
        catch(ExceptionTwo e) {
            // set proper response code and return values
        }
        catch(ExceptionThree e) {
            // set proper response code and return values
        }
    }
}

Basically, this behaviour yields a lot of repetition (might as well name my exceptions D, R, and Y...), but is otherwise very suited to handling the internal application logic.

My question is: How can I implement a custom Exception Dispatcher that would handle this in Java? Ideally, I would want something like this answer here, but unfortunately simply throwing the current exception like in that C++ code is not possible in Java, as far as I know. For brevity, what I would like to accomplish is something like the following:

@Controller
public class ApiImpl {

    public String methodOne(...) {

        try {
            // do stuff that can yield an exception
        }
        catch(ExceptionOne e) {
            handle()
        }
    }

    private void handle() { // maybe Throwable or Exception subclass as parameter
      // handle the correct exception type, set correct response code, etc.
    }
}

Are there any good approaches to doing this so as to minimize code repetition?


Here is a preliminary attempt I tried to get this working:

public class Thrower {

    public Thrower(int e) throws ExceptionOne, ExceptionTwo, ExceptionThree {
        if(e == 0) {
            throw new ExceptionOne();
        }
        if(e == 1) {
            throw new ExceptionTwo();
        }
        if(e == 2) {
            throw new ExceptionThree();
        }
    }
}

class ExceptionOne extends Exception {}
class ExceptionTwo extends Exception {}
class ExceptionThree extends Exception {}

public class ExceptionHandler {

    private void handle(Exception ex) throws Exception  {
        try {
            throw ex;
        }
        catch(ExceptionOne e) {
            e.printStackTrace();
            System.out.println("Exception one");
        }
        catch(ExceptionTwo e) {
            e.printStackTrace();
            System.out.println("Exception two");
        }
        catch(ExceptionThree e) {
            e.printStackTrace();
            System.out.println("Exception three");
        }
    }

    public void causesException(int which) throws Throwable {
        try {
            Thrower t = new Thrower(which);
        }
        catch(Exception e) {
            handle(e);
        }
    }

    public static void main(String[] args) throws Throwable {
        ExceptionHandler eh = new ExceptionHandler();

        eh.causesException(0);
        eh.causesException(1);
        eh.causesException(2);

    }
}

This works as expected, and I can handle the different exception types as needed (shown here using a constructor, but the principle would be the same). However, this feels extremely clunky.

Upvotes: 1

Views: 780

Answers (1)

Vasu
Vasu

Reputation: 22384

If you are looking for globally handling all Controller Layer exceptions (in Spring MVC architecture), you can do that at one place for all controllers (option1 below) by using @ExceptionHandler methods which is a ControllerAdvice from Spring.

Option(1): Configure Exceptions in Separate Class

@ControllerAdvice
class MyProjectExceptionHandler {

   @ExceptionHandler(value = ExceptionOne.class)
   public R exceptionOne(ExceptionOne exe) {
      //set proper response code and return values
   }

   @ExceptionHandler(value = ExceptionTwo.class)
   public R exceptionTwo(ExceptionTwo exe) {
      //set proper response code and return values
   }
}

Option(2): Configure Exceptions in Controller Class itself

If you are looking for handling the exceptions within the Controller class itself, then you can do that as below:

@Controller
public class ApiImpl {

    public String methodOne(...) {

    }

    @ExceptionHandler(ExceptionOne.class)
    public R exceptionTwo(ExceptionOne exe) {
      //set proper response code and return values
   }

   //other exceptions
  }

You can look more on this at here

Upvotes: 3

Related Questions