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.
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;
}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With