javaspringrest

How to control exception while developing RESTful API with Java?


I'm developing RESTful API for our clients.
I'm about to show error information if some error occurs.
The error information protocol look like below.

{ 
    "status": "failure",
    "error": {
        "message": "", 
        "type": "",
        "code": 0000 
    } 
} 

In programming level, how to controll exceptions?
Now I've made custom exception class extending Exception class. (not RuntimeException)
Is this approach good or not? Is it better using RuntimeExcepion?
My custom exception class is ...

public class APIException extends Exception {
    public enum Code {      
        // duplicated exceptions
        ALREADY_REGISTERED(1001),
        
        // size exceptions
        OVER_KEYWORD_LIMIT(2001),
        OVER_CATEGORY_LIMIT(2002),
        TOO_SHORT_CONTENTS_LENGTH(2003),
        TOO_SHORT_TITLE_LENGTH(2004),

        // database exceptions
        DB_ERROR(3001),

        // unregistered exceptions
        UNREGISTERED_NAME(4001),

        // missing information exceptions
        MISSING_PARAMETER(5001),

        // invalid information exceptions
        INVALID_PARAMETER(6001),
        INVALID_URL_PATTERN(6002);

        private final Integer value;
        private Code(Integer value) {
            this.value = value;
        }
        public Integer getType() {
            return value;
        }
    }

    private final Code code;

    public APIException(Code code) {
        this.code = code;
    }
    public APIException(Code code, Throwable cause) {
        super(cause);
        this.code = code;
    }
    public APIException(Code code, String msg, Throwable cause) {
        super(msg, cause);
        this.code = code;
    }
    public APIException(Code code, String msg) {
        super(msg);
        this.code = code;
    }

    public Code getCode() {
        return code;
    }
}

And using APIException class like this...

public void delete(int idx) throws APIException {
    try {
        Product product = productDao.findByIdx(idx);
        if (product.getCount() > 0) {
            throw new APIException(Code.ALREADY_REGISTERED,
                    "Already registered product.");
        }
        productDao.delete(idx);
    } catch (Exception e) {
        throw new APIException(Code.DB_ERROR,
                "Cannot delete product. " + e.getMessage());
    }
}

Which is better make custom exception class or using exist exception like IllegalArgumentException.
If making custom exception class is better, what should I extend among Exception or RuntimeException?
Please recommend me good example like my situation.


Solution

  • Since you're using Spring, I'd recommend:

    1. Extending RuntimeException and letting the exceptions drop through to the controller

    2. If your exception class models the attributes you want to return in your error XML, annotate the exception so it can be returned as a response (including a @ResponseStatus if they all have the same status code).

    3. Implement one or more @ExceptionHandler methods on your controller that returns the exception as the @ResponseBody and ensures the HttpServletResponse is correct. Something like:

      @ExceptionHandler
      @ResponseBody
      public ErrorResponse handleAPIException(APIException e, HttpServletResponse response) {
      // Set any response attributes you need...
          return e; // or some other response
      }