METADATA parameters disappear after AJAX action - ajax

in template i'm defining a parameter
<f:metadata >
<f:viewParam name="pageKey" value="#{parameterProvider.pageKey}" />
</f:metadata>
All works fine except AJAX requests with makes this param disappear?
example ajax button in xhtml page:
Message value from server= [#{lockerBean.msg}]<br/>
<h:form>
<h:commandButton value="Ajax Action" styleClass="systemButton" >
<f:ajax execute="#all" render="#all" listener="#{lockerBean.ajaxButton(event)}"/>
</h:commandButton><br/>
</h:form>
ajax action is simply
public void ajaxButton(ActionEvent event){
msg="Ajax reload";
}
After ajax request pageKey is gone. If i set required="true" i get valudation error
j_idt3: Validation Error: Value is required. with clearly indicates, that parameter has been deleted. how can i preserve it?
I know about includeViewParams, but i don't understand this mechanism very well and it is not easy to add to all kinds of buttons and links... can i somehow force it to be passed or can i inject them somewhere in context?
EDIT:
this log might help to understand what is happening:
ParameterProvider, is sessionscoped CGI that holds pageKey. I modified getter & setter, so they log info about being called. In whole aplication getters and setters to this value is used only when applying request value in jsf lifecycle (my own code uses different methods)
14:04:06,400 OFF [ParameterProvider] (default task-12) Getting pageKey[-1] into viewParams.
14:04:06,401 OFF [ParameterProvider] (default task-12) Setting pageKey[2] from viewParams.
14:04:06,401 OFF [MultiActionLockListener] (default task-12) AJAX ACTION
14:04:06,414 OFF [ParameterProvider] (default task-12) Getting pageKey[3] into viewParams.
as you can see, before anything we have calling getter and setter for key (2 has been send from client 3 suppose to be sent to client in response)
calling another action will cause to log:
14:08:54,281 OFF [MultiActionLockListener] (default task-14) AJAX ACTION
14:08:54,294 OFF [ParameterProvider] (default task-14) Getting pageKey[7] into viewParams.
as you see, there is no getter and setter, which means pageKey is gone?

Related

Apache-Shiro: User authenticates within AJAX, how to restore GET-Variables after login?

in my JavaEE-Application, I am using Apache Shiro[1] for user-authentication.
My users are navigating via GET-URLs, as for example "/company/index.xhtml?companyId=327".
I have enabled programmatic login, following a guide[2] from BalusC:
SavedRequest savedRequest = WebUtils.getAndClearSavedRequest(Faces.getRequest());
My problem is, that savedRequest.getRequestUrl() does not contain the previous mentioned GET-parameteres, when my case is asynchronous POST with or without RememberMe; just "/company/index.xhtml" is returned, for example. It seems as if "FacesAjaxAwareUserFilter" (see [2]) is not GET-params aware. Everything works fine on synchronous GET-calls.
How do I get the GET-parameters after an shiro-redirect because of authentication-needed in case of using "FacesAjaxAwareUserFilter"?
[1] https://shiro.apache.org/
[2] Followed this great article about JavaEE and Shiro: http://balusc.blogspot.de/2013/01/apache-shiro-is-it-ready-for-java-ee-6.html
JSF ajax requests are sent to the URL as generated by <h:form>. This is however by default not exactly the current URL including the query string, it's by default the current URI without the query string.
There are several ways to fix this. The simplest but ugliest way is to use JS:
<h:form id="foo">
...
</h:form>
<script>document.getElementById("foo").action += "?" + location.search;</script>
The cleanest way would be to create a custom ViewHandler whose getActionURL() (as used by <h:form>) will return the desired URL with the query string.
JSF utility library OmniFaces has already such a component which does that based on view parameters: the <o:form> which basically extends the <h:form> with support for includeViewParams="true" (exactly the same way as <h:link> does).
<f:metadata>
<f:viewParam name="companyId" value="#{bean.company}" />
</f:metadata>
...
<o:form includeViewParams="true">
...
</o:form>

Primefaces p:calendar with p:ajax value not updated (one step delay)

I want to call a bean after a date is selected in a p:calendar. In my setup I have a #Named #ViewScoped Bean, the class ObWithDate is a #Entity with a date field validFrom.
<h:form id="fUser">
<p:dataTable id="dt" var="cum" value="#{myBean.listObWithDates}">
<p:column>
<p:calendar id="cValidFrom" value="#{cum.validFrom}">
<p:ajax event="dateSelect" listener="#{myBean.update(cum)}"
update=":fUser:dt"/>
</p:calendar>
</p:column>
</p:dataTable>
</h:form>
The good thing is, that the bean method update(ObWithDate myO) is called with the correct object each time I select a date. The bad thing is, that myO.validFrom does not have the correct value. It's always one step behind:
Field initialized with 2012-01-01
GUI change to 2012-01-05, bean method debugs to 2012-01-01
GUI change to 2012-01-15, bean method debugs to 2012-01-05
This issue drives me crazy, I've found several issues with not correctly updated values and also some about p:calendar. Most of them suggest using the attribute selectListener="#{calendarBean.handleDateSelect}" with a handleDateSelect(DateSelectEvent event) method. But I want to call my method since I want to pass the current instance of the variable.
Firebug verifies, that the correct updated values are transmitted in a POST request
I'm using Primefaces 3.2 and JBoss-7.1.1-Final
Even without the p:dataTable and only using p:calendar the issue is still the same.
The wrong value of the debug output can be observed for the method-Object update(ObWithDate myO) as well for the corresponding entry in myBean.listObWithDates.
<p:ajax immediate="true" .../> does not solve this issue.
Update MattHandy helped me a lot, the resulting question How to get the corresponding list item in the ajax call inside the beans method? is formulated in the followup JSF p:calendar in p:dataTable: How to get the row of p:ajax dateSelect event.
This is most likely a lifecycle issue. The setter for your field is called before your listener executes. You should not use the listener to set your value.
The el expression on your listener is evaluated at render response phase of the previous request thus it holds the cum value "one step behind".
You should update your custom object from the setter of the calendar's date value.
I ran into this issue today morning. Found that primefaces have removed the DateSelectEvent from Primefaces 3.5 . Hence had to remove the ajax event call from my calendar object. Instead retrieving the value using get..(). Please find the discussion for the same in this link below.
http://forum.primefaces.org/viewtopic.php?f=3&t=27590

How to know whether JSF bean setter is invoked from AJAX event or as part of form POST processing

I have a form that contains a Part Number inputText field and some other fields that represent the attributes of a part. If the user enters an existing part number, I want to populate the other fields with the part's existing attributes. The operator then has the option to change Part Number to something else (essentially creating a new part using the existing part as a template) and/or modify its attributes. I have an AJAX event defined to update the model when Part Number changes, so I can retrieve the attributes from the database:
<f:ajax event="valueChange" execute="#this" render="partlength" />
My question is this: How does the Part Number setter (e.g. setPartNumber() ) know whether it is being invoked as part of an AJAX event, in which case I want to fetch the attributes, or as part of the Update Model Values phase of the form being posted, in which case I don't? Or is there a better way to accomplish what I'm trying to do?
You can determine by PartialViewContext#isAjaxRequest() whether the current request is an ajax request or not. You can obtain the PartialViewContext by FacesContext#getPartialViewContext().
if (FacesContext.getCurrentInstance().getPartialViewContext().isAjaxRequest()) {
// The current request is an ajax request.
}
An alternative is to just do the job in the listener method of <f:ajax> instead of in the getter/setter (doing business job in getters/setters is a poor practice anyway):
<f:ajax listener="#{bean.listener}" render="partlength" />
(note that I omitted the event and execute attributes as you've used the default values already)

Passing request scoped beans from one page to another

If I have a request scope bean on a page in JSF2....how do I pass it to another page (I'm using JSF2 with Spring)?
I've tried the following but it doesnt work:
<h:commandButton action="complete.xhtml?faces-redirect=true" value="Confirm Booking">
<f:setPropertyActionListener target="#{quoteHolder.item}" value="#{quoteHolder.item}"/>
</h:commandButton>
action="complete.xhtml?faces-redirect=true"
You're sending a redirect. The <f:setPropertyActionListener> won't help much here as the request scoped bean will be garbaged after the invoke action phase anyway.
You have basically the following options:
Send all the data as request parameter(s) instead (conversion to/from String necessary!)
Don't send a redirect (the <f:setPropertyActionListener> becomes superfluous then)
Store it in a session scoped bean (not recommended! may be bad for user experience).

JSF: Reload request scope property after ajax-request

I have a hidden input field, which value is read from a property of the request scope:
<h:inputHidden id="myHiddenField" value="#{requestScope['myVar']}" />
I trigger an Ajax-Request where I change the value of myVar.
<p:commandButton value="submit" action="#{myController.doSomething}" update="myHiddenField">
But my input field still contains the old value.
Any idea how I can solve this?
UPDATE:
Maybe I have to explain it a little bit more.. myVar contains the IDs of all input fields with an error message (facesContext.getClientIdsWithMessages()).
When I first submit the form (with some validation errors) it works as expected. When I resubmit the form with some other validation errors the value of myVar doesn't get updated... (Still contains the IDs of the 'old' errors) When I resubmit the form with no validation errors myVar gets updated. (myVar is empty now)
If you want to access a bean after the page has been loaded it needs to be at least ViewScoped. RequestScoped beans are destroyed when the page is loaded (the request is handled and there is no need for it anymore).

Resources