you can use a servlet filter to handle conversation-specific exceptions. Every CDI 1.1 container provides a special filter with the name "CDI Conversation Filter" - this can be mapped after your custom filter in web.xml (filters are invoked in the same order they're defined in the deployment descriptor):
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <filter> <filter-name>MyFilter</filter-name> <filter-class>com.whatever.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>MyFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CDI Conversation Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
This mapping instructs the container to determine the conversation after your filter calls chain.doFilter() and allows you to catch any exceptions thrown in the chain.
Thanks for replying so fast, in my case this is a little bit complicated, the project is using JSF 2.1 & Richfaces 4.x with CDI, in application, because CDI doesn't have "Restart Conversation" with one request/response, I have to do "Post-Redirect-Get" or "AJAXPost-Redirect-Get" to restart the session, in JSF ajax call force redirect is different than normal request, JSF lib will return a xml and the jsf.js will parse that and redirect, it was fine if I use JSF exception hanlder, If I use the method you suggested, the JSF AJAX Post - Redirect - Get won't work, any idea how to solve that?
Also in the @BeforeDestruct on Conversation/Session beans if I call any JSF api (for example adding some Faces messages) with CDI 1.0 it's fine, with CDI 1.1 it will throw out exception because the destroy is in the filter instead of JSF lifecycle.
Could you describe the "AJAXPost-Redirect-Get" more thorougly? And what exactly does not work?
Re @PreDestroy - you're right, conversation scoped beans are now destroyed at the end of the servlet request, after the Faces servlet returns. Session scoped beans were always destroyed at the end of the request. I'm not sure it's a good idea to call JSF API inside @PreDestroy callback. What's your use case?
For example, in the faces-config.xml I have navigation rule:
<redirect include-view-params="false" />
then the JSF action return "endConversation", it will redirect, if the JSF action is called with <a4j:jsFunction> or <a4j:commandButton>, it actually fired a AJAX call and the JSF response instead 302 http code, it will be something like:
<?xml version='1.0' encoding='UTF-8'?>
and on the page the jsf.js will fire a GET request to the server GET /home.jsf...
Same thing if Conversation is not exist (WELD-0321) or pre-exist (WELD-0218), I'll use this method to redirect to /home.jsf or /home.jsf?cid=...
but with WELD2, I don't know how to do this.
And I saw the WELD2 boundled sample didn't have the beans.xml & web.xml updated, is there any way I can get a sample beans.xml & web.xml with all options in there?
Hm, I think I finally see the reason why the "ajax way" doesn't work. I'm afraid you'll have to handle the ajax response and redirect manually, see for example http://stackoverflow.com/a/7880970.
I still don't understand why to call JSF API in the @PreDestroy callback?