Reputation: 1146
I have a sdr project where I do some basic validation in entity setters and throw a domain exception if model is invalid. I can not get a message source inside the exception so that I can localize the business exception message. Custom exception class I have tried is:
@ResponseStatus(org.springframework.http.HttpStatus.CONFLICT)
public class DoublePriceException extends Exception {
@Autowired
static ReloadableResourceBundleMessageSource messageSource;
private static final long serialVersionUID = 1L;
public DoublePriceException(OrderItem orderItem) {
super(String.format(
messageSource.getMessage("exception.doublePricedItem", null, LocaleContextHolder.getLocale()),
orderItem.name));
}
}
And how I try to throw this mofo is:
public void setPrices(List<Price> prices) throws DoublePriceException {
for (Price price : prices) {
List<Price> itemsPrices = prices.stream().filter(it -> price.item.equals(it.item)).collect(Collectors.toList());
if(itemsPrices.size() > 1)
throw new DoublePriceException(itemsPrices.get(0).item);
}
this.prices = prices;
}
messageSource is always null. Is what I am trying not achievable?
Upvotes: 0
Views: 477
Reputation: 1146
Best I could come up with is catching the HttpMessageNotReadableException
and calling getMostSpecificCause()
like the following:
@RestControllerAdvice
public class ExceptionHandlingAdvice {
@Autowired
private MessageSource messageSource;
@ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<Object> onException(HttpMessageNotReadableException ex, WebRequest request) {
Locale locale = request.getLocale();
Throwable cause = ex.getMostSpecificCause();
String message = cause.getMessage();
if (cause instanceof MultiplePriceException) {
message = messageSource.getMessage("exception.multiple.price",
new Object[] { ((MultiplePriceException) cause).orderItem.name }, locale);
}
return new ResponseEntity(Collections.singletonMap("error", message), new HttpHeaders(),
HttpStatus.BAD_REQUEST);
}
}
Upvotes: 0
Reputation: 23226
DoublePriceException
is obviously not a Spring managed Bean so that is not going to work.
You can register a Spring ControllerAdvice
in your application that handles the exception and generates a suitable response.
/**
* Spring MVC @link {@link ControllerAdvice} which
* is applied to all Controllers and which will handle
* conversion of exceptions to an appropriate JSON response.
*/
@ControllerAdvice
public class ErrorHandlingAdvice
{
/**
* Handles a @DoublePriceException
*
* @param ex the DoublePriceException
*
* @return JSON String with the error details.
*/
@ExceptionHandler(DoublePriceException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public Object processValidationError(DoublePriceException ex)
{
//return suitable representation of the error message
//e.g. return Collections.singletonMap("error", "my error message");
}
}
Placing the above in a package scanned by the Spring framework should be enough to have it detected and applied.
Upvotes: 1