Is there a way to integrate Springs @ExceptionHandler with Joinfaces

103 Views Asked by At

i wanted to ask if there is a way to enable Springs @ExceptionHandler capabilities with Joinfaces/Primefaces.

For now i'm able to handle global @ControllerAdvice beans, but not if the @ExceptionHandler is inside the @Controller class.

Are there any suggestions on how to solve this topic?

Here is the code i wrote so far

@Slf4j
public class SpringJsfExceptionHandler extends ExceptionHandlerWrapper {

    public SpringJsfExceptionHandler(ExceptionHandler wrapped) {
        super(wrapped);
    }

    @Override
    public void handle() throws FacesException {
        final Iterator<ExceptionQueuedEvent> queue = getUnhandledExceptionQueuedEvents().iterator();

        while (queue.hasNext()) {
            ExceptionQueuedEvent item = queue.next();
            ExceptionQueuedEventContext exceptionQueuedEventContext = (ExceptionQueuedEventContext) item.getSource();

            try {
                Throwable throwable = exceptionQueuedEventContext.getException();

                FacesContext context = FacesContext.getCurrentInstance();

                handleException(context, (Exception) throwable);

            } finally {
                queue.remove();
            }
        }
    }

    private void handleException(FacesContext context, Exception throwable) {
        WebApplicationContext applicationContext = resolveApplicationContext(context);

        Collection<HandlerExceptionResolver> exceptionResolvers = listExceptionHandlerResolvers(applicationContext);

        for (HandlerExceptionResolver resolver : exceptionResolvers) {
            resolver.resolveException(request(context), response(context), null, throwable);
        }
    }

    private Collection<HandlerExceptionResolver> listExceptionHandlerResolvers(WebApplicationContext context) {
        return context.getBeansOfType(HandlerExceptionResolver.class).values();
    }

    private HttpServletRequest request(FacesContext context) {
        return (HttpServletRequest) context.getExternalContext().getRequest();
    }

    private HttpServletResponse response(FacesContext context) {
        return (HttpServletResponse) context.getExternalContext().getResponse();
    }

    private WebApplicationContext resolveApplicationContext(FacesContext context) {
        HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
        return WebApplicationContextUtils.findWebApplicationContext(request.getServletContext());
    }

}
public class SpringJsfExceptionHandlerFactory extends ExceptionHandlerFactory {

    public SpringJsfExceptionHandlerFactory() {
    }

    public SpringJsfExceptionHandlerFactory(ExceptionHandlerFactory wrapped) {
        super(wrapped);
    }

    @Override
    public ExceptionHandler getExceptionHandler() {
        return new SpringJsfExceptionHandler(getWrapped() != null ? getWrapped().getExceptionHandler() : null);
    }
}

This works:

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler
    public void handleCalculationException(CalculationException e) {
        FacesContext.getCurrentInstance().
                addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), e.getMessage()));
    }
}

This does not work:

@Data
@Controller
@ViewScoped
public class CalculatorController implements Serializable {

    @ExceptionHandler
    public void handleCalculationException(CalculationException e) {
        FacesContext.getCurrentInstance().
                addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), e.getMessage()));
    }
[...]

Thanks in advance

1

There are 1 best solutions below

1
On

TLDR: No

@ExceptionHandler is part of Spring MVC.

Spring MVC and JSF are separate web frameworks.

Joinfaces allows you to use JSF in a Spring Application, and you can also use Spring MVC in the same application. Every request will however either be handled by Spring MVC (i.e. the DispatcherServlet) or JSF (i.e. the FacesServlet).