I'm using a configuration similar to yours, with Spring webflow and Spring security. To handle exceptions I use webflow handling instead of a SimpleMappingExceptionResolver and this works very well for me.
as a start you need a global xml flow that handle the exceptions, this flow will be used as "parent" of all your other flows. or you could also include directly the global transition and view-state in your flows:
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd"
abstract="true">
<persistence-context/>
<view-state id="generalException" view="../views/exception/generalException.xhtml">
<on-entry>
<evaluate expression="exceptionManager.extractMessages(flowExecutionException, rootCauseException)" result="viewScope.exc"/>
</on-entry>
</view-state>
<global-transitions>
<transition on-exception="java.lang.Exception" to="generalException"/>
</global-transitions>
</flow>
The class ExceptionManager is used only to format the exception in a readable way, specially in my case BatchUpdateException that needs the next() method to be called to know the source of the exception:
@Service("exceptionManager")
public class ExceptionManagerImpl {
public Map<String, String> extractMessages(Exception e, Exception root)
{
Map<String, String> out = new HashMap<String, String>();
out.put("exc_message", e.getClass().toString() + ": " + e.getMessage());
out.put("exc_details", formatStackTrace(e.getStackTrace()));
out.put("root_message", root.getClass().toString() + ": " + root.getMessage());
out.put("root_details", formatStackTrace(root.getStackTrace()));
if (root instanceof BatchUpdateException)
{
out.put("batch_message", ((BatchUpdateException)root).getNextException().getClass().toString() + ": " + ((BatchUpdateException)root).getNextException().getMessage());
}
return out;
}
public String formatStackTrace(StackTraceElement[] elements)
{
String out = "";
for (StackTraceElement ste: elements)
out += ste.toString() + "<br/>";
return out;
}
}
in this way all the unhandled exception will display into a JSF page, or whatever you use for views. AccessDeniedException goes normally trough Spring security in my system with this implementation. You could also specify different behaviours for different exception.
I hope it helps, have a good day,
Mattia