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>
Related
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
I'm trying to fill, submit, and test a web form in Play Framework, using ScalaTest and FluentLenium. It seems like it should be very straightforward, but I'm having all kinds of problems.
First, part of the web form in question:
<form class="signin" id="loginform" method="POST" action="/login">
<div class="form-group">
<label for="name">Email Address:</label>
<input type="email" class="form-control" placeholder="Enter Email Address" id="email" name="email" required />
...
This works fine from a real web browser. Now the problem comes when I try to fill in and submit the form:
#RunWith(classOf[JUnitRunner])
#SharedDriver(deleteCookies = false)
#SharedDriver(`type` = SharedDriver.SharedType.PER_CLASS)
class TestWebsiteAuthentication extends Specification {
"Application" should {
"login as an administrative user on the web site" in new WithBrowser with GPAuthenticationTestUtility {
browser.goTo(loginURL)
browser.fill("#email").`with`(prerequisiteAccounts.head.userIdentity) must equalTo(OK)
...
At that last line, I get an exception:
[info] x login as an administrative user on the web site
[error] 'org.fluentlenium.core.action.FillConstructor#1c25c183' is not equal to '200' (TestWebsiteAuthentication.scala:93)
[error] Expected: 200
[error] Actual: org.fluentlenium.core.action.FillConstructor#1c25c183
Any ideas what I'm doing wrong here?
I've tried taking out the "must equalTo(OK)" but this just causes the form to fail on submit -- unfortunately, I haven't been able to find ANY documentation on how to do this, so I'm basically piecing it together bit by bit. Pointers to relevant documentation would be appreciated -- there doesn't seem to be anything complete at Tyrpesafe... just "teasers" that get you started, but no depth. :-(
When you write browser.fill("#email").``with``("x#y.com"), all you're really doing is telling Fluentlenium to edit the template to add a value attribute inside the input tag.
On the other hand, OK is an HTTP status code, so comparing them will naturally yield false.
When you say you tried to submit the form and it failed, i am assuming you did something such as:
browser.fill("#email").`with`("x#y.com")
browser.fill("#password").`with`("myPass")
browser.click("#button") // this should submit the form and load the page after login
and then tried to make an assertion such as:
browser.title() must equalTo("next page") // fails because "next page" != "login page"
one suggestion is to try something like this, Before browser.click:
browser.pageSource() must contain("xyz") // this will fail
When the above assertion fails, it will print the content of browser.pageSource() to your terminal, and you'll be able to see the modifications the Fill function did to the HTML.
In my case, I observed that my pageSource() now contained the following:
<input type="text" id="email" name="email" value="x#y.com"/>
<input type="password" id="password" name="password"/>
Notice how the first input has a value="x#y.com", but the second input is still empty. It turns out the second one is empty because it is an input of type password, however I eventually made the form login work.
Here is a list of things you can look into:
have a database enabled in that Spec
have it populated with Users (in case your form validation connects to a DB, that is)
from what I have experienced, using browser.goTo more than once in a test will not work well with form submission (anyone can confirm?)
Hope this helps
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.
Is it possible to add groovy code to grails form?
I have a form:
<g:uploadForm controller="document" action="save" method="post">
<input type="file" name="dataFile" />
<input type="submit" id="addDocument" value="<g:message code=messages.document.save"/>">
</g:uploadForm>
I need to add code that puts the URL segments to the parameter value.
You're using a POST (because it's an upload and that's correct) method in your form, so you will not see the params in the URL. The params will get there (to the controller you redirect the request to), but won't show at the URL. In any case, you should go with hidden inputs in your form. Like:
<input type="hidden" id="foo" value=""/>
In your controller, you can get the parameters set in your input hidden fields simply by accessing the params map:
params.foo
Use hidden fields inside the form.
JSP:
<form:form commandName="editWeather" method="post" action="../edit">
<!-- Input fields -->
<input type="submit" value="Submit">
</form:form>
And this is how I get the model in Spring:
#ModelAttribute("DONTGIVEADAMN") Weather weather
And I can still use the weather to do my operations and it works great, for example:
weatherService.editWeather(weather);
My question is...Why does this work?
Model attribute name doesn't matter when binding data received from a form (because names of form fields correspond to the names of fields of the model object), it matters only when rendering a form.
I particular, when model attribute name in your POST handler method doesn't match the commandName in the form, you will be able to receive the data, but won't be able to redisplay a form with validation errors.
its matching the class type (or interface), not the name of the variable/parameter; and the specified request mapping/method signature must be correct.