Eu me deparei com esse problema e executei as etapas abaixo para reutilizar o meu ExceptionController
que está anotado @ControllerAdvise
para Exceptions
inserido em um filtro registrado.
Obviamente, existem muitas maneiras de lidar com a exceção, mas, no meu caso, eu queria que a exceção fosse tratada pelo meu ExceptionController
porque sou teimoso e também porque não quero copiar / colar o mesmo código (ou seja, tenho algum processamento / registro código emExceptionController
). Eu gostaria de retornar a bela JSON
resposta, assim como o resto das exceções lançadas não de um Filtro.
{
"status": 400,
"message": "some exception thrown when executing the request"
}
Enfim, consegui fazer uso do meu ExceptionHandler
e tive que fazer um pouco mais conforme mostrado abaixo nas etapas:
Passos
- Você tem um filtro personalizado que pode ou não lançar uma exceção
- Você tem um controlador Spring que lida com exceções usando, por exemplo,
@ControllerAdvise
MyExceptionController
Código de amostra
//sample Filter, to be added in web.xml
public MyFilterThatThrowException implements Filter {
//Spring Controller annotated with @ControllerAdvise which has handlers
//for exceptions
private MyExceptionController myExceptionController;
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void init(FilterConfig arg0) throws ServletException {
//Manually get an instance of MyExceptionController
ApplicationContext ctx = WebApplicationContextUtils
.getRequiredWebApplicationContext(arg0.getServletContext());
//MyExceptionHanlder is now accessible because I loaded it manually
this.myExceptionController = ctx.getBean(MyExceptionController.class);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
try {
//code that throws exception
} catch(Exception ex) {
//MyObject is whatever the output of the below method
MyObject errorDTO = myExceptionController.handleMyException(req, ex);
//set the response object
res.setStatus(errorDTO .getStatus());
res.setContentType("application/json");
//pass down the actual obj that exception handler normally send
ObjectMapper mapper = new ObjectMapper();
PrintWriter out = res.getWriter();
out.print(mapper.writeValueAsString(errorDTO ));
out.flush();
return;
}
//proceed normally otherwise
chain.doFilter(request, response);
}
}
E agora o exemplo de Spring Controller que lida Exception
em casos normais (ou seja, exceções que normalmente não são lançadas no nível de Filtro, aquele que queremos usar para exceções lançadas em um Filtro)
//sample SpringController
@ControllerAdvice
public class ExceptionController extends ResponseEntityExceptionHandler {
//sample handler
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ExceptionHandler(SQLException.class)
public @ResponseBody MyObject handleSQLException(HttpServletRequest request,
Exception ex){
ErrorDTO response = new ErrorDTO (400, "some exception thrown when "
+ "executing the request.");
return response;
}
//other handlers
}
Compartilhando a solução com aqueles que desejam usar ExceptionController
para Exceptions
jogar em um filtro.