JSF - f:param: parameter not sent but jessionid and ln=javax.faces - jsf

I've the following facelet code here
<h:form>
<h:button
value="Open"
outcome="foo.xhtml">
<f:param
name="fid"
value="#{foo.bar}" />
</h:button>
</h:form>
Usually the parameter is sent and the url of page foo.xhtml appears as
https://foo.bar/foo.xhtml?fid=4711
This is correct and expected. But sometimes it appears as
https://foo.bar/foo.xhtml;jessionid=...?ln=javax.faces
and the parameter is not sent. What's wrong? Thanks in advance.
WildFly 12 Final; Mojarra 2.3.3.SP1
Update (09.03.2021)
From end user report, now the same problem with:
public String foo() {
return "foo.xhtml?fid=4711&faces-redirect=true";
}
But still only sporadically.

Related

Flash-Scope in latest Mojarra-versions?

i read many topics with problems about mojarra's flash-scope
and until now, i was not able to get completly rid of these annoying
"The response was already committed by the time we tried to set the outgoing cookie for the flash. Any values stored to the flash will not be available on the next request."
messages which results in a lot of headache.
i read about workarounds like custom cookies or request-parameters, but i am
not feeling very well, when such
a basic thing does not work as accepted for a long time.
current enviroment:
- mojarra 2.2.13
- omnifaces 1.12.1
- tomcat 8.0.32
can anybody confirm, that this still occurs with the latest mojarra?
i also had these problems with previous mojarra versions - sometimes it works, sometimes not. anyway, the message
appears only one time after login, but the created cookie "csfcfc" never gets deleted and the warning now occurs on every request.
switching to myfaces is currently not an option due to other problems.
my simple case, eally nothing special?:
#ManagedBean
public class LoginBean implements Serializeable {
public String login(){
String nextPage = null;
//...
if (dataOk){
Messages.addFlashGlobalInfo("welcome");
nextPage = "/user/dashboard?faces-redirect=true";
}
return nextPage;
}
}
#ViewScoped
public class DashboardBean implements Serializeable {
#PostConstruct
protected void init(){
//....
initData();
}
}
mastertemplate.xhtml:
<h:body>
<f:view>
<div class="content">
<h:panelGroup id="messages">
<h:panelGroup layout="block" rendered="#{not empty facesContext.messageList}">
<o:messages globalOnly="true" escape="false" infoClass="alert-success alert-dismissable" />
</h:panelGroup>
</h:panelGroup>
<ui:insert name="content"/>
</div>
</f:view>
</h:body>
login.xhtml
<h:commandButton action="#{LoginBean.login}" id="btn-login" value="Login">
</h:commandButton>

Primefaces - commandButton does not work

I am facing a problem with commandButton, it is working only when the type is submit. Can someone take a look and let me know if there is a solution for that? The code below is very simple and does have the the propose to illustrate what I need. The method test() is not executed. Method runSubmit is executed successfully.
I need that test method is executed without a submit as the original page does have validations that are executed during the submit, test() method must be executed without a submit as it is a preliminary operation before of the submit.
I am using PrimeFaces 4.0, JDK 7, Tomcat 6 and JSF 2.0 (Apache), however I think it is happening in Mojarra as well.
SESSION:
package com.andre.bean;
public class AndreBean {
public void runSubmit() {
System.out.println("Submit executed");
}
public String test() {
System.out.println("Not submit executed");
return "true";
}
}
XHTML
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:form id="test">
<p:commandButton id="ns" value="not submit" type="button" action="#{andreBean.test}" ajax="false"></p:commandButton>
<p:commandButton id="s" value="submit" action="#{andreBean.runSubmit}"></p:commandButton>
</h:form>
</html>
Thank you very much
Andre
What's going on?
What you get is correct behaviour. In PrimeFaces button with type="button" works as it does in basic HTML - it doesn't cause any request. As PrimeFaces user's guide says:
Push buttons are used to execute custom javascript without causing an
ajax/non-ajax request. To create a push button set type as "button".
<p:commandButton type="button" value="Alert" onclick="alert('Prime')" />
If you want to "talk to" bean, you need to use type="submit" (which is default in p:commandButton).
However... contrary to submit buttons behaviour in HTML, in PrimeFaces such submission will not force redirection to new page but all communication will be handled by underlying AJAX requests.
Therefore only your second button will execute beans' method:
<p:commandButton id="s" value="submit" action="#{andreBean.runSubmit}" />
What probably you wanted to obtain?
If you don't want to send all your form to bean you can limit the scope of components that are processed with "process" attribute of p:commandButton:
<h:form id="test">
<p:inputText value="#{andreBean.value}"/>
<p:commandButton id="s" value="submit" action="#{andreBean.runSubmit}" process="#this" />
</h:form>
With the following bean you will see the difference:
public class AndreBean {
private String value;
public void runSubmit() {
System.out.println("Submit executed");
}
public String getValue() {
System.out.println("getValue");
return value;
}
public void setValue(String value) {
System.out.println("setValue: " + value);
this.value = value;
}
}
If you don't limit executed components in console you get:
getValue
setValue: foobar
Submit executed
...and with components limited only to process="#this" you get only:
Submit executed
Hope that helps.
Sometimes, the solution is simply add immediate="true", it changes the point, in JSF lifecyle, in which the bean action is triggered.
Here are an article about how and when use it:
immediate attribute article
Please check your binding with bean.
bean fields should be String or non primitive.

how to rerender a4j:commandLink after the action has been completed

i have a very simple code here:
<a4j:commandLink action="#{ticketAboxEventHelper.removeAboxTicket(ticketAbox)}"
onclick="if(!confirm('Are you sure ... ?')) return false;"
reRender="aboxlistpanel">
<h:graphicImage alt="Delete" url="../../img/dialog-error-5.png" title="Delete" />
<a4j:support event="oncomplete"
action="#{editTicketNewAction.testRerender()}"
reRender="aboxlistpanel"
/>
</a4j:commandLink>
When the link clicked the system must
ask if the user is confirmed
do the action
rerender the aboxlistpanel
Now my problem is the rerendering is hapenning before the action is getting finished. any idea how it can be done in the right way?
Your action methods is not valid for JSF 1.2 and you don't need the <a4j:support>. Since you want to pass a parameter, you should use <f:attribute /> and actionListener :
<a4j:commandLink actionListener="#{ticketAboxEventHelper.removeAboxTicket}" onclick="if(!confirm('Are you sure ... ?')) return false;" reRender="aboxlistpanel">
<h:graphicImage alt="Delete" url="../../img/dialog-error-5.png" title="Delete" />
<f:attribute name="ticket" value="#{ticketAbox}" />
</a4j:commandLink>
Your bean method will look like this :
public void removeAboxTicket(ActionEvent event)
{
TicketAbox ticket = (TicketAbox)event.getComponent().getAttributes().get("ticket");
// Your business logic
}
More info :
How to pass parameters in method expression JSF 2.0
Solved. I wrapped the offending JSF code in a and everything began working as expected. related to answer <a4j:commandLink> Not Rerendering. i solved it first and then found out someone else solved it in the same way. hmmm....

JSF2: why does empty test in rendered of panelGroup in composite prevent action from being called?

I am having problems getting an action of a managed bean to be called when certain other JSF elements from custom composite components are present in the same page as the h:commandButton that submits the h:form. I can narrow down the page elements that cause problems to those that perform the following harmless (to me) looking rendering tests:
<h:panelGroup rendered="#{not empty cc.attrs.element}">
or:
<h:panelGroup rendered="#{empty cc.attrs.element}">
where 'element' is a required attribute, loaded from a JPA entity by id. Something about that 'empty cc.attrs.element' or 'not empty cc.attrs.element' test blocks correct form submission and blocks action calling in any h:form in which it appears.
The form submission page debug.xhtml is:
<f:view>
<f:metadata>
<f:viewParam name="id" value="#{elementController.id}"/>
</f:metadata>
</f:view>
<h:head>
<title>DEBUG</title>
</h:head>
<h:body>
<h:form>
<util:view_link element="#{elementController.selected}"/>
<h:commandButton value="Apply" action="#{elementController.reflect}" />
</h:form>
</h:body>
Note the view parameter 'id' that via ElementController.setId will force the loading of the 'selected' or 'current' Element entity by id from JPA, not shown here. This should then move to test.xhtml via the action reflect():
#JSFaction
public Object reflect() {
String $i = "reflect";
log_debug($i);
if (current==null) {
log_warn($i, "can't generate reflect outcome for null current element");
return null;
}
//return "reflect?faces-redirect=true&includeViewParams=true&id="+current.getId();
//return "test?faces-redirect=true&includeViewParams=true&id="+current.getId();
//return "reflect?id="+current.getId();
return "/test?faces-redirect=true&id="+current.getId();
}
You can see above I have experimented with different outcome URLs, but it turns out the problem has nothing to do with that, it is simply that the action is not called at all (when the {not empty cc.attrs.element} test is performed in another page element.
The composite component that causes the problem is my util:view_link::
<composite:interface>
<composite:attribute name="element" required="true" type="com.greensoft.objectdb.test.entity.Element"/>
<composite:attribute name="name" required="false"/>
<composite:attribute name="showOwnerAsText" required="false" default="false"/>
<composite:attribute name="showModelClass" required="false" default="false"/>
<composite:attribute name="showEntityClass" required="false" default="false"/>
<composite:attribute name="showId" default="false"/>
<!--composite:attribute name="showHelp" required="false" default="false"/-->
<!--composite:attribute name="title" required="false"/-->
</composite:interface>
<composite:implementation>
<h:panelGroup rendered="#{empty cc.attrs.element}">
<span class="warn">NULL</span>
</h:panelGroup>
<h:panelGroup rendered="#{not empty cc.attrs.element}">
<h:panelGroup rendered="#{cc.attrs.showOwnerAsText}">
<h:outputText style="font-weight:bold" value="#{cc.attrs.element.owner.name}."/>
</h:panelGroup>
<h:panelGroup rendered="#{cc.attrs.showId}">
<h:link outcome="/view" value="<#{cc.attrs.element.id}>">
<f:param name="id" value="#{cc.attrs.element.id}"/>
</h:link>
</h:panelGroup>
<h:link outcome="/view"
value="#{empty cc.attrs.name ? cc.attrs.element.name: cc.attrs.name}"
>
<f:param name="id" value="#{cc.attrs.element.id}"/>
</h:link>
</h:panelGroup>
</composite:implementation>
You can see this is just a reusable way of creating a link to each Element, with the database id passed as parameter. If there is no Element a "NULL" is shown.
By commenting out bits at a time (bracketing) I can prove the problem has something to do with rendered="#{empty cc.attrs.element} and rendered="#{not empty cc.attrs.element} tests, which both prevent form submission and the action from being invoked by a h:commandButton in the same composed page (see debug.xhtml above). If for example I just use plain h:panelGroup elements without the 'rendered="#{empty cc.attrs.element}' and 'rendered="#{not empty cc.attrs.element}' tests, everything displays fine and the h:commandButton works as expected and the action is called ok, and the navigation works fine !
Q: Why does test 'rendered="#{empty cc.attrs.element}' or 'rendered="#{not empty cc.attrs.element}' prevent correct form submission and stop the action from being called ?
Grateful for ideas, Webel
EDIT: The problem only happens when I test on elementController.selected, where .selected is an #Entity Element. I tried it with a simple Duummy class with String name property, and a #RequestScoped DebugController, and it worked fine (the action was called).
<h:panelGroup rendered="#{not empty debugController.dummy}">
<h:outputText value="#{debugController.dummy.name}"/>
</h:panelGroup>
<h:commandButton value="Apply" action="#{elementController.reflect}" />
Reported as bug: http://java.net/jira/browse/JAVASERVERFACES-2343
I can now partially answer this question. I can now see what is happening and describe it, but I still do not understand fully - in terms of JSF phases and request scope - why it is happening as it is. It is a subtle and tricky problem.
To explain it I have rewritten the test case to make it simpler. The view.xhtml test page that takes an id query parameter is:
<f:view>
<f:metadata>
<f:viewParam name="id" value="#{elementController.id}"/>
</f:metadata>
</f:view>
<h:body>
<h:form>
<h:panelGroup rendered="#{empty elementController.selected}">
<div style="color:orange;">
No Element found for id(#{elementController.id}) or page called without id query param.
</div>
</h:panelGroup>
<h:panelGroup rendered="#{not empty elementController.selected}">
[<h:outputText value="#{elementController.selected.id}"/>]
<h:outputText value="#{elementController.selected.name}"/>
</h:panelGroup>
<br/><br/>
<h:commandButton value="Apply" action="#{elementController.action}" />
</h:form>
</h:body>
Where ElementController extends RequestController. On loading a view.xhtml the id query parameter is set as a viewParam using setId, which loads a matching Element entity by id (from database) and sets it as the 'current' (a.k.a. "selected") Element, available as getSelected(), which also performed a test for null current, and that was what was causing the problem:
public void setId(Long id) {
log_debug("setId","id",id);
if (id != null) {
this.id = id;
T found = (T) getAbstractFacade().find(id);
if (found == null) {
String $error = "No object with id(" + id + ") found for class " + getManagedClass().getSimpleName();
log_error($error);
}
setCurrent(found);
}
}
public T getSelected() {
log_debug("getSelected","current",current);
if (current == null) {
//current = newElement(); //THIS WAS CAUSING PROBLEMS
log_warn("getSelected","null current Element");
}
return current;
}
The problem was that on submission of the form, getSelected() was being called twice for each instance of the test '#{not empty elementController.selected}' or '#{empty elementController.selected}' before the action was being called and with the field 'current' null.
In the #RequestScoped #ManagedBean ElementController the getSelected() method had a test for whether the current (a.k.a. selected) Element is null, and was taking an action that lead to an error, and this was shortcircuiting the call of the action on the commandButton when a 'not empty elementController.selected' was called:
(The problem I am seeing has nothing to do with whether the "selected" Element subjected to the 'not empty' or 'empty' test is an #Entity or not, I was mislead to believe that because the problem is with the ElementController that handles Element entities, and of course that conclusion did not sound right anyway.)
If I get rid of the assignment of newElement(), which was causing an error, and was there to catch cases when the view page is invoked without an id parameter (that triggers loading of the 'current' entity by id), and instead log a warning, I can see that for each instance of a 'not empty elementController.selected' or 'empty elementController.selected' test, that warning is logged twice BEFORE the action of the commandButton is called on form submission.
Somehow - and this is the part I do not fully understand - under #RequestScoped, the Element that was assigned to variable 'current' (a.k.a. "selected") is lost, and the 'not empty elementController.selected' test in the view page (and thus getSelected()) is invoked twice with current = null (with side-effects).
If I change the scope of the ElementController to #SessionScoped the problem vanishes; the current Element state is maintained, and getSelected() is never called with 'current' null.
I would appreciate any reply comments that explain in terms of JSF phases and request scope why my 'current' variable is suddenly null and why the '#{not empty elementController.selected}' is performed twice before the action is called. I have checked that setId is not called at all in between (only on initial view page load), something else is resetting current to null, or the request scoped bean is recreated in between form submission and the calling of the action.

Problems with conditionals in JSF

I have the code bellow:
<c:set var="show" value="#{cartBean.itemsAdded}" />
<c:if test="${show}">
<h:form id="test1">
<h:commandLink action="#{cartBean.foo}">this doesn't work</h:commandLink>
</h:form>
</c:if>
<h:form id="test2">
<h:commandLink action="#{cartBean.foo}">this works!</h:commandLink>
</h:form>
When show=false, show only the second link.
And it works. I can reach server (I'm using debug to see this).
When show=true, both links appears. But ONLY second link works. The link inside conditional doesn't trigger the action in server.
Someone, can, please, help me?
Note: the same thing happens when I use a4j:outputPanel rendered="#{show}"
During processing of the form submit, JSF will re-evaluate whether the command button/link is been rendered. If it is not rendered, then it will simply skip the action.
You need to ensure that the expression #{cartBean.itemsAdded} returns true as well when the form submit is been processed by JSF. An easy test is to put the bean in the session scope (and I assume that the isItemsAdded() is a pure getter, i.e. it contains only return itemsAdded;).
If that did fix the problem and you'd like to keep the bean in the request scope, then add a <a4j:keepAlive> to retain the bean properties in the subsequent request.
<a4j:keepAlive beanName="#{cartBean}" />
See also:
Commandlink is not being invoked
Unrelated to the concrete problem, you should prefer JSF tags/attributes over JSTL ones as much as possible. In this particular case, you should get rid of both JSTL <c:> tags and use the JSF-provided rendered attribute instead:
<h:form id="test1" rendered="#{cartBean.itemsAdded}">
<h:commandLink action="#{cartBean.foo}">this doesn't work</h:commandLink>
</h:form>
WORKARROUND:
I don't want to use sessionScope, because of the danger of use this in a huge system (my case). I don't like to use keepAlive neighter, because I'm in a clutered server and many attributes are not serializable.
Anyway, I've found this workarround:
Send a parameter in request (like show=true)
Change the check method, adding a OR in return to see this new parameter.
MANAGED BEAN:
Before:
public boolean itemsAdded() {
return foo; // my initial check
}
After:
public HttpServletRequest getRequest() {
return (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
}
public boolean itemsAdded() {
return foo || getRequest().getParameter("show") != null;
}
XHTML:
Before:
<c:set var="show" value="#{cartBean.itemsAdded}" />
<c:if test="${show}">
<h:form id="test1">
<h:commandLink action="#{cartBean.foo}">link</h:commandLink>
</h:form>
</c:if>
After:
<c:set var="show" value="#{cartBean.itemsAdded}" />
<c:if test="${show}">
<h:form id="test1">
<h:commandLink action="#{cartBean.foo}">link
<f:param name="show" value="true"/>
</h:commandLink>
</h:form>
</c:if>
IMPROVED (and tiny) WORKARROUND:
Change only XHTML:
Before:
<c:if test="#{cartBean.itemsAdded}">
<h:form id="test1">
<h:commandLink action="#{cartBean.foo}">link</h:commandLink>
</h:form>
</c:if>
After:
<c:if test="#{cartBean.itemsAdded || params['show']}">
<h:form id="test1">
<h:commandLink action="#{cartBean.foo}">link
<f:param name="show" value="true"/>
</h:commandLink>
</h:form>
</c:if>

Resources