JSF - Keep Faces Messages after redirect from @PostConstruct
Asked Answered
A

3

2

I have page1 with button that navigates to page2, page 2 add some messages and navigates back to page1. I want display those messages on page1. I've tried many solutions, but nothing work.

Sample code page1.xhtml:

<p:commandButton value="edit" action="#{bean1.edit}"/>

In the managed bean:

public String edit() {
  return "page2?faces-redirect=true";
}

page2 managed bean

@PostConstruct
private void postConstruct() {
  Faces.getFlash().setKeepMessages(true);
  Messages.addFlashGlobalError("cannot edit!");
  Faces.navigate("page1?faces-redirect=true");
}

Both beans are view scoped and both pages have <p:messages> at the end of body.

Aeolian answered 3/10, 2012 at 12:6 Comment(1)
Have you tried to do it with Navigation?Prostration
R
1

First of all, I'm not entirely sure that the @PostConstruct is the best place to perform a redirect. See this. That being said, google turned up this and it looks reasonable. Try redirecting within the facelets page itself with a preRender event tag close to the top of the page. Cheers

Rupertruperta answered 4/10, 2012 at 4:4 Comment(1)
At first I used ocpsoft.org/java/… but it didn't work, I had to change afterPhase() and now it's OK.Aeolian
T
3

That can happen if the @PostConstruct is invoked too late. Apparently the bean is referenced and thus constructed for the first time relatively "late" in the view (e.g. in the very bottom). At that point, the response may be already committed which is a point of no return. You cannot navigate to a different view anymore.

You basically want to invoke the init() method before render response. With OmniFaces, you can use the following approach in page2.xhtml:

<f:metadata>
    <f:viewParam name="dummy" />
    <f:event type="postInvokeAction" listener="#{bean.init}" />
</f:metadata>

(you can remove the <f:viewParam name="dummy" /> if you already have your own view parameters on that page; it's just to ensure that INVOKE_ACTION phase is executed, see also postInvokeAction demo page)

and just a simple <f:event listener> method:

public void init() {
    Messages.addFlashGlobalError("cannot edit!");
    Faces.navigate("page1?faces-redirect=true"); // Or Faces.redirect("page1.xhtml");
}

The Faces.getFlash().setKeepMessages(true); is unnecessary as Messages#addFlashGlobalError() already does that. Please keep in mind that in Mojarra the Flash scope won't work if the navigation is to a different folder in the URL. The both pages have to be in the same folder in the URL. This is fixed in upcoming Mojarra 2.1.14.

Trapshooting answered 4/10, 2012 at 14:43 Comment(0)
R
1

First of all, I'm not entirely sure that the @PostConstruct is the best place to perform a redirect. See this. That being said, google turned up this and it looks reasonable. Try redirecting within the facelets page itself with a preRender event tag close to the top of the page. Cheers

Rupertruperta answered 4/10, 2012 at 4:4 Comment(1)
At first I used ocpsoft.org/java/… but it didn't work, I had to change afterPhase() and now it's OK.Aeolian
P
-1

Just use nevigation. It will surely work. check following code. public String redirect() throws Exception { FacesContext.getCurrentInstance().addMessage("Msg1",new FacesMessage("Message 1 is")); //FacesContext.getCurrentInstance().getExternalContext().redirect("/Sam/page2.jsf"); return "page2"; }

Prostration answered 4/10, 2012 at 7:58 Comment(1)
But I need to redirect from PostConstruct or preRenderView, these are void methods...Aeolian

© 2022 - 2024 — McMap. All rights reserved.