Small technique we use for getting useful “step” logging from Spring Web Flow applications, where the URL itself doesn’t tell you what path a user is taking through your application. Which is often useful for investigating issues.

The basic entity of this solution is a custom FlowExecutionListener, with the stateEntered() method implemented to log information about the current state and transition. We include the HTTP Session ID so that we can track a single user’s path through the flow.

    @Override  
    public void stateEntered(RequestContext context, StateDefinition previousState, StateDefinition newState)  {  
        logProgress(context);  
    }

    private static Logger progress = Logger.getLogger("progress");

    /**  
     * Method for logging some standard progress indicators, callable from any SWF state.  
     * Currently uses a separate log4j Logger ({@link #progress}), and logs timestamp, Session ID,  
     * User-Agent header, SWF execution key (eXsY), SWF state name, and SWF event name.  
     * <p>Note the execution key is for the POST portion of the POST-Redirect-GET flow. Thus, it  
     * will match what appeared in the user's browser before the current view, not what appears  
     * when looking at the rendered view.</p>  
     */  
    public static void logProgress(RequestContext context) {  
        HttpServletRequest req = (HttpServletRequest) (context.getExternalContext().getNativeRequest());

        StringBuilder sb = new StringBuilder();  
        sb.append(req.getSession().getId()).append(", ")  
          .append(req.getHeader("User-Agent")).append(", ")  
          .append(context.getFlowExecutionContext().getKey()).append(", ")  
          .append(context.getCurrentState().getId());

        Event event = context.getCurrentEvent();  
        if (event != null) {  
            sb.append(", ").append(event.getId());  
        }

        progress.info(sb.toString());  
    }

You configure a FlowExecutionListener for Spring Web Flow like this:

    <bean id="progressLoggingListener" class="my.custom.webflow.ProgressLoggingFlowExecutionListener"/>

    <webflow:flow-executor id="flowExecutor">  
        <webflow:flow-execution-listeners>  
            <webflow:listener ref="progressLoggingListener"/>  
        </webflow:flow-execution-listeners>  
    </webflow:flow-executor>