Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use builder pattern to create exceptions?

I have an exception in my java code that has several properties which would be passed into the constructor. Therefore I thought it would be nice to create an exception with builder pattern so I created the exception like this:

public class ApplicationException extends Exception {

    private static final long serialVersionUID = -8999932578270387947L;

    /** 
     * contains redundantly the HTTP status of the response sent back to the client in case of error, so that
     * the developer does not have to look into the response headers. If null a default 
     */
    Integer status;

    /** application specific error code */
    int code; 

    /** link documenting the exception */   
    String link;

    /** detailed error description for developers*/
    String developerMessage;    

    /**
     * 
     * @param status
     * @param code
     * @param message
     * @param developerMessage
     * @param link
     */
    protected ApplicationException(String message) {
        super(message);
    }

    ...

    public static Builder getBuilder(String message) {
        return new Builder(message);
    }   

    public static class Builder {
        private Integer status;
        private int code; 
        private String link;
        private String message;
        private String developerMessage;     

        public Builder(String message) {
            this.message = message;
        }

        public Builder status(int status) {
            this.status = status;
            return this;
        }


        public Builder code(int code) {
            this.code = code;
            return this;            
        }        

        public Builder developerMessage(String developerMessage) {
            this.developerMessage = developerMessage;
            return this;            
        }    

        public Builder link(String link) {
            this.link = link;
            return this;            
        }

        public ApplicationException build() {
            if (StringUtils.isBlank(message)) {
                throw new IllegalStateException("message cannot be null or empty");
            }

            if (StringUtils.isBlank(link)){
                link = AppConstants.API_SUPPORT_EMAIL;
            }

            ApplicationException created = new ApplicationException(message);
            created.status = status;
            created.code = code;
            created.developerMessage = developerMessage;
            created.link = link;

            return created;
        }        
    }
}

Now I can create an exception like this:

throw ApplicationException.getBuilder("This is the general error message")
    .status(404)
    .code(StatusCode.RESOURCE_DOES_NOT_EXIST)
    .developerMessage("The resource does not exist")
    .build();

The problem that I currently have is that I want to create different exceptions from this base exception. E.g. ValidationException which should extends from ApplicationException.

But the build() method already returns the concrete type ApplicationException. Currently I'm stuck because I'm not that familiar with using generics and if it is even possible within exception classes.

like image 352
daniel Avatar asked May 01 '26 14:05

daniel


2 Answers

You can pass Class<? extends Exception> to your build method, and use newInstance() inside to create the Exception object of the desired type:

throw ExceptionBuilder.getBuilder("This is the general error message")
    .status(404)
    .code(StatusCode.RESOURCE_DOES_NOT_EXIST)
    .developerMessage("The resource does not exist")
    .build(ValidationException.class); // <<== Choose type here

Exception object should not be created until the build call; inside the build you can do this:

Exception build(Class<? extends Exception> eClass) {
    Exception res = null;
    try {
        res = eClass.newInstance();
    } catch (.......) {
        // Catch the appropriate exceptions here
    }
    res.setAbc(); // Set values as needed
    ...
    return res;
}
like image 117
Sergey Kalinichenko Avatar answered May 04 '26 05:05

Sergey Kalinichenko


How many different exception subtypes are you dealing with? If it's not too many, you could just make one build() method in your builder for each exception type:

throw ApplicationException.getBuilder("This is the general error message")
    .status(404)
    .code(StatusCode.RESOURCE_DOES_NOT_EXIST)
    .developerMessage("The resource does not exist")
    .buildValidation();  // or buildSomeOther()

It's not generic but it's very simple and will play nicely with IDE autocomplete

like image 38
Misha Avatar answered May 04 '26 04:05

Misha



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!