Search code examples
jsfjsf-2websphere

JSF 2 equivalent of IBM's hx:scriptCollector pre- and postRender


I am migrating an old JSF application from WebSphere to JBoss: the old version uses an IBM implementation of JSF. My question concerns the following component:

<hx:scriptCollector id="aScriptCollector"
        preRender="#{aBean.onPageLoadBegin}" postRender="#{aBean.onPageLoadEnd}">

To reproduce the preRender behavior in JSF 2 I use a binding for the form (s. here). My questions:

1) Do you know a trick for simulating postRender in JSF 2?

2) Do you think is the trick I am using for preRender "clean"?

Thanks a lot for your help! Bye


Solution

  • Closest what you can get to achieve exactly the same hooks is

    <f:view beforePhase="#{bean.beforePhase}" afterPhase="#{bean.afterPhase}">
    

    with

    public void beforePhase(PhaseEvent event) {
        if (event.getPhaseId == PhaseId. RENDER_RESPONSE) {
            // ...
        }
    }
    
    public void afterPhase(PhaseEvent event) {
        if (event.getPhaseId == PhaseId. RENDER_RESPONSE) {
            // ...
        }
    }
    

    The preRender can be achieved in an easier manner, put this anywhere in your view:

    <f:event type="preRenderView" listener="#{bean.preRenderView}" />
    

    with

    public void preRenderView(ComponentSystemEvent event) {
        // ...
    }
    

    (the argument is optional, you can omit it if never used)


    There's no such thing as postRenderView, but you can easily create custom events. E.g.

    @NamedEvent(shortName="postRenderView")
    public class PostRenderViewEvent extends ComponentSystemEvent {
    
        public PostRenderViewEvent(UIComponent component) {
            super(component);
        }
    
    }
    

    and

    public class PostRenderViewListener implements PhaseListener {
    
        @Override
        public PhaseId getPhaseId() {
            return PhaseId.RENDER_RESPONSE;
        }
    
        @Override
        public void beforePhase(PhaseEvent event) {
            // NOOP.
        }
    
        @Override
        public void afterPhase(PhaseEvent event) {
            FacesContext context = FacesContext.getCurrentInstance();
            context.getApplication().publishEvent(context, PostRenderViewEvent.class, context.getViewRoot());
        }
    
    }
    

    which you register in faces-config.xml as

    <lifecycle>
        <phase-listener>com.example.PostRenderViewListener</phase-listener>
    </lifecycle>
    

    then you can finally use

    <f:event type="postRenderView" listener="#{bean.postRenderView}" />
    

    with

    public void postRenderView(ComponentSystemEvent event) {
        // ...
    }