Added serializable variants of commonly used JSF data model classes (SWF-748)

This commit is contained in:
Erwin Vervaet
2008-09-06 14:13:11 +00:00
parent 8be104c4e1
commit 31be8ba9e6
6 changed files with 401 additions and 0 deletions

View File

@@ -21,6 +21,7 @@ Package org.springframework.webflow.executor
the flow execution (SWF-745).
* FlowPhaseListener will now save the JSF component state before a flow execution redirect is issued (SWF-747).
* Fixed FlowPhaseListener to correctly deal with scenarios where we fallback to standard JSF navigation.
* Added serializable variants of commonly used JSF data model classes (SWF-748).
* Fixed use of wrong flow execution key in externalRedirect view when using PortletFlowController (SWF-435).
Changes in version 1.0.5 (03.10.2007)

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2004-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.webflow.executor.jsf.model;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import javax.faces.model.DataModelListener;
/**
* Serializable variant of JSF's {@link javax.faces.model.ArrayDataModel}.
*
* @author Erwin Vervaet
*/
public class ArrayDataModel extends javax.faces.model.ArrayDataModel implements Externalizable {
/**
* Construct a new {@link ArrayDataModel} with no specified wrapped data.
*
* @see javax.faces.model.ArrayDataModel#ArrayDataModel()
*/
public ArrayDataModel() {
}
/**
* Construct a new {@link ArrayDataModel} wrapping the specified array.
* @param array the array to be wrapped, if any
*
* @see javax.faces.model.ArrayDataModel#ArrayDataModel(Object[])
*/
public ArrayDataModel(Object[] array) {
super(array);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
setWrappedData(in.readObject());
setRowIndex(in.readInt());
DataModelListener[] listeners = (DataModelListener[]) in.readObject();
for (int i = 0; i < listeners.length; i++) {
addDataModelListener(listeners[i]);
}
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(getWrappedData());
out.writeInt(getRowIndex());
out.writeObject(getDataModelListeners());
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2004-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.webflow.executor.jsf.model;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.List;
import javax.faces.model.DataModelListener;
/**
* Serializable variant of JSF's {@link javax.faces.model.ListDataModel}.
*
* @author Erwin Vervaet
*/
public class ListDataModel extends javax.faces.model.ListDataModel implements Externalizable {
/**
* Construct a new {@link ListDataModel} with no specified wrapped data.
*
* @see javax.faces.model.ListDataModel#ListDataModel()
*/
public ListDataModel() {
}
/**
* Construct a new {@link ListDataModel} wrapping the specified list.
* @param list the list to be wrapped, if any
*
* @see javax.faces.model.ListDataModel#ListDataModel(List)
*/
public ListDataModel(List list) {
super(list);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
setWrappedData(in.readObject());
setRowIndex(in.readInt());
DataModelListener[] listeners = (DataModelListener[]) in.readObject();
for (int i = 0; i < listeners.length; i++) {
addDataModelListener(listeners[i]);
}
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(getWrappedData());
out.writeInt(getRowIndex());
out.writeObject(getDataModelListeners());
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2004-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.webflow.executor.jsf.model;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import javax.faces.model.DataModelListener;
/**
* Serializable variant of JSF's {@link javax.faces.model.ScalarDataModel}.
*
* @author Erwin Vervaet
*/
public class ScalarDataModel extends javax.faces.model.ScalarDataModel implements Externalizable {
/**
* Construct a new {@link ScalarDataModel} with no specified wrapped data.
*
* @see javax.faces.model.ScalarDataModel#ScalarDataModel()
*/
public ScalarDataModel() {
}
/**
* Construct a new {@link ScalarDataModel} wrapping the specified object.
* @param scalar the object to wrap, if any
*
* @see javax.faces.model.ScalarDataModel#setWrappedData(Object)
*/
public ScalarDataModel(Object scalar) {
super(scalar);
}
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
setWrappedData(in.readObject());
setRowIndex(in.readInt());
DataModelListener[] listeners = (DataModelListener[]) in.readObject();
for (int i = 0; i < listeners.length; i++) {
addDataModelListener(listeners[i]);
}
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject(getWrappedData());
out.writeInt(getRowIndex());
out.writeObject(getDataModelListeners());
}
}

View File

@@ -0,0 +1,5 @@
<html>
<body>
<p>Provides serializable variants of commonly used JSF data model classes for use with Spring Web Flow.</p>
</body>
</html>

View File

@@ -0,0 +1,202 @@
/*
* Copyright 2004-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.webflow.executor.jsf.model;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EventListener;
import java.util.List;
import javax.faces.model.DataModelEvent;
import javax.faces.model.DataModelListener;
import junit.framework.TestCase;
/**
* Tests for the serializable JSF data model variants provided by Spring Web Flow.
*
* @author Erwin Vervaet
*/
public class SerializableDataModelTests extends TestCase {
public void testListDataModelSerializability() throws Exception {
// from scratch
ListDataModel ldm = (ListDataModel) writeAndReadBack(new ListDataModel());
assertNull(ldm.getWrappedData());
assertEquals(-1, ldm.getRowIndex());
assertEquals(0, ldm.getDataModelListeners().length);
// with input list
ldm = (ListDataModel) writeAndReadBack(new ListDataModel(sampleList()));
assertEquals(sampleList(), ldm.getWrappedData());
assertEquals(0, ldm.getRowIndex());
assertEquals(0, ldm.getDataModelListeners().length);
// manipulated
ldm = new ListDataModel(sampleList());
ldm.setRowIndex(1);
ldm = (ListDataModel) writeAndReadBack(ldm);
assertEquals(sampleList(), ldm.getWrappedData());
assertEquals(1, ldm.getRowIndex());
assertEquals(0, ldm.getDataModelListeners().length);
// with listeners
ldm = new ListDataModel(sampleList());
ldm.addDataModelListener(new TestDataModelListener("swf"));
ldm.setRowIndex(1);
ldm = (ListDataModel) writeAndReadBack(ldm);
assertEquals(sampleList(), ldm.getWrappedData());
assertEquals(1, ldm.getRowIndex());
assertEquals(1, ldm.getDataModelListeners().length);
assertEquals("swf", ldm.getDataModelListeners()[0].toString());
// serialization fails with non serializable objects
try {
ldm = new ListDataModel(Collections.singletonList(new EventListener() {
}));
writeAndReadBack(ldm);
fail();
} catch (NotSerializableException e) {
// expected
}
}
public void testArrayDataModelSerializability() throws Exception {
// from scratch
ArrayDataModel adm = (ArrayDataModel) writeAndReadBack(new ArrayDataModel());
assertNull(adm.getWrappedData());
assertEquals(-1, adm.getRowIndex());
assertEquals(0, adm.getDataModelListeners().length);
// with input array
adm = (ArrayDataModel) writeAndReadBack(new ArrayDataModel(sampleList().toArray()));
assertEquals(sampleList(), Arrays.asList((Object[]) adm.getWrappedData()));
assertEquals(0, adm.getRowIndex());
assertEquals(0, adm.getDataModelListeners().length);
// manipulated
adm = new ArrayDataModel(sampleList().toArray());
adm.setRowIndex(1);
adm = (ArrayDataModel) writeAndReadBack(adm);
assertEquals(sampleList(), Arrays.asList((Object[]) adm.getWrappedData()));
assertEquals(1, adm.getRowIndex());
assertEquals(0, adm.getDataModelListeners().length);
// with listeners
adm = new ArrayDataModel(sampleList().toArray());
adm.addDataModelListener(new TestDataModelListener("swf"));
adm.setRowIndex(1);
adm = (ArrayDataModel) writeAndReadBack(adm);
assertEquals(sampleList(), Arrays.asList((Object[]) adm.getWrappedData()));
assertEquals(1, adm.getRowIndex());
assertEquals(1, adm.getDataModelListeners().length);
assertEquals("swf", adm.getDataModelListeners()[0].toString());
// serialization fails with non serializable objects
try {
adm = new ArrayDataModel(new Object[] { new EventListener() {
} });
writeAndReadBack(adm);
fail();
} catch (NotSerializableException e) {
// expected
}
}
public void testScalarDataModelSerializability() throws Exception {
// from scratch
ScalarDataModel sdm = (ScalarDataModel) writeAndReadBack(new ScalarDataModel());
assertNull(sdm.getWrappedData());
assertEquals(-1, sdm.getRowIndex());
assertEquals(0, sdm.getDataModelListeners().length);
// with input object
sdm = (ScalarDataModel) writeAndReadBack(new ScalarDataModel("foobar"));
assertEquals("foobar", sdm.getWrappedData());
assertEquals(0, sdm.getRowIndex());
assertEquals(0, sdm.getDataModelListeners().length);
// manipulated
sdm = new ScalarDataModel("foobar");
sdm.setRowIndex(1);
sdm = (ScalarDataModel) writeAndReadBack(sdm);
assertEquals("foobar", sdm.getWrappedData());
assertEquals(1, sdm.getRowIndex());
assertEquals(0, sdm.getDataModelListeners().length);
// with listeners
sdm = new ScalarDataModel("foobar");
sdm.addDataModelListener(new TestDataModelListener("swf"));
sdm.setRowIndex(1);
sdm = (ScalarDataModel) writeAndReadBack(sdm);
assertEquals("foobar", sdm.getWrappedData());
assertEquals(1, sdm.getRowIndex());
assertEquals(1, sdm.getDataModelListeners().length);
assertEquals("swf", sdm.getDataModelListeners()[0].toString());
// serialization fails with non serializable objects
try {
sdm = new ScalarDataModel(new EventListener() {
});
writeAndReadBack(sdm);
fail();
} catch (NotSerializableException e) {
// expected
}
}
// internal helpers
private Object writeAndReadBack(Object obj) throws Exception {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream oout = new ObjectOutputStream(bout);
oout.writeObject(obj);
oout.flush();
ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
ObjectInputStream oin = new ObjectInputStream(bin);
return oin.readObject();
}
private List sampleList() {
List list = new ArrayList(2);
list.add("foo");
list.add("bar");
return list;
}
private static class TestDataModelListener implements DataModelListener, Serializable {
private String name;
public TestDataModelListener(String name) {
this.name = name;
}
public void rowSelected(DataModelEvent event) {
}
public String toString() {
return name;
}
}
}