From 5c5d1c322f3a25adf475c595bb779064df0d7d7e Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Wed, 7 Apr 2010 18:52:27 +0000 Subject: [PATCH] SWF-1187 Applied patch attached to JIRA issue, polished unit test a little, and did some testing. --- .../FlowFacesContextMessageDelegate.java | 31 +++++++++++++- .../faces/webflow/FlowFacesContextTests.java | 40 +++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContextMessageDelegate.java b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContextMessageDelegate.java index 3d9bcb9d..f1395320 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContextMessageDelegate.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/FlowFacesContextMessageDelegate.java @@ -1,5 +1,8 @@ package org.springframework.faces.webflow; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -271,7 +274,7 @@ public class FlowFacesContextMessageDelegate { /** * Adapter class to convert a {@link FacesMessage} to a Spring {@link Message}. This adapter is required to allow * FacesMessages to be registered with spring while still retaining their mutable nature. It is not - * uncommon for FacesMessages to be changed after they gave been added to a FacesContext, for + * uncommon for FacesMessages to be changed after they have been added to a FacesContext, for * example, from a PhaseListener. *

* NOTE: Only {@link javax.faces.application.FacesMessage} instances are directly adapted, any subclasses will be @@ -282,8 +285,8 @@ public class FlowFacesContextMessageDelegate { private static class FlowFacesMessageAdapter extends Message implements MessageResolver { private String key; - private FacesMessage facesMessage; private String source; + private transient FacesMessage facesMessage; public FlowFacesMessageAdapter(String source, String key, FacesMessage message) { super(null, null, null); @@ -292,6 +295,30 @@ public class FlowFacesContextMessageDelegate { this.facesMessage = asStandardFacesMessageInstance(message); } + // Custom serialization to work around myfaces bug MYFACES-1347 + + private void writeObject(ObjectOutputStream oos) throws IOException { + oos.defaultWriteObject(); + oos.writeObject(facesMessage.getSummary()); + oos.writeObject(facesMessage.getDetail()); + oos.writeInt(facesMessage.getSeverity().getOrdinal()); + } + + private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { + ois.defaultReadObject(); + String summary = (String) ois.readObject(); + String detail = (String) ois.readObject(); + int severityOrdinal = ois.readInt(); + FacesMessage.Severity severity = FacesMessage.SEVERITY_INFO; + for (Iterator iterator = FacesMessage.VALUES.iterator(); iterator.hasNext();) { + FacesMessage.Severity value = (FacesMessage.Severity) iterator.next(); + if (value.getOrdinal() == severityOrdinal) { + severity = value; + } + } + facesMessage = new FacesMessage(severity, summary, detail); + } + /** * Use standard faces message as required to protect against bugs such as SWF-1073. * diff --git a/spring-faces/src/test/java/org/springframework/faces/webflow/FlowFacesContextTests.java b/spring-faces/src/test/java/org/springframework/faces/webflow/FlowFacesContextTests.java index 79285497..6732752c 100644 --- a/spring-faces/src/test/java/org/springframework/faces/webflow/FlowFacesContextTests.java +++ b/spring-faces/src/test/java/org/springframework/faces/webflow/FlowFacesContextTests.java @@ -1,5 +1,10 @@ package org.springframework.faces.webflow; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -176,6 +181,41 @@ public class FlowFacesContextTests extends TestCase { assertEquals(3, iterationCount); } + public final void testMessagesAreSerializable() throws Exception { + DefaultMessageContext messageContext = new DefaultMessageContext(); + EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext); + EasyMock.replay(new Object[] { requestContext }); + + facesContext.addMessage("TESTID", new FacesMessage("summary1")); + FacesMessage sourceMessage = (FacesMessage) facesContext.getMessages("TESTID").next(); + sourceMessage.setSummary("summary2"); + sourceMessage.setSeverity(FacesMessage.SEVERITY_FATAL); + + Serializable mementoWrite = messageContext.createMessagesMemento(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(mementoWrite); + oos.flush(); + byte[] byteArray = bos.toByteArray(); + oos.close(); + + ByteArrayInputStream bis = new ByteArrayInputStream(byteArray); + ObjectInputStream ois = new ObjectInputStream(bis); + Serializable mementoRead = (Serializable) ois.readObject(); + ois.close(); + + messageContext.restoreMessages(mementoRead); + EasyMock.reset(new Object[] { requestContext }); + EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext); + EasyMock.replay(new Object[] { requestContext }); + + FacesContext newFacesContext = new FlowFacesContext(requestContext, jsf.facesContext()); + assertSame(FacesContext.getCurrentInstance(), newFacesContext); + FacesMessage gotMessage = (FacesMessage) newFacesContext.getMessages("TESTID").next(); + assertEquals("summary2", gotMessage.getSummary()); + assertEquals(FacesMessage.SEVERITY_FATAL, gotMessage.getSeverity()); + } + public final void testGetMaximumSeverity() { messageContext = prepopulatedMessageContext; EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);