SWF-1017 - FlowFacesContext does not return the same FacesMessages instances
SWF-985 - Multiple JSF validators duplicate messages
This commit is contained in:
@@ -16,9 +16,7 @@
|
||||
package org.springframework.faces.webflow;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.el.ELContext;
|
||||
import javax.faces.FactoryFinder;
|
||||
@@ -33,14 +31,8 @@ import javax.faces.context.ResponseWriter;
|
||||
import javax.faces.lifecycle.Lifecycle;
|
||||
import javax.faces.render.RenderKit;
|
||||
|
||||
import org.springframework.binding.message.Message;
|
||||
import org.springframework.binding.message.MessageBuilder;
|
||||
import org.springframework.binding.message.MessageCriteria;
|
||||
import org.springframework.binding.message.MessageResolver;
|
||||
import org.springframework.binding.message.Severity;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
@@ -50,6 +42,7 @@ import org.springframework.webflow.execution.RequestContext;
|
||||
* requests in the case of the POST+REDIRECT+GET pattern being enabled.
|
||||
*
|
||||
* @author Jeremy Grelle
|
||||
* @author Phil Webb
|
||||
*/
|
||||
public class FlowFacesContext extends FacesContext {
|
||||
|
||||
@@ -58,21 +51,13 @@ public class FlowFacesContext extends FacesContext {
|
||||
*/
|
||||
static final String RENDER_RESPONSE_KEY = "flowRenderResponse";
|
||||
|
||||
/**
|
||||
* Key for identifying summary messages
|
||||
*/
|
||||
static final String SUMMARY_MESSAGE_KEY = "_summary";
|
||||
|
||||
/**
|
||||
* Key for identifying detail messages
|
||||
*/
|
||||
static final String DETAIL_MESSAGE_KEY = "_detail";
|
||||
|
||||
/**
|
||||
* The key for storing the renderResponse flag
|
||||
*/
|
||||
private RequestContext context;
|
||||
|
||||
private FlowFacesContextMessageDelegate messageDelegate;
|
||||
|
||||
/**
|
||||
* The base FacesContext delegate
|
||||
*/
|
||||
@@ -90,6 +75,7 @@ public class FlowFacesContext extends FacesContext {
|
||||
public FlowFacesContext(RequestContext context, FacesContext delegate) {
|
||||
this.context = context;
|
||||
this.delegate = delegate;
|
||||
this.messageDelegate = new FlowFacesContextMessageDelegate(context);
|
||||
setCurrentInstance(this);
|
||||
}
|
||||
|
||||
@@ -97,61 +83,14 @@ public class FlowFacesContext extends FacesContext {
|
||||
* Translates a FacesMessage to an SWF Message and adds it to the current MessageContext
|
||||
*/
|
||||
public void addMessage(String clientId, FacesMessage message) {
|
||||
String source = null;
|
||||
if (StringUtils.hasText(clientId)) {
|
||||
source = clientId;
|
||||
}
|
||||
|
||||
StringBuffer summaryText = new StringBuffer();
|
||||
if (StringUtils.hasText(message.getSummary())) {
|
||||
summaryText.append(message.getSummary());
|
||||
}
|
||||
|
||||
String summarySource = source + SUMMARY_MESSAGE_KEY;
|
||||
MessageResolver summaryResolver;
|
||||
if (message.getSeverity() == FacesMessage.SEVERITY_INFO) {
|
||||
summaryResolver = new MessageBuilder().source(summarySource).defaultText(summaryText.toString()).info()
|
||||
.build();
|
||||
} else if (message.getSeverity() == FacesMessage.SEVERITY_WARN) {
|
||||
summaryResolver = new MessageBuilder().source(summarySource).defaultText(summaryText.toString()).warning()
|
||||
.build();
|
||||
} else if (message.getSeverity() == FacesMessage.SEVERITY_ERROR) {
|
||||
summaryResolver = new MessageBuilder().source(summarySource).defaultText(summaryText.toString()).error()
|
||||
.build();
|
||||
} else {
|
||||
summaryResolver = new MessageBuilder().source(summarySource).defaultText(summaryText.toString()).fatal()
|
||||
.build();
|
||||
}
|
||||
context.getMessageContext().addMessage(summaryResolver);
|
||||
|
||||
StringBuffer detailText = new StringBuffer();
|
||||
if (StringUtils.hasText(message.getDetail())) {
|
||||
detailText.append(message.getDetail());
|
||||
}
|
||||
String detailSource = source + DETAIL_MESSAGE_KEY;
|
||||
MessageResolver detailResolver;
|
||||
if (message.getSeverity() == FacesMessage.SEVERITY_INFO) {
|
||||
detailResolver = new MessageBuilder().source(detailSource).defaultText(detailText.toString()).info()
|
||||
.build();
|
||||
} else if (message.getSeverity() == FacesMessage.SEVERITY_WARN) {
|
||||
detailResolver = new MessageBuilder().source(detailSource).defaultText(detailText.toString()).warning()
|
||||
.build();
|
||||
} else if (message.getSeverity() == FacesMessage.SEVERITY_ERROR) {
|
||||
detailResolver = new MessageBuilder().source(detailSource).defaultText(detailText.toString()).error()
|
||||
.build();
|
||||
} else {
|
||||
detailResolver = new MessageBuilder().source(detailSource).defaultText(detailText.toString()).fatal()
|
||||
.build();
|
||||
}
|
||||
context.getMessageContext().addMessage(detailResolver);
|
||||
|
||||
messageDelegate.addMessage(clientId, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Iterator for all component clientId's for which messages have been added.
|
||||
*/
|
||||
public Iterator getClientIdsWithMessages() {
|
||||
return new ClientIdIterator();
|
||||
return messageDelegate.getClientIdsWithMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,27 +98,14 @@ public class FlowFacesContext extends FacesContext {
|
||||
* associated with any specific UIComponent. If no such messages have been queued, return null.
|
||||
*/
|
||||
public FacesMessage.Severity getMaximumSeverity() {
|
||||
if (context.getMessageContext().getAllMessages().length == 0) {
|
||||
return null;
|
||||
}
|
||||
FacesMessage.Severity max = FacesMessage.SEVERITY_INFO;
|
||||
Iterator i = getMessages();
|
||||
while (i.hasNext()) {
|
||||
FacesMessage message = (FacesMessage) i.next();
|
||||
if (message.getSeverity().getOrdinal() > max.getOrdinal()) {
|
||||
max = message.getSeverity();
|
||||
}
|
||||
if (max.getOrdinal() == FacesMessage.SEVERITY_FATAL.getOrdinal())
|
||||
break;
|
||||
}
|
||||
return max;
|
||||
return messageDelegate.getMaximumSeverity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Iterator for all Messages in the current MessageContext that does translation to FacesMessages.
|
||||
*/
|
||||
public Iterator getMessages() {
|
||||
return new FacesMessageIterator();
|
||||
return messageDelegate.getMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,7 +113,7 @@ public class FlowFacesContext extends FacesContext {
|
||||
* to FacesMessages.
|
||||
*/
|
||||
public Iterator getMessages(String clientId) {
|
||||
return new FacesMessageIterator(clientId);
|
||||
return messageDelegate.getMessages(clientId);
|
||||
}
|
||||
|
||||
public boolean getRenderResponse() {
|
||||
@@ -273,100 +199,6 @@ public class FlowFacesContext extends FacesContext {
|
||||
|
||||
// ------------------ Private helper methods ----------------------//
|
||||
|
||||
private FacesMessage toFacesMessage(Message summaryMessage, Message detailMessage) {
|
||||
if (summaryMessage.getSeverity() == Severity.INFO) {
|
||||
return new FacesMessage(FacesMessage.SEVERITY_INFO, summaryMessage.getText(), detailMessage.getText());
|
||||
} else if (summaryMessage.getSeverity() == Severity.WARNING) {
|
||||
return new FacesMessage(FacesMessage.SEVERITY_WARN, summaryMessage.getText(), detailMessage.getText());
|
||||
} else if (summaryMessage.getSeverity() == Severity.ERROR) {
|
||||
return new FacesMessage(FacesMessage.SEVERITY_ERROR, summaryMessage.getText(), detailMessage.getText());
|
||||
} else {
|
||||
return new FacesMessage(FacesMessage.SEVERITY_FATAL, summaryMessage.getText(), detailMessage.getText());
|
||||
}
|
||||
}
|
||||
|
||||
private class FacesMessageIterator implements Iterator {
|
||||
|
||||
private Object[] messages;
|
||||
|
||||
private int currentIndex = -1;
|
||||
|
||||
protected FacesMessageIterator() {
|
||||
Message[] summaryMessages = context.getMessageContext().getMessagesByCriteria(new SummaryMessageCriteria());
|
||||
Message[] detailMessages = context.getMessageContext().getMessagesByCriteria(new DetailMessageCriteria());
|
||||
Message[] userMessages = context.getMessageContext().getMessagesByCriteria(new UserMessageCriteria());
|
||||
|
||||
List translatedMessages = new ArrayList();
|
||||
for (int i = 0; i < summaryMessages.length; i++) {
|
||||
translatedMessages.add(toFacesMessage(summaryMessages[i], detailMessages[i]));
|
||||
}
|
||||
for (int z = 0; z < userMessages.length; z++) {
|
||||
translatedMessages.add(toFacesMessage(userMessages[z], userMessages[z]));
|
||||
}
|
||||
|
||||
this.messages = translatedMessages.toArray();
|
||||
}
|
||||
|
||||
protected FacesMessageIterator(String clientId) {
|
||||
Message[] summaryMessages = context.getMessageContext().getMessagesBySource(clientId + SUMMARY_MESSAGE_KEY);
|
||||
Message[] detailMessages = context.getMessageContext().getMessagesBySource(clientId + DETAIL_MESSAGE_KEY);
|
||||
Message[] userMessages = context.getMessageContext().getMessagesBySource(clientId);
|
||||
|
||||
List translatedMessages = new ArrayList();
|
||||
for (int i = 0; i < summaryMessages.length; i++) {
|
||||
translatedMessages.add(toFacesMessage(summaryMessages[i], detailMessages[i]));
|
||||
}
|
||||
for (int z = 0; z < userMessages.length; z++) {
|
||||
translatedMessages.add(toFacesMessage(userMessages[z], userMessages[z]));
|
||||
}
|
||||
|
||||
this.messages = translatedMessages.toArray();
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return messages.length > currentIndex + 1;
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
currentIndex++;
|
||||
return messages[currentIndex];
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Messages cannot be removed through this iterator.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class ClientIdIterator implements Iterator {
|
||||
|
||||
private Message[] messages;
|
||||
|
||||
int currentIndex = -1;
|
||||
|
||||
protected ClientIdIterator() {
|
||||
this.messages = context.getMessageContext().getMessagesByCriteria(new IdentifiedMessageCriteria());
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return messages.length > currentIndex + 1;
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
Message next = messages[++currentIndex];
|
||||
if (next.getSource().toString().endsWith(SUMMARY_MESSAGE_KEY)) {
|
||||
return next.getSource().toString().replaceAll(SUMMARY_MESSAGE_KEY, "");
|
||||
} else {
|
||||
return next.getSource().toString();
|
||||
}
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Messages cannot be removed through this iterator.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class FlowExternalContext extends ExternalContextWrapper {
|
||||
|
||||
private static final String CUSTOM_RESPONSE = "customResponse";
|
||||
@@ -391,49 +223,4 @@ public class FlowFacesContext extends FacesContext {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class SummaryMessageCriteria implements MessageCriteria {
|
||||
|
||||
public boolean test(Message message) {
|
||||
if (message.getSource() == null) {
|
||||
return false;
|
||||
}
|
||||
return message.getSource().toString().endsWith(SUMMARY_MESSAGE_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
private class DetailMessageCriteria implements MessageCriteria {
|
||||
|
||||
public boolean test(Message message) {
|
||||
if (message.getSource() == null) {
|
||||
return false;
|
||||
}
|
||||
return message.getSource().toString().endsWith(DETAIL_MESSAGE_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
private class UserMessageCriteria implements MessageCriteria {
|
||||
|
||||
public boolean test(Message message) {
|
||||
if (message.getSource() == null) {
|
||||
return true;
|
||||
}
|
||||
return !message.getSource().toString().endsWith(SUMMARY_MESSAGE_KEY)
|
||||
&& !message.getSource().toString().endsWith(DETAIL_MESSAGE_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
private class IdentifiedMessageCriteria implements MessageCriteria {
|
||||
|
||||
String nullSummaryId = null + SUMMARY_MESSAGE_KEY;
|
||||
|
||||
public boolean test(Message message) {
|
||||
if (message.getSource() == null || message.getSource().equals("")
|
||||
|| message.getSource().equals(nullSummaryId)
|
||||
|| message.getSource().toString().endsWith(DETAIL_MESSAGE_KEY)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,337 @@
|
||||
package org.springframework.faces.webflow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.faces.application.FacesMessage;
|
||||
import javax.faces.context.FacesContext;
|
||||
|
||||
import org.springframework.binding.message.Message;
|
||||
import org.springframework.binding.message.MessageCriteria;
|
||||
import org.springframework.binding.message.MessageResolver;
|
||||
import org.springframework.binding.message.Severity;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Helper delegate class for use with the {@link FlowFacesContext} that handles all faces message methods.
|
||||
*
|
||||
* @author Jeremy Grelle
|
||||
* @author Phil Webb
|
||||
*/
|
||||
public class FlowFacesContextMessageDelegate {
|
||||
|
||||
private RequestContext context;
|
||||
|
||||
/**
|
||||
* Key for identifying summary messages
|
||||
*/
|
||||
static final String SUMMARY_MESSAGE_KEY = "_summary";
|
||||
|
||||
/**
|
||||
* Key for identifying detail messages
|
||||
*/
|
||||
static final String DETAIL_MESSAGE_KEY = "_detail";
|
||||
|
||||
/**
|
||||
* Mappings between {@link FacesMessage} and {@link Severity}.
|
||||
*/
|
||||
private static final Map FACESSEVERITY_TO_SPRINGSEVERITY;
|
||||
static {
|
||||
FACESSEVERITY_TO_SPRINGSEVERITY = new HashMap();
|
||||
FACESSEVERITY_TO_SPRINGSEVERITY.put(FacesMessage.SEVERITY_INFO, Severity.INFO);
|
||||
FACESSEVERITY_TO_SPRINGSEVERITY.put(FacesMessage.SEVERITY_WARN, Severity.WARNING);
|
||||
FACESSEVERITY_TO_SPRINGSEVERITY.put(FacesMessage.SEVERITY_ERROR, Severity.ERROR);
|
||||
}
|
||||
|
||||
public FlowFacesContextMessageDelegate(RequestContext context) {
|
||||
super();
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see FlowFacesContext#addMessage(String, FacesMessage)
|
||||
*/
|
||||
public void addMessage(String clientId, FacesMessage message) {
|
||||
String source = null;
|
||||
if (StringUtils.hasText(clientId)) {
|
||||
source = clientId;
|
||||
}
|
||||
context.getMessageContext().addMessage(new FlowFacesMessageAdapter(source, SUMMARY_MESSAGE_KEY, message));
|
||||
context.getMessageContext().addMessage(new FlowFacesMessageAdapter(source, DETAIL_MESSAGE_KEY, message));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see FlowFacesContext#getClientIdsWithMessages
|
||||
*/
|
||||
public Iterator getClientIdsWithMessages() {
|
||||
return new ClientIdIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see FlowFacesContext#getMaximumSeverity()
|
||||
*/
|
||||
public FacesMessage.Severity getMaximumSeverity() {
|
||||
if (context.getMessageContext().getAllMessages().length == 0) {
|
||||
return null;
|
||||
}
|
||||
FacesMessage.Severity max = FacesMessage.SEVERITY_INFO;
|
||||
Iterator i = getMessages();
|
||||
while (i.hasNext()) {
|
||||
FacesMessage message = (FacesMessage) i.next();
|
||||
if (message.getSeverity().getOrdinal() > max.getOrdinal()) {
|
||||
max = message.getSeverity();
|
||||
}
|
||||
if (max.getOrdinal() == FacesMessage.SEVERITY_FATAL.getOrdinal())
|
||||
break;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see FlowFacesContext#getMessages()
|
||||
*/
|
||||
public Iterator getMessages() {
|
||||
return new FacesMessageIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see FlowFacesContext#getMessages(String)
|
||||
*/
|
||||
public Iterator getMessages(String clientId) {
|
||||
return new FacesMessageIterator(clientId);
|
||||
}
|
||||
|
||||
// ------------------ Private helper methods ----------------------//
|
||||
|
||||
private FacesMessage toFacesMessage(Message summaryMessage, Message detailMessage) {
|
||||
|
||||
// If we can return the actual message instance.
|
||||
if (summaryMessage instanceof FlowFacesMessageAdapter) {
|
||||
return ((FlowFacesMessageAdapter) summaryMessage).getFacesMessage();
|
||||
}
|
||||
if (detailMessage instanceof FlowFacesMessageAdapter) {
|
||||
return ((FlowFacesMessageAdapter) detailMessage).getFacesMessage();
|
||||
}
|
||||
|
||||
// If we have not got an actual instance adapt the message
|
||||
if (summaryMessage.getSeverity() == Severity.INFO) {
|
||||
return new FacesMessage(FacesMessage.SEVERITY_INFO, summaryMessage.getText(), detailMessage.getText());
|
||||
} else if (summaryMessage.getSeverity() == Severity.WARNING) {
|
||||
return new FacesMessage(FacesMessage.SEVERITY_WARN, summaryMessage.getText(), detailMessage.getText());
|
||||
} else if (summaryMessage.getSeverity() == Severity.ERROR) {
|
||||
return new FacesMessage(FacesMessage.SEVERITY_ERROR, summaryMessage.getText(), detailMessage.getText());
|
||||
} else {
|
||||
return new FacesMessage(FacesMessage.SEVERITY_FATAL, summaryMessage.getText(), detailMessage.getText());
|
||||
}
|
||||
}
|
||||
|
||||
private class FacesMessageIterator implements Iterator {
|
||||
|
||||
private Object[] messages;
|
||||
|
||||
private int currentIndex = -1;
|
||||
|
||||
protected FacesMessageIterator() {
|
||||
Message[] summaryMessages = context.getMessageContext().getMessagesByCriteria(new SummaryMessageCriteria());
|
||||
Message[] detailMessages = context.getMessageContext().getMessagesByCriteria(new DetailMessageCriteria());
|
||||
Message[] userMessages = context.getMessageContext().getMessagesByCriteria(new UserMessageCriteria());
|
||||
|
||||
List translatedMessages = new ArrayList();
|
||||
for (int i = 0; i < summaryMessages.length; i++) {
|
||||
translatedMessages.add(toFacesMessage(summaryMessages[i], detailMessages[i]));
|
||||
}
|
||||
for (int z = 0; z < userMessages.length; z++) {
|
||||
translatedMessages.add(toFacesMessage(userMessages[z], userMessages[z]));
|
||||
}
|
||||
|
||||
this.messages = translatedMessages.toArray();
|
||||
}
|
||||
|
||||
protected FacesMessageIterator(String clientId) {
|
||||
Message[] summaryMessages = context.getMessageContext().getMessagesBySource(clientId + SUMMARY_MESSAGE_KEY);
|
||||
Message[] detailMessages = context.getMessageContext().getMessagesBySource(clientId + DETAIL_MESSAGE_KEY);
|
||||
Message[] userMessages = context.getMessageContext().getMessagesBySource(clientId);
|
||||
|
||||
List translatedMessages = new ArrayList();
|
||||
for (int i = 0; i < summaryMessages.length; i++) {
|
||||
translatedMessages.add(toFacesMessage(summaryMessages[i], detailMessages[i]));
|
||||
}
|
||||
for (int z = 0; z < userMessages.length; z++) {
|
||||
translatedMessages.add(toFacesMessage(userMessages[z], userMessages[z]));
|
||||
}
|
||||
|
||||
this.messages = translatedMessages.toArray();
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return messages.length > currentIndex + 1;
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
currentIndex++;
|
||||
return messages[currentIndex];
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Messages cannot be removed through this iterator.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class ClientIdIterator implements Iterator {
|
||||
|
||||
private Message[] messages;
|
||||
|
||||
int currentIndex = -1;
|
||||
|
||||
protected ClientIdIterator() {
|
||||
this.messages = context.getMessageContext().getMessagesByCriteria(new IdentifiedMessageCriteria());
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return messages.length > currentIndex + 1;
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
Message next = messages[++currentIndex];
|
||||
if (next.getSource().toString().endsWith(SUMMARY_MESSAGE_KEY)) {
|
||||
return next.getSource().toString().replaceAll(SUMMARY_MESSAGE_KEY, "");
|
||||
} else {
|
||||
return next.getSource().toString();
|
||||
}
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Messages cannot be removed through this iterator.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class SummaryMessageCriteria implements MessageCriteria {
|
||||
|
||||
public boolean test(Message message) {
|
||||
if (message.getSource() == null) {
|
||||
return false;
|
||||
}
|
||||
return message.getSource().toString().endsWith(SUMMARY_MESSAGE_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
private class DetailMessageCriteria implements MessageCriteria {
|
||||
|
||||
public boolean test(Message message) {
|
||||
if (message.getSource() == null) {
|
||||
return false;
|
||||
}
|
||||
return message.getSource().toString().endsWith(DETAIL_MESSAGE_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
private class UserMessageCriteria implements MessageCriteria {
|
||||
|
||||
public boolean test(Message message) {
|
||||
if (message.getSource() == null) {
|
||||
return true;
|
||||
}
|
||||
return !message.getSource().toString().endsWith(SUMMARY_MESSAGE_KEY)
|
||||
&& !message.getSource().toString().endsWith(DETAIL_MESSAGE_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
private class IdentifiedMessageCriteria implements MessageCriteria {
|
||||
|
||||
String nullSummaryId = null + SUMMARY_MESSAGE_KEY;
|
||||
|
||||
private Set identifiedMessageSources = new HashSet();
|
||||
|
||||
public boolean test(Message message) {
|
||||
if (message.getSource() == null || message.getSource().equals("")
|
||||
|| message.getSource().equals(nullSummaryId)
|
||||
|| message.getSource().toString().endsWith(DETAIL_MESSAGE_KEY)) {
|
||||
return false;
|
||||
}
|
||||
return identifiedMessageSources.add(message.getSource());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapter class to convert a {@link FacesMessage} to a Spring {@link Message}. This adapter is required to allow
|
||||
* <tt>FacesMessages</tt> to be registered with spring while still retaining their mutable nature. It is not
|
||||
* uncommon for <tt>FacesMessages</tt> to be changed after they gave been added to a <tt>FacesContext</tt>, for
|
||||
* example, from a <tt>PhaseListener</tt>.
|
||||
* <p>
|
||||
* For convenience this class also implements the {@link MessageResolver} interface.
|
||||
*/
|
||||
private static class FlowFacesMessageAdapter extends Message implements MessageResolver {
|
||||
|
||||
private String key;
|
||||
private FacesMessage facesMessage;
|
||||
private String source;
|
||||
|
||||
public FlowFacesMessageAdapter(String source, String key, FacesMessage message) {
|
||||
super(null, null, null);
|
||||
this.source = source;
|
||||
this.key = key;
|
||||
this.facesMessage = message;
|
||||
}
|
||||
|
||||
public Object getSource() {
|
||||
return source + key;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
String text = null;
|
||||
if (DETAIL_MESSAGE_KEY.equals(key)) {
|
||||
text = facesMessage.getDetail();
|
||||
} else if (SUMMARY_MESSAGE_KEY.equals(key)) {
|
||||
text = facesMessage.getSummary();
|
||||
} else {
|
||||
throw new RuntimeException("Unknown faces message type key");
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(text)) {
|
||||
return text;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public Severity getSeverity() {
|
||||
Severity severity = null;
|
||||
if (facesMessage.getSeverity() != null) {
|
||||
severity = (Severity) FACESSEVERITY_TO_SPRINGSEVERITY.get(facesMessage.getSeverity());
|
||||
}
|
||||
return (severity == null ? Severity.INFO : severity);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
ToStringCreator rtn = new ToStringCreator(this);
|
||||
rtn.append("severity", getSeverity());
|
||||
if (FacesContext.getCurrentInstance() != null) {
|
||||
// Only append text if running within a faces context
|
||||
rtn.append("text", getText());
|
||||
}
|
||||
return rtn.toString();
|
||||
}
|
||||
|
||||
public Message resolveMessage(MessageSource messageSource, Locale locale) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The original {@link FacesMessage} adapted by this class.
|
||||
*/
|
||||
public FacesMessage getFacesMessage() {
|
||||
return facesMessage;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -12,9 +12,6 @@ import org.springframework.binding.message.DefaultMessageContext;
|
||||
import org.springframework.binding.message.Message;
|
||||
import org.springframework.binding.message.MessageBuilder;
|
||||
import org.springframework.binding.message.MessageContext;
|
||||
import org.springframework.binding.message.MessageCriteria;
|
||||
import org.springframework.binding.message.MessageResolver;
|
||||
import org.springframework.binding.message.Severity;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
public class FlowFacesContextTests extends TestCase {
|
||||
@@ -92,6 +89,24 @@ public class FlowFacesContextTests extends TestCase {
|
||||
assertEquals("There should be 5 messages to iterate", 5, iterationCount);
|
||||
}
|
||||
|
||||
public final void testMutableGetMessages() {
|
||||
messageContext = prepopulatedMessageContext;
|
||||
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
|
||||
EasyMock.replay(new Object[] { requestContext });
|
||||
|
||||
facesContext.addMessage("TESTID", new FacesMessage("summary1"));
|
||||
FacesMessage soruceMessage = (FacesMessage) facesContext.getMessages("TESTID").next();
|
||||
soruceMessage.setSummary("summary2");
|
||||
|
||||
// check that message sticks around even when the facesContext has been torn down and re-created during the
|
||||
// processing of the current request
|
||||
FacesContext newFacesContext = new FlowFacesContext(requestContext, jsf.facesContext());
|
||||
assertSame(FacesContext.getCurrentInstance(), newFacesContext);
|
||||
|
||||
FacesMessage gotMessage = (FacesMessage) newFacesContext.getMessages("TESTID").next();
|
||||
assertEquals("summary2", gotMessage.getSummary());
|
||||
}
|
||||
|
||||
public final void testGetMessagesByClientId_ForComponent() {
|
||||
messageContext = prepopulatedMessageContext;
|
||||
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
|
||||
@@ -180,46 +195,4 @@ public class FlowFacesContextTests extends TestCase {
|
||||
prepopulatedMessageContext.addMessage(new MessageBuilder().defaultText("Subzero Wins - Fatality").fatal()
|
||||
.build());
|
||||
}
|
||||
|
||||
private class TestGetMessagesContext implements MessageContext {
|
||||
|
||||
Message[] messages;
|
||||
|
||||
TestGetMessagesContext() {
|
||||
messages = new Message[7];
|
||||
messages[0] = new Message("null_summary", "foo", Severity.INFO);
|
||||
messages[1] = new Message("null_detail", "foo", Severity.INFO);
|
||||
messages[2] = new Message("componentId_summary", "bar", Severity.WARNING);
|
||||
messages[3] = new Message("componentId_detail", "bar", Severity.WARNING);
|
||||
messages[4] = new Message("userMessage", "userMessage", Severity.INFO);
|
||||
messages[5] = new Message("null_summary", "baz", Severity.ERROR);
|
||||
messages[6] = new Message("null_detail", "baz", Severity.ERROR);
|
||||
}
|
||||
|
||||
public void addMessage(MessageResolver messageResolver) {
|
||||
|
||||
}
|
||||
|
||||
public Message[] getAllMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
public Message[] getMessagesBySource(Object source) {
|
||||
return new Message[] { messages[1] };
|
||||
}
|
||||
|
||||
public Message[] getMessagesByCriteria(MessageCriteria criteria) {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public boolean hasErrorMessages() {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public void clearMessages() {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user