Announcement Announcement Module
Collapse
No announcement yet.
Previous solution to using links to fire events in JSF appears broken in 2.0.8 Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Previous solution to using links to fire events in JSF appears broken in 2.0.8

    In a previous thread, 63975, there was a post from jeremyg which referenced a PhaseListener solution to firing an event via a link in JSF.

    http://forum.springsource.org/showpo...58&postcount=5

    This solution works on version 2.0.7, but does not seem to work on version 2.0.8. i.e. If we switch the 2.0.7 distribution jars with the 2.0.8 jars, the solution no longer seems to work in our application, the afterPhase method never gets called.

    Does anyone have a solution?

  • #2
    Due to some changes in the way Web Flow processes a request in conjunction with the fix required for SWF-1133, a bit more extension is required to keep the PhaseListener working. Essentially, the View needs to be aware of the _eventId parameter in order to tell Web Flow that there is an event to be processed.

    You can achieve this by providing an extended JsfViewFactoryCreator that uses a wrapper/delegation approach to supply the correct detection of the _eventId parameter. Here is a working example:

    Code:
    package com.mycompany.example;
    
    import java.io.IOException;
    import java.io.Serializable;
    
    import org.springframework.binding.convert.ConversionService;
    import org.springframework.binding.expression.Expression;
    import org.springframework.binding.expression.ExpressionParser;
    import org.springframework.faces.webflow.JsfViewFactoryCreator;
    import org.springframework.webflow.engine.builder.BinderConfiguration;
    import org.springframework.webflow.execution.Event;
    import org.springframework.webflow.execution.RequestContext;
    import org.springframework.webflow.execution.View;
    import org.springframework.webflow.execution.ViewFactory;
    
    public class WrappingJsfViewFactoryCreator extends JsfViewFactoryCreator {
    
        @Override
        public ViewFactory createViewFactory(Expression viewIdExpression, ExpressionParser expressionParser,
    	    ConversionService conversionService, BinderConfiguration binderConfiguration) {
    	return new WrappingViewFactory(super.createViewFactory(viewIdExpression, expressionParser, conversionService,
    		binderConfiguration));
        }
    
        private static class WrappingViewFactory implements ViewFactory {
    
    	private final ViewFactory viewFactory;
    
    	public WrappingViewFactory(ViewFactory viewFactory) {
    	    this.viewFactory = viewFactory;
    	}
    
    	public View getView(RequestContext context) {
    	    return new EventIdAwareWrappingJsfView(viewFactory.getView(context), context);
    	}
        }
    
        private static class EventIdAwareWrappingJsfView implements View {
    
    	private final View view;
    
    	private final boolean userEventDetected;
    
    	public EventIdAwareWrappingJsfView(View view, RequestContext requestContext) {
    	    this.view = view;
    	    this.userEventDetected = requestContext.getRequestParameters().contains("_eventId");
    	}
    
    	public Event getFlowEvent() {
    	    return view.getFlowEvent();
    	}
    
    	public Serializable getUserEventState() {
    	    return view.getUserEventState();
    	}
    
    	public boolean hasFlowEvent() {
    	    return view.hasFlowEvent();
    	}
    
    	public void processUserEvent() {
    	    view.processUserEvent();
    	}
    
    	public void render() throws IOException {
    	    view.render();
    	}
    
    	public void saveState() {
    	    view.saveState();
    	}
    
    	public boolean userEventQueued() {
    	    return userEventDetected || view.userEventQueued();
    	}
    
        }
    
    }
    You would need to wire this into your Web Flow configuration as follows:
    Code:
    <!-- Configures the Spring Web Flow JSF integration -->
    <faces:flow-builder-services id="facesFlowBuilderServices" development="true" view-factory-creator="wrappingViewFactoryCreator"/>
    	
    <bean id="wrappingViewFactoryCreator" class="com.mycompany.example.WrappingJsfViewFactoryCreator" />
    This implementation assumes the presence of the previous PhaseListener workaround. If you don't care about a true FacesEvent being fired and rather just need a Web Flow event, you could probably eliminate the PhaseListener altogether and just extend the above implementation further to do the actual parsing of the event.

    Obviously, this would all be better if we just handled the _eventId parameter out-of-the-box, and that is still our intention in the future.

    Comment


    • #3
      Thanks

      Thanks Jeremy,

      I'll take a look at that. I don't suppose you have any timescales for a release that will have this out of the box?


      Stewart

      Comment


      • #4
        Is this still necessary with WebFlow 2.3.2? I am having trouble getting a link to transition to the next view state unless I use an h:commandLink vs. h:outputLink.

        Comment

        Working...
        X