简体   繁体   中英

why Exception Constructor is called instead of IOException Constructor?

Below is a java class, named AuthentificationResourceException , which extends Exception and having 2 overloaded constructors. For simplicity, this exception will be thrown when the user call verifyToken method situated in a Controller class.

 public class AuthentificationResourceException extends Exception{

    // Exception constructor
    public AuthentificationResourceException(Exception cause, VerifyTokenResponse response) {
            handleException(response, "Exception verifyToken method");
        }

    // IOException constructor
    public AuthentificationResourceException(IOException cause, VerifyTokenResponse response) {
        handleException(response, "Probleme of reading / writting");
    }

    public void handleException(VerifyTokenResponse response, String messageException) {
        response.setValid(false);
        response.setCause(messageException);
    }

In the controller class, I used @ExceptionHandler annotation to manage unhandled exceptions thrown by verifyToken method :

@Controller
@RequestMapping(value = "/authentification", method = RequestMethod.POST, consumes = "application/json", produces = "application/json"){
public class AuthentificationRessource {



            @RequestMapping(value = "/verifyToken", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
            @ExceptionHandler({ AuthentificationResourceException.class })
            @ResponseBody
            public VerifyTokenResponse verifyToken(@RequestBody VerifyTokenRequest request)
                    throws AuthentificationResourceException {

                JWTVerifier verifier = new JWTVerifier("TOTO");
                VerifyTokenResponse response = new VerifyTokenResponse();

                try {
                    Map<String, Object> mapper = verifier.verify(request.getToken());
                    response.setMapper(mapper);
                    response.setValid(true);
                } catch (Exception e) {
                    // map exceptions with ExceptionHandler
                    throw new AuthentificationResourceException(e, response);
                }
                return response;
            }

}

When I used, Junit to test verifyToken method, I encounter a problem :

  1. When the exception is null and of type IOException , the system invoke the second constructor IOException constructor
  2. When the exception is not null and instance of IOException , the system invoke the first constructor Exception constructor instead of IOException constructor .

What is the reason ?

In Java, overloaded methods are are resolved at compile time. So in the catch clause, the function can be any exception according to its compile-time type, therefore java resolved the function call to the first constructor.

The null case is interesting. That's just java resolving to the most specific constructor when it can't determine the objects input type.

One way to solve this would be a runtime type check.

  public AuthentificationResourceException(Exception cause, VerifyTokenResponse response) {
      if (cause instanceof IOException) {
         handleException(response, "Problem reading / writing");
      } else {
         handleException(response, "Exception verifyToken method");
      }
  }

Another option would be to explicitly catch the IOException separately so java will know what method to call.

try {
   ...
} catch(IOException e) {
   throw new AuthentificationResourceException(e, response);
} catch (Exception e) {
   throw new AuthentificationResourceException(e, response);
}

It was an interesting idea to try and overload there but unfortunately the java type system doesn't allow runtime overloading.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM