-2

I'm blocked for couple of days on a JSF issue.

I have a web app where I create the page content quite dynamically from database data. Every page has several sections containing a form with h:commandButton (or a set of buttons). Some forms work correctly and the form action method is launched as expected. Some other forms however don't work - the action method is not being called at all. And I don't know why :-(

I know this response: action method is not called in JSF which lists conditions which must be fulfilled and I believe that everything is ok here, but it simply doesn't work for some forms... Some points:

  • The problem is 100% repeatable
  • The same piece of XHTML is used for both successful and unsuccessful requests
  • The same action method (in the same bean) is being called for all forms
  • the console output differs in both cases
  • ...RESTORE_VIEW phase is the same (my code logs seem to be equal)
  • ...APPLY_REQUEST and few other phases are empty for the wrong case (only the final RENDER_RESPONSE phase is being executed
  • ...APPLY_REQUEST and the following phases are not empty for the correct phase
  • (using ui:debug) Scoped variables / Request parameters contain ONLY vallues passed via f:param for the successfull case
  • Scoped variables / Request parameters contain however also formid, formid:action_name and an input box content for the UNsuccessfull case
  • the console shows absolutely no exception in any case
  • the correct request returns HTTP code 302 followed by another GET request with the target parameters (as build in the action method)
  • the incorrect request returns directly 200 (and no action is called)
  • when the JSF debug is switched on (javax.faces.level = ALL, com.sun.faces.level = ALL) still no exception is being shown, I see only couple of "javax.faces.component.UIComponentBase getRenderer\nFINE: No renderer-type for component j_idt171" messages and one "com.sun.faces.facelets.util.DevTools writeAttributes FINEST: Error writing out attribute" followed by a NullPointerException - during RENDER_RESPONSE phase

So most probably there is a problem with restoring the view, but I have no idea why. The same XHTML block generates form and command button for both (successfull and unsuccessfull) cases (in a c:forEach loop).

But the strange think is also difference in the parameters in the correct case an in the wrong case...

Can anyone plase give me some directions what/where I should be looking for? Thanks a lot in advance!

EDIT: some code...

This is the XHTML (unnecessary code cis cut)

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
template="/templates/base.xhtml">

<ui:define name="title">IS runtime</ui:define>

<ui:define name="menu">
    <h:link value="Home" outcome="/index" /> | <h:link value="IS home"
        outcome="/runtime">
        <f:param name="env" value="#{param.env}" />
    </h:link>
</ui:define>

<ui:define name="content">
    <c:forEach var="pv" items="#{runtimeBean.pageViews}">
        <div id="view_#{runtimeBean.ISViews[pv.view].code}"
            class="view_#{runtimeBean.ISViews[pv.view].code}">
            <h2>#{runtimeBean.ISViews[pv.view].code}</h2>
            <h:form id="form_#{runtimeBean.ISViews[pv.view].code}">
                <h:messages />
                <c:if
                    test="#{runtimeBean.getEnvView(pv.view).type == 'RECORD_DETAIL'}">
                    <c:forEach var="item" items="#{runtimeBean.getViewItems(pv.view)}">
                        <h:outputText value="#{item.sqlColumn}" />:
                        <ui:fragment rendered="#{item.type == 'INPUT_FIELD'}">
                            <h:inputText id="#{item.sqlColumn}"
                                value="#{runtimeBean.sqlData0[item.sqlColumn]}" />
                        </ui:fragment>
                        <ui:fragment rendered="#{item.type == 'READ_ONLY'}">
                            <h:outputText value="#{runtimeBean.sqlData0[item.sqlColumn]}" />
                        </ui:fragment>
                        <br />
                    </c:forEach>
                </c:if>
                <c:forEach var="action"
                    items="#{runtimeBean.getViewActions(pv.view, 'BOTTOM_LEFT')}">
                    <h:commandButton id="action_BL_#{action.code}"
                        value="#{action.code}" action="#{runtimeBean.doPageAction}">
                        <f:param name="env" value="#{param.env}" />
                        <f:param name="view" value="#{pv.view}" />
                        <f:param name="action" value="#{action.id}" />
                        <c:forEach var="actionParam"
                            items="#{runtimeBean.getActionParams(pv.view)}">
                            <f:param name="#{actionParam}" value="#{param[actionParam]}" />
                        </c:forEach>
                    </h:commandButton>
                </c:forEach>
            </h:form>
        </div>
    </c:forEach>
    <ui:debug hotkey="z"
        rendered="#{facesContext.application.projectStage == 'Development'}" />
</ui:define>
</ui:composition>

This is Scoped Variables / Request Parameters for the correctly processed action:

Name    Value
env     5
id      22
page    3

After the correct action the next page contains the parameters as passed:

http://localhost:8080/metais/runtime.jsf?env=5&page=3&id=22

and the same for the incorrect action:

Name    Value
action  3
env     5
form_prj_detail form_prj_detail
form_prj_detail:action_BL_delete    form_prj_detail:action_BL_delete
form_prj_detail:name    p5
id      22
view    3

In the wrong case the next page doesn't show the arguments. Just simple:

http://localhost:8080/metais/runtime.jsf

In both cases the parameters are passed already in the HTTP (POST) request. It seems to me more as a problem of javascript part of the JSF library...

EDIT2: I made some progress in investigating the problem and I've found the following: The page is being generated dynamically including the forms. They are generated based on parameters passed to the page. However when applying the form data, they are being applied to page built with missing parameter. If the particular form is NOT present on the same page rendered w/o this parameter, the JSF then doesn't know the form instance and thus its values are not applied and the rest of the page processing chain is invalid. Using different words: if I add the problematic form to a "default page" (with missing page parameter), the form is processed also from different pages (the same XHTML but different parametrs causing showing different forms on the page). So for some reason when the page is restored or when the form data are being applied not all page parameters are used to restore the view. ...I made one small step but still don't have a solution and I'm frustrated :-(((

BR, Rada

Community
  • 1
  • 1
Rada
  • 52
  • 5

1 Answers1

0

So, finally I've understood the problem.

The problem is in the Restore View phase when the server reconstructs the submitted page before any form values could be set and before the form action could be performed.

The point is that the page is not being restored from internal JSF view state but it's restored as a "new" page - and using arguments used to build the original page.

My app. creates the forms dynamically and concrete page content depends on the page parameters (set in the HTTP GET message) and then data read from DB. Pressing a command button builds a request with parameters necessary for making the action - which however don't match with parameters necessary to reconstruct the original/previous page (I don't care of it).

This means that the Restore view is reconstructing DIFFERENT page than the one the command button is pressed from. This means that the reconstructed forms don't match with the original page forms. And this finally means that they can't be matched and thus the follow up life cycle steps are not successfull and no action method could be called.

So... this is either my misunderstanding of the JSF principles OR it's a JSF design issue. I'd simply expect that the Restore View must be performed implicitly and automatically...

Comments welcome!

BR, Rada

Rada
  • 52
  • 5