1
votes

I really had touch time dealing with jsf life cycle phases. I trying to invoke business logic by passing through backing bean.And I noticed the update model phase is not at all invoked. let me explain code.

MyPage.xhtml

<h:selectOneMenu value="#{myModel.sortBy}">
    <f:selectItem itemValue="studId" itemLabel="Student Id" />
    <f:selectItem itemValue="rollNo" itemLabel="Roll No" />
    <f:param name="actionValue" value="sort" />
    <a4j:ajax event="change" render=":stdGrp" listener="#{myModel.processAjaxBehavior}" execute="@form" />
</h:selectOneMenu>

<h:selectOneMenu value="#{myModel.sortOrder}">
    <f:selectItem itemValue="asc" itemLabel="Ascending" />
    <f:selectItem itemValue="desc" itemLabel="Descending" />
    <f:param name="actionValue" value="sort" />
    <a4j:ajax event="change" render=":stdGrp" listener="#{myModel.processAjaxBehavior}" execute="@form" />
</h:selectOneMenu>

And my backing bean is: MyModel.java

public class MyModel implements Serializable, AjaxBehaviorListener,PhaseListener{
    private String sortBy = "studId";
    private String sortOrder = "desc";  

    //Getters and setters

    @Override
    public void processAjaxBehavior(AjaxBehaviorEvent arg0) throws AbortProcessingException {
        String eventId =  FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("actionValue");
        if(StringUtils.isNotBlank(eventId)) {
            FacesContext.getCurrentInstance().getExternalContext().getRequestMap().put(JsfView.EVENT_KEY, eventId); 
        } 
        else {
            throw new ApplicationException("param tag expected with 'activeValue' along with ajax tag"  ,null ); 
        }
    }

    @Override
    public void afterPhase(PhaseEvent arg0) {
        System.out.println("END PHASE " + arg0.getPhaseId());
    }

    @Override
    public void beforePhase(PhaseEvent arg0) {
        System.out.println("START PHASE " + arg0.getPhaseId());
    }

    @Override
    public PhaseId getPhaseId() {
        return PhaseId.ANY_PHASE;
    }
}

And some transition state in webflow to deal with sort. But the problem is when I select the drop down, nothing in the page gets changed, and I didnt notice errors too I make use of rich:messages even.

But from tomcat logs I can see, phase 4 and phase 5 are getting by passed as.

START PHASE RESTORE_VIEW 1
END PHASE RESTORE_VIEW 1
START PHASE APPLY_REQUEST_VALUES 2
END PHASE APPLY_REQUEST_VALUES 2
START PHASE PROCESS_VALIDATIONS 3
END PHASE PROCESS_VALIDATIONS 3
START PHASE RENDER_RESPONSE 6
END PHASE RENDER_RESPONSE 6

I dont know why this is happening, any help is appreciated.

1

1 Answers

1
votes

That will happen when a conversion or validation error occurred. Normally, the enduser is notified by conversion/validation errors by faces messages which are displayed by <h:message(s)>. If your view and/or action is somehow designed in such way that those messages don't have any chance to be displayed, then they are normally logged to the server log as a warning.

It's hard to tell what exactly happened in your case as the code is not in SSCCE flavor and you didn't explicitly mention if you checked the server log for clues. My best guess would be that there's a validation error elsewhere in the form, given that you're using execute="@form". The execute="@form" namely submits, processes, converts and validates the entire form. If one of the inputs has failed conversion/validation, then the update model values and invoke application phases are bypassed.

Once you add a <h:messages> to the view, or at least attach a <h:message> to every single input component, and make sure that the render="..." covers the message component(s), then you should be able to see them.

E.g.

<h:messages id="messages" />

<h:form>
    ...
    <a4j:ajax ... render=":messages :stdGrp" />
    ...
</h:form>

Or, if you actually didn't want to execute the entire form, but only the current component, then you should be using execute="@this" instead.

See also: