Removing JSF messages from the flash - jsf

I have one page that does something and when the user clicks a button, the user is redirected to another page and a message is displayed. Here is my code:
public String confirm() {
FacesContext context = FacesContext.getCurrentInstance();
Flash flash = context.getExternalContext().getFlash();
flash.setKeepMessages(true);
FacesMessage msg = new FacesMessage("Succesful", "Release is confirmed!");
context.addMessage(null, msg);
return "/prot/expert/releases?faces-redirect=true";
}
I use a p:growl component which displays my message on the "releases" page. So far so good.
But then on any subsequent page that has p:growl (or if I go to another page and go back) the message is displayed again and again and I can't kill it.
I tried something like:
<c:set target="#{flash}" property="keepMessages" value="false" />
on the page that has the p:growl, I tried clearing the flash from the backing bean etc.
The message is retained and displayed all over again. If I remove flash.setKeepMessages(true); from the code above then nothing is displayed.
What am I doing wrong?

I did get the exact same problem on JBoss AS 6 with both Mojarra 2.0.3 and Mojarra 2.1.1. The flash should survive only one redirect, but in practice it not always does.
In an action method I have basically the same code:
// [add global faces message]
FacesContext.getCurrentInstance().getExternalContext().getFlash().setKeepMessages(true);
return "/someView.xhtml?faces-redirect=true";
I've been seeing three symptoms of the problem:
After doing a postback on someView, the flash faces message keeps being displayed
After a clean request to a completely different page, the face message is also displayed
After going again through the code that adds the faces message, you'll get two of the same messages on someView
Issue 2 can be explained by realizing that the flash scope is cookie based (at least in Mojarra). Relatively few people seem to understand the inherent problem with that. I've found this related question, but it has no answers: Is Flash scope free of race conditions?
Also, when trying to reproduce the problem I've got approximately a 2/3 chance of actually reproducing it. Sometimes it indeed only survives a single redirect, sometimes it's gone after a few refreshes (time based or so?) and sometimes it just sticks around and the only way to get rid of it is restarting my server(!).
Maybe I'm doing something wrong somewhere?
Observing the cookies being set, I noticed the followed:
After initially triggering the action that does the redirect:
POST Response
Set-Cookie csfcfc=_50Xfr
GET Response
Set-Cookie csfcfc=50Xfn_51Xfn
The thing to notice here is that the response from the GET request for the redirect again sets a cookie. You want think that for a flash scope the cookie would need to be deleted here.
If I submit a form on the view towards I'm redirected, the following happens:
POST Response
Set-Cookie csfcfc=_50Xfn
The message is now gone.
However, when I submit the form once more, the following happens:
POST Response
Set-Cookie csfcfc=_52Xfn
And, the message is back :(
If I again submit the form:
POST Response
There is no more Set-Cookie header and the message in once again gone. If I continue submitting the form, the last cookie (csfcfc=_52Xfn) keeps being send to the server, but there are no more new cookies being set and no messages are displayed.
Edit:
During debugging I came across a critical section in ELFlash.java (Mojarra 2.0.3):
void saveAllMessages(FacesContext context) {
// take no action on the GET that comes after a REDIRECT
Map<Object, Object> contextMap = context.getAttributes();
PreviousNextFlashInfoManager flashManager;
if (null == (flashManager = getCurrentFlashManager(contextMap, true))) {
return;
}
if (flashManager.getPreviousRequestFlashInfo().isIsRedirect()) {
return;
}
}
During the context of the GET request following the redirect, one would suppose isIsRedirect would return true, but it returned false. This could be a local problem, that I'm going to investigate further.
Interesting to note is perhaps that the cookie values actually have some meaning, according to the following:
FirstTimeThru("f"),
SecondTimeThru("s"),
IsRedirect("r"),
IsNormal("n");
So the first cookie (_50Xfr), is a FirstTimeThru and a IsRedirect.

Your concrete problem is caused by a bug in older Mojarra versions, specifically issue 1751. There have however been many issue reports for the flash scope afterwards. The flash scope is in older Mojarra versions known for the following major problems:
issue 1751 - Flash scoped messages lives longer than next request - fixed in 2.0.7 / 2.1.4
issue 2126 - Flash cookie enables data exploits - fixed in 2.1.24 / 2.2.1
issue 2136 - Flash cookie not available when redirected to different path - fixed in 2.1.14 / 2.2.0
issue 2902 - Flash cookie uses wrong path for applications on root - fixed in 2.1.24 / 2.2.1
issue 2955 - Flash creates sometimes version1 cookies which fails in IE<=10 - fixed in 2.1.25 / 2.2.2
issue 2973 - Flash causes NPE on stale cookies after a session expire - fixed in 2.1.25 / 2.2.2
issue 2862 - Flash cookie not cleared when stale - fixed in 2.1.27 / 2.2.5
All in all, concluded can be that you'd need to upgrade to a minimum of Mojarra 2.1.27 / 2.2.5 (due date 2 january 2014) in order to get rid of all those problems.

Try setting property redisplay to false:
<p:growl redisplay="false"/>

Related

PrimeFaces 7.0 Ajax Update Warning

I am getting this warning org.primefaces.PrimeFaces$Ajax.update PrimeFaces.current().ajax().update() called but component can't be resolved!Expression will just be added to the renderIds. Sometimes when using PrimeFaces.current().ajax().update I get the above warning, searching I implemented this solution https://forum.primefaces.org/viewtopic.php?t=58678
public static UIComponent findComponentById(String componentId) {
FacesContext context = FacesContext.getCurrentInstance();
UIViewRoot root = context.getViewRoot();
return root.findComponent(componentId);
}
So to avoid getting the warning I do the following:
if (FacesUtils.findComponentById("pnlEstado") != null) {
PrimeFaces.current().ajax().update("pnlEstado");
}
And it works, it does no longer throw the warning because component is always "findable" for updating.
The problem here is that my partner said he isn't sure if this is the best way to handle the warning because he thinks it will take alot of time when this is in production for it to execute, he said like this goes to client then comebacks to server then again to client, how this works he asked, and I didn't really know how to explain but the thing is I think this is the best way to handle it, want to know your opinion about it.
I also tried with binding component and checking if it is rendered but it is always true that it is rendered so it always updates and throws warning.
So I removed bindings and used this way. Also this only happens because I have 2 menus, when 1 is open the other one is not displayed, so I think thats why the update throws warning sometimes, but the solution I implemented solves it, anyways im open to your opinions.
Also this is the way he said he prefers me to solve it, im gonna try it https://forum.primefaces.org/viewtopic.php?t=32040
But I think its better with the one I want to use
The warning happens because the component for the given IDs can't be resolved in the current ViewRoot.
For the same reason, your FacesUtils.findComponentById returns null.
In PrimeFaces we just added this warning to inform the user, that the component to be updated, is likely not there and/or wont be updated. This can of course lead to a unexpected behavior for the developer.
So your FacesUtils.findComponentById is just a hack which leads to worse performance, as 'viewRoot.findComponent' will be called twice when the component is available.
The only real solution is to only call PrimeFaces.current().ajax().update() if you know that the component is rendered. Your view bean/controller should know the current state.
Otherwise just ignore the warning.

#ConversationScoped bean behaves as #RequestScoped since OmniFaces 2.5 FacesViews

I tried to upgrade my Java EE 7 / JSF 2.2 application to Omnifaces 2.6. Currently I am running version 2.4.
After that, I have noticed a strange behavior when using #ConversationScoped and Ajax-Requests. When calling, the area, which should get rendered after the request, gets cleared (no exception on the server, response status code 200).
Next, I have a kind of wizard implementation, based on #ConversationScoped. It holds a class called ViewManager which has itself a List of Views. Initializing works fine and this list gets filled. But somehow it gets cleared (set to null) when the first form/view gets submitted. The setter for this is never called after the initialization, so it is not changed by my code. Somehow the view manager instance is still available, only this list of view within the view manager is null, which is kind of strange.
With omnifaces 2.4, everything did work fine (this is why I did not add some code of my wizard). I checked the changelog and noticed the MultiViews configuration when using ExtensionlessURLs. Don't know why this could effect my problem, but i tried it...with no success.
I have no idea what could be the problem, so maybe you can help me.
Thanks in advance :)
In OmniFaces, the FacesViews extensionless URLs feature got in version 2.5 an overhaul in order to support the so-called MultiViews as you can read on this blog.
During this overhaul I made a backwards compatibility mistake in the FacesViewsViewHandler where the <h:form> action URL is being manipulated in order to include the virtual folders of the MultiViews feature. The query string parameters were dropped from the original action URL and not added back.
The #ConversationScoped relies on the cid request parameter being present in the <h:form> action URL as in /context/page?cid=1. This thus became /context/page and therefore the conversation isn't retained across postbacks.
I will fix this in next OmniFaces release, for now you can get back the desired behavior by adding the below context parameter to web.xml.
<context-param>
<!-- Workaround for disappearing #ConversationScoped ?cid= parameter -->
<!-- This can be removed in next OmniFaces version after 2.6 -->
<param-name>org.omnifaces.FACES_VIEWS_VIEW_HANDLER_MODE</param-name>
<param-value>BUILD_WITH_PARENT_QUERY_PARAMETERS</param-value>
</context-param>
This parameter triggers a different way of building the URL whereby the entire query string from the original action URL is explicitly retained.

Is the PrimeFaces socket supposed to append every connection to the URL?

I'm running the latest PrimeFaces showcase demo on GlassFish 4 and I'm running into the problem where every time the socket.connect("/user") is called, "/user" is simply being appended to the exiting URL.
requestContext.execute("PF('subscriber').connect('/" + username + "')");
Maybe the disconnect method is not working correctly?
The outcome is there are an increasing number of path segments so they don't get properly mapped to the path variables on the endpoint class.
A page refresh before making the connection works.
I know this came up in one similar post but I'm not allowed to comment.
Primefaces Push - What are the methods in <p:socket/> client widget
Thanks for any help :)
Looks like this was a defect that has been fixed now.
https://github.com/primefaces/primefaces/issues/1132

Navigation from managed bean constructor in ADF Faces JSF 1.2

Is it possible to navigate to another page/view from the constructor of the managed bean? I want this redirection if any exception occurred. I have tried many ways:
Try-1:
getFacesContext().responseComplete();
getFacesContext().getApplication().getNavigationHandler().handleNavigation(getFacesContext(), null, "gotoPartError");
getFacesContext().renderResponse();
Try-2:
getServletResponse().sendRedirect("partError.jspx")
Try-3:
getFacesContext().responseComplete();
getFacesContext().getExternalContext().redirect(getServletRequest().getContextPath() + "/pages/partError.jspx");
Try-4:
RequestDispatcher dispatcher = getServletRequest().getRequestDispatcher("partError.jspx");
dispatcher.forward(getServletRequest(), getServletResponse());
Try-5:
FacesContext context = getFacesContext();
UIViewRoot newPage = context.getApplication().getViewHandler().createView(context, "/partError.jspx");
context.setViewRoot(newPage);
context.renderResponse();
Try-6:
ControllerContext.getInstance().getCurrentViewPort().setViewId("partError");
Try-7:
Exception Handler in adfc-config.xml
Try-8:
Custom service handler defined in /.adf/META-INF/services/oracle.adf.view.rich.context.Exceptionhandler which extends oracle.adf.view.rich.context.Exceptionhandler
Try-9:
By extending JSF Life Cycle
None of them worked. For all the cases I received
java.lang.IllegalStateException: Cannot forward after response has been committed
Is not really possible in JSF 1.2? As I am using ADF 11.1.1.6.0, which uses JSF 1.2, some of the above "Try" contains ADF Faces ways.
I need anyway, that can be JSF 1.2 or ADF Faces, to navigate to error page. The only way I got success is the use of javascript, executed from backend, to open the error page in the _self window in case of error, but I don't really like it.
Any pointer in this matter would be very helpful.
It's easier to solve a problem if the cause of the problem is understood. A good exception tells basically already everything about the cause of the problem.
Look closer:
java.lang.IllegalStateException: Cannot forward after response has been committed
The response has been committed. This is a point of no return. Perhaps you failed to understand what it means that a response has been committed (which has the consequence that you also failed to understand the exception itself).
By default, the HTTP response is written to a buffer which is flushed every ~2KB, depending on server configuration. A flush of the response buffer causes the written bytes being actually sent from server to client. Once that happens for the first time, a response is considered committed. This is a point of no return. The server cannot take the already written bytes back from the client in case the server actually needs to change the response afterwards.
If you have some code which potentially needs to change the response, then you should be invoking it before the response is committed.
In your particular case, the managed bean is apparently constructed in the midst of the JSF render response phase during generating the HTML output. A part of the generated HTML output has already been sent to the client (so, the response is committed). You're apparently referencing the request scoped bean relatively late in the JSF page, or the response buffer is relatively small, or the HTML <head> is relatively large which causes a flush already before the <body> starts, etcetera.
You really need to invoke the code before the render response phase. In JSF 1.2, you can use the <f:view beforePhase> for this.
E.g.
<f:view beforePhase="#{bean.navigate}">
with
public void navigate(PhaseEvent event) {
if (event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
// Do here your job which should run right before the RENDER_RESPONSE.
}
}
Then your Try-1 and Try-3 will work (you can however leave those responseComplete() and renderResponse() lines away, they are implicitly already taken care of).
Try-2 and Try-4 are poor. You should avoid having javax.servlet.* imports in your backing bean. Try-5 is clumsy. Try-6, Try-7 and Try-8 are beyond my scope. Try-9 is doable, but extremely clumsy.

IceFaces: inputRichText - session timeout while typing

I'm using the inputRichText component for composing HTML-formatted messages in a system I'm working on.
I've encountered a problem, however. It seems the session times out, even when the user is working in the editor.
I tried setting the session timeout parameter in web.xml to 1 minute and started typing in the editor. After 1 minute the "User session expired" dialog box appeared. Is there any way to make the rich text editor component keep the session alive? It's pretty annoying to work on something for a while only to loose it to a session time out, event though you haven't been inactive.
This is the code I use to display the component in the page:
<ice:inputRichText height="250" toolbar="MyToolbar" customConfigPath="/FCKconfig.js" id="messageBody" value="#{bean.messageBody}" language="sv" saveOnSubmit="true" />
Thanks!
Edit:
I solved it using a periodic JavaScript calling into a servlet implementing the stuff outlined in this IceFaces JIRA report
If there's a better way, please let me know :)
I solved it using a periodic JavaScript calling into a servlet implementing the stuff outlined in this IceFaces JIRA report.
It basically allows a servlet to "touch" the session and hence keep it alive.
If there's a better way, please let me know :)

Resources