Beehive Devs, I've been looking at exception handing with respect to control container management and wanted to get some feedback or ideas from the dev group. Sorry for the long note. Hopefully the details do not cause too much confusion.
In NetUI today, when an action is executed, the FlowController.execute() method goes through the following general steps. - get the page flow control container and call beginContext() on the ControlContainerContext. - execute the beginAction, Action, afterAction code (in FlowController.internalExecute ()) -- call the beforeAction() callback -- execute the actual action method -- call the beforeAction() callback - perform the endContext() on the page flow ControlContainerContext. Note, in the FlowController.internalExecute() method where we actually execute the action method, we already have exception handling in place. If an exception is thrown at this stage in the NetUI framework, we will catch it and call the FlowController method, handleException(), to invoke user code if appropriate and return a destination URI. We also set the exception being handled in the PageFlowRequestWrapper. However, if an exception is thrown during the beginContext()/endContext() in the page flow Control container management, we do not catch the exception and run it through handleException(). Instead, the exception is caught in the processActionPerform() method of the Struts framework, then passed to the RequestProcessor method processException(). If there's no matching exception config, processException() will throw a new ServletException with the "root cause" exception. Unfortunately, when there is a user defined exception handler associated to the exception, processException() does not properly handle an exception config for the NetUI page flow exception handler. In this case, a ClassNotFoundException occurs in the Struts code when it tries to create an ExceptionHandler from the exception config. Struts expects the handler attribute of the exception element in the struts config to be a fully qualified Java class name. In NetUI we generate just the method name of the page flow Controller exception handler. This causes the CNFE. Then, a ServletException also gets thrown but doesn't wrap the root cause. The ServletException is eventually caught in the PageFlowRequestProcessor (in processInternal()). We then try to run it through the NetUI framework support in FlowController.handleException(). The exception could still result in an HTTP status 500 page if an exception has already been handled during the actual action method execution, it's not a framework exception, or one that a developer has written a handler. In general, I think the above works fine as designed. The only case that causes an issue is when a user has defined a NetUI exception handler for the exception thrown during the control container context management. This is the scenario that causes the CNFE described above. I think this one case may cause confusion. One possible solution is to leave the exception handling as is but just change our PageFlowRequestProcessor.processException() override to check if the ExceptionConfig is an instance of PageFlowExceptionConfig. Then we could try to handle the exception with FlowController.handleException(), rather than falling into the Struts super class implementation, RequestProcessor.processException(), to avoid the CNFE. Other thoughts? Should we explicitly try to catch exceptions in FlowController.execute() when we do the beginContext/endContext rather than let them bubble up? If so, should we just log them, or try to run them through the FlowController.handleException(). Thanks for the help. Kind regards, Carlin
