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
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
Related
I am using JSF 2.2 on Glassfish 4.1.
I am trying to pass in a query parameter to as an action method argument as follows:
// Example 1. This does not work.
// at url http://localhost:8080/app/order.xhtml?email=test#email.com
<p:commandButton value="Place order" action="#{orderManager.placeOrder(param['email'])}" />
(Know that param is an implicit EL object.)
In the server log I have configured it to print the method parameter, but I can see that an empty string was passed-in, not "test#email.com" as I expected.
I have confirmed that my overall configuration is working. If I replace the above snippet with the following, then "test#email.com" is output in the server log:
// Example 2. This works.
<p:commandButton value="Place order" action="#{orderManager.placeOrder('test#email.com')}" />
I have also confirmed that my use of EL implicit objects is feasible. The following snippet works if I retrieve the parameter from the FacesContext (after removing the email parameter from placeOrder's signature, of course):
// Example 3. This works.
<p:commandButton value="Place order" action="#{orderManager.placeOrder()}" >
<f:param name="email" value="#{param['email']}"/>
</p:commandButton>
And here is a final mystery, one that truly confuses me, if I use the following snippet, I can retrieve the "email" parameter from both the method parameter and the FacesContext, but recall that the method parameter wasn't retrievable in Example 1!
// Example 4. This works, and BOTH parameters are retrievable!
<p:commandButton value="Place order" action="#{orderManager.placeOrder(param['email'])}" >
<f:param name="email" value="#{param['email']}"/>
</p:commandButton>
Can I pass in an implicit JSF EL object as an action method parameter?
And do you have an explanation for why it seems to work in Example 4, but not Example 1?
The action attribute is evaluated during apply request values phase of the HTTP request triggered by the form submit, which is thus a different HTTP request than the one which produced the HTML output with therin the form (and having the email parameter present in the request).
The <f:param> tag is evaluated during render response phase of the HTTP request which needs to produce the HTML output with therein the form. This thus ends up "hardcoded" in the generated HTML output (on contrary to the EL method arguments in the action attribute!). When the user submits the form, this just gets passed back to the server as a plain vanilla String request parameter (which you would need to convert back if it was originally a complex type).
This has got nothing to do with whether the value is an implicit EL object or not.
That said, there are 2 other ways:
Pass it as hidden input (no, not with <h:inputHidden>).
<h:form>
<input type="hidden" name="email" value="#{param.email}" />
...
</h:form>
Set it as property of a view scoped bean, it'll stay in bean as long as the view lives.
<f:metadata>
<f:viewParam name="email" value="#{viewScopedBean.email}" />
</f:metadata>
Is it considered correct to have a composite component (compA) that holds a form, when compA can itself be contained in another form (in the using page)?
<!-- composite -->
<cc:implementation>
<h:form id="innerForm">
... composite stuff
</h:form>
</cc:implementation>
<!-- using page/component -->
<h:form id="outerForm">
<util:compA ... />
</h:form>
When trying to remove nested forms, any ajax call in the composite will submit the whole form, and as has some values may not yet be filled, validation fails.
Is there any best-practice approach to this?
Nested forms are always a bad idea and will result in invalid HTML output.
A Composite Component itself is a Naming Container so it should not be a problem to process only the CC or even some parts of it.
To prevent the whole form from being even submitted I would suggest PrimeFaces AJAX calls with partialSubmit="true". See here for reference.
If there are still problems with your AJAX calls you habe to provide the related code of your CC.
Hello I have that form:
<h:form>
<h:selectOneRadio layout="pageDirection" value="#{votesBean.answer}">
<f:converter converterId="PollConverter"/>
<f:selectItems value="#{pollsBean.selectItems}"/>
</h:selectOneRadio>
<h:messages/>
<h:commandButton value="#{msgs.vote}" action="/profile/main.xhtml"/>
</h:form>
But when I submit this form, page no redirects to main.xhtml, but refresh current page (viewpoll.xhtml, I ‘think because there are errors in form), but not include view parameters. I use view parameter to know current poll… in result I get nullpointer exception, because I don’t have poll id.
If you would like to navigate directly without validation and conversion, use immediate="true" in h:commandButton.
Otherwise, there might be a failure in Request Processing Life Cycle, Eg. validation phase.
Finally, your URL(/profile/main.xhtml) address is incorrect.
A have problem with accessing my custom components (which are used as parts of the form).
Here is the story:
I have dynamic form which have few modes of work. Each mode can be selected and loaded into form body with AJAX. It looks like that (template):
<t:form t:id = "form">
<p class= "calcModeTitle">
${message:modeLabel}: <select t:id="modeSelect"
t:type="select"
t:model="modesModel"
t:value="selectedMode"
t:blankOption="NEVER"
t:encoder="modeEncoder"
t:zone = "modeZone"
/>
</p>
<div class="horizontal_tab">
<t:errors/>
</div>
<t:zone t:id="modeZone" id="modeZone" t:update="show">
<t:if test="showCompany">
<t:delegate to="block:companyBlock" />
</t:if>
<t:if test="showPersonal">
<t:delegate to="block:personalBlock" />
</t:if>
<t:if test="showMulti">
<t:delegate to="block:multiBlock" />
</t:if>
</t:zone>
<t:block id="companyBlock">
<t:modes.CompanyMode t:id="company"/>
</t:block>
<t:block id="personalBlock">
<t:modes.PersonalMode t:id="personal" />
</t:block>
<t:block id="multiBlock">
<t:modes.MultiMode t:id="multi" />
</t:block>
<div class="horizontal_tab">
<input type="submit" value="${message:submit_label}" class="submitButton thickBtn"/>
</div>
</t:form>
AJAX works pretty well and form changes accordingly the "modeSelect" state. But i run into problem when submitting the form. I have in class definition hooks for components placed as:
//----form elements
#Component(id = "form")
private Form form;
#InjectComponent
private CompanyMode company;
#InjectComponent
private PersonalMode personal;
#InjectComponent
private MultiMode multi;
where *Mode classes are my own components, containing form elements and input components. I planned to get access to them during validation, and check values supplied by user with form, but when I am trying to reach anything from them I've got nullPointerException - it seems that component are not initialized in my class definition of form. On the other hand form component is injected properly (I am able to write some error for example). I am a bit lost now. How to properly inject my components to class page containing the form?
Dynamic forms in tapestry are a bit complicated. Tapestry passes a t:formdata request parameter which contains the serialized form entities. This is then used serverside in the POST to re-hydrate initial form state. This must be kept up-to-date with what the client sees.
If you want to add dynamic content to a form via ajax, you will need to use the FormInjector. You might want to take a look at the source code for the AjaxFormLoop to see an example.
If you want to render hidden form fragments and make them visible based on clientside logic, you can use the FormFragment
From tapestry guide:
A block does not normally render; any component or contents you put
inside a block will not ordinarily be rendered. However, by injecting
the block you have precise control over when and if the content
renders.
Try to use here either "t:if" or "t:delegate".
Something like this:
<t:zone t:id="modeZone" id="modeZone" t:update="show">
<t:delegate to="myBlock" />
</t:zone>
<t:block t:id="companyBlock">
<t:modes.CompanyMode t:id="company"/>
</t:block>
<t:block t:id="personalBlock">
<t:modes.PersonalMode t:id="personal" />
</t:block>
<t:block t:id="multiBlock">
<t:modes.MultiMode t:id="multi" />
</t:block>
java:
#Inject
private Block companyBlock, personalBlock, multiBlock;
public Block getMyBlock(){
if (getShowCompany()) return companyBlock;
if (getShowPersonal()) return personalBlock;
return multiBlock;
}
We're on CF 8 and we have a CF application with a 1 hour session timeout specified.
<cfapplication sessionmanagement="yes" sessiontimeout="#CreateTimeSpan(0, 0, 60, 0)#" name="myAppName" clientmanagement="yes">
Within the CF administrator, we have a default session timeout of 1 hour, and a max session timeout of 1 day.
We're having some odd (intermittent) form timeout issues on submission of a regular form (not a flash form)...
Let's say the user hits the form page at 10:30am. (I know this because I'm appending the time to the "Action" property of the form tag). At 11:10am, the user submits the form, but none of the form struct is available to the action page, so the user gets an error.
I know that it's coming from the correct page since the CGI.referrer is defined properly.
In my custom error handler, I iterate over any form, session, or client structs -- and there is NO form struct defined at this point. All of the other Session and Client variables ARE still available.
Excerpts from Form Page:
<cfform name="chairsComment" id="chairsComment" action="library/save_chairsComment.cfm?Start=0224_153027" method="post" >
<input name="chairsCommentNumber" id="chairsCommentNumber" type="hidden" value="13" />
<textarea name="comment_13" rows="50" wrap="virtual" cols="100" id="comment_13" ></textarea>
<input name="save_answer" id="save_answer" type="submit" value="Save Response" />
</cfform>
And for the Action page, it throws an error on line 1:
<cfset whichCommentNumber = form.chairsCommentNumber>
It works during testing, but when some of our users use it, it throws the error that "Element CHAIRSCOMMENTNUMBER is undefined in FORM." We've just started looking at the specific browser that this individual is using (Safari 4.0.3) and asked him to upgrade to 5.x, but with SUCH a vanilla form, it seems an unlikely culprit.
Any Ideas?
In the midst of a discussion on Ray Camden's blog about file uploading, someone mentions a problem with Safari 4.0.5 throwing an error because the form field did not contain a file ... it's not the same problem, necessarily, but it could be related. Unfortunately, the commenter never returned with more information.
There's a post on another blog here where a commenter mentions an issue with Safari and a cfform inside a cfdiv tag. If your cfform is similarly nested, you might need to reverse the order (nest the cfdiv inside the form) to make this work.