我有以下commandButton操作方法处理程序:
public String reject()
{
//Do something
addMessage(null, "rejectAmountInvalid", FacesMessage.SEVERITY_ERROR);
redirectToPortlet("/xxx/inbox?source=pendingActions#pendingApproval");
}
public static void addMessage(String clientId, String key, Severity level, Object... objArr)
{
FacesContext context = FacesContext.getCurrentInstance();
FacesMessage message = null;
String msg = getTextFromResourceBundle(key);
if (objArr != null && objArr.length > 0)
msg = MessageFormat.format(msg, objArr);
message = new FacesMessage(msg);
message.setSeverity(level);
context.addMessage(clientId, message);
}
public static void redirectToPortlet(String urlToRedirect)
{
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext externalContext = context.getExternalContext();
try
{
PortletRequest portletRequest = (PortletRequest) externalContext.getRequest();
ThemeDisplay themeDisplay = (ThemeDisplay) portletRequest.getAttribute("THEME_DISPLAY");
String portalURL = themeDisplay.getPortalURL();
String redirect = portalURL + urlToRedirect;
externalContext.redirect(redirect);
}
catch (Throwable e)
{
logger.log("Exception in redirectToPortlet to the URL: " + urlToRedirect, VLevel.ERROR, e);
}
}
当页面重定向到“/ xxx / inbox?source = pendingActions#pendingApproval”时,我添加的错误消息将丢失。有没有办法在JSF 2.1中保留错误消息?
由于 斯
答案 0 :(得分:7)
您可以使用PhaseListener保存未显示的下一个请求的消息。
我在Lincoln Baxter的博文Persist and pass FacesMessages over multiple page redirects中使用了一段时间,您只需将课程复制到某个软件包并在faces-config.xml
上注册。
博客文章中没有明确提及,但我假设代码是公共领域,所以我在这里发布一个更独立的答案:
package com.yoursite.jsf;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
/**
* Enables messages to be rendered on different pages from which they were set.
*
* After each phase where messages may be added, this moves the messages
* from the page-scoped FacesContext to the session-scoped session map.
*
* Before messages are rendered, this moves the messages from the
* session-scoped session map back to the page-scoped FacesContext.
*
* Only global messages, not associated with a particular component, are
* moved. Component messages cannot be rendered on pages other than the one on
* which they were added.
*
* To enable multi-page messages support, add a <code>lifecycle</code> block to your
* faces-config.xml file. That block should contain a single
* <code>phase-listener</code> block containing the fully-qualified classname
* of this file.
*
* @author Jesse Wilson jesse[AT]odel.on.ca
* @secondaryAuthor Lincoln Baxter III lincoln[AT]ocpsoft.com
*/
public class MultiPageMessagesSupport implements PhaseListener
{
private static final long serialVersionUID = 1250469273857785274L;
private static final String sessionToken = "MULTI_PAGE_MESSAGES_SUPPORT";
public PhaseId getPhaseId()
{
return PhaseId.ANY_PHASE;
}
/*
* Check to see if we are "naturally" in the RENDER_RESPONSE phase. If we
* have arrived here and the response is already complete, then the page is
* not going to show up: don't display messages yet.
*/
// TODO: Blog this (MultiPageMessagesSupport)
public void beforePhase(final PhaseEvent event)
{
FacesContext facesContext = event.getFacesContext();
this.saveMessages(facesContext);
if (PhaseId.RENDER_RESPONSE.equals(event.getPhaseId()))
{
if (!facesContext.getResponseComplete())
{
this.restoreMessages(facesContext);
}
}
}
/*
* Save messages into the session after every phase.
*/
public void afterPhase(final PhaseEvent event)
{
if (!PhaseId.RENDER_RESPONSE.equals(event.getPhaseId()))
{
FacesContext facesContext = event.getFacesContext();
this.saveMessages(facesContext);
}
}
@SuppressWarnings("unchecked")
private int saveMessages(final FacesContext facesContext)
{
List<FacesMessage> messages = new ArrayList<FacesMessage>();
for (Iterator<FacesMessage> iter = facesContext.getMessages(null); iter.hasNext();)
{
messages.add(iter.next());
iter.remove();
}
if (messages.size() == 0)
{
return 0;
}
Map<String, Object> sessionMap = facesContext.getExternalContext().getSessionMap();
List<FacesMessage> existingMessages = (List<FacesMessage>) sessionMap.get(sessionToken);
if (existingMessages != null)
{
existingMessages.addAll(messages);
}
else
{
sessionMap.put(sessionToken, messages);
}
return messages.size();
}
@SuppressWarnings("unchecked")
private int restoreMessages(final FacesContext facesContext)
{
Map<String, Object> sessionMap = facesContext.getExternalContext().getSessionMap();
List<FacesMessage> messages = (List<FacesMessage>) sessionMap.remove(sessionToken);
if (messages == null)
{
return 0;
}
int restoredCount = messages.size();
for (Object element : messages)
{
facesContext.addMessage(null, (FacesMessage) element);
}
return restoredCount;
}
}
然后,在faces-config.xml
:
<phase-listener>com.yoursite.jsf.MultiPageMessagesSupport</phase-listener>
答案 1 :(得分:7)
如果重定向位于同一路径,则可以使用Flash#setKeepMessages()
。
context.getExternalContext().getFlash().setKeepMessages(true);
这样,消息将持久保存在闪存范围内,只要单个后续GET请求(在重定向期间发生)就会有效地生效。