From 2bfe9c0fc371b4de4cc0920fa6a8e04fd250c5ed Mon Sep 17 00:00:00 2001 From: robokaso Date: Tue, 4 Nov 2008 16:29:33 +0000 Subject: [PATCH] REOPENED - BATCH-900: Retreive null values from the ExecutionContext putting null value now equals removing entry for given key --- .../batch/item/ExecutionContext.java | 30 ++----- .../batch/item/ExecutionContextTests.java | 89 ++++++++++--------- 2 files changed, 53 insertions(+), 66 deletions(-) diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContext.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContext.java index aaf8638c2..c50d69e3a 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContext.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContext.java @@ -29,19 +29,14 @@ import org.springframework.util.Assert; * for a map that allows optionally for type safety on reads. It also allows for * dirty checking by setting a 'dirty' flag whenever any put is called. * + * Note that putting null value is equivalent to removing the entry + * for the given key. + * * @author Lucas Ward * @author Douglas Kaminsky */ public class ExecutionContext implements Serializable { - /** - * Underlying {@link ConcurrentHashMap} does not accept null - * values, so we convert it to a private constant under the covers. - */ - private static enum Constants { - NULL - }; - private volatile boolean dirty = false; private final Map map; @@ -111,7 +106,8 @@ public class ExecutionContext implements Serializable { } /** - * Add an Object value to the context (must be Serializable). + * Add an Object value to the context (must be Serializable). Putting + * null value for a given key removes the key. * * @param key Key to add to context * @param value Value to associate with key @@ -119,12 +115,12 @@ public class ExecutionContext implements Serializable { public void put(String key, Object value) { if (value != null) { Assert.isInstanceOf(Serializable.class, value, "Value: [ " + value + "must be serializable."); + map.put(key, value); } else { - value = Constants.NULL; + map.remove(key); } dirty = true; - map.put(key, value); } /** @@ -228,13 +224,7 @@ public class ExecutionContext implements Serializable { * @return The value represented by the given key */ public Object get(String key) { - Object value = map.get(key); - if (value == Constants.NULL) { - return null; - } - else { - return value; - } + return map.get(key); } /** @@ -249,10 +239,6 @@ public class ExecutionContext implements Serializable { Object value = map.get(key); - if (value == Constants.NULL) { - return null; - } - if (!type.isInstance(value)) { throw new ClassCastException("Value for key=[" + key + "] is not of type: [" + type + "], it is [" + (value == null ? null : "(" + value.getClass() + ")" + value) + "]"); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ExecutionContextTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ExecutionContextTests.java index 945310c13..12fe0759d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ExecutionContextTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/ExecutionContextTests.java @@ -27,7 +27,7 @@ import org.junit.Test; /** * @author Lucas Ward - * + * */ public class ExecutionContextTests { @@ -37,15 +37,15 @@ public class ExecutionContextTests { public void setUp() throws Exception { context = new ExecutionContext(); } - + @Test - public void testNormalUsage(){ - + public void testNormalUsage() { + context.putString("1", "testString1"); context.putString("2", "testString2"); context.putLong("3", 3); context.putDouble("4", 4.4); - + assertEquals("testString1", context.getString("1")); assertEquals("testString2", context.getString("2")); assertEquals("defaultString", context.getString("5", "defaultString")); @@ -54,96 +54,99 @@ public class ExecutionContextTests { assertEquals(3, context.getLong("3")); assertEquals(5, context.getLong("5", 5)); } - + @Test - public void testInvalidCast(){ - + public void testInvalidCast() { + context.putLong("1", 1); - try{ + try { context.getDouble("1"); fail(); } - catch(ClassCastException ex){ - //expected + catch (ClassCastException ex) { + // expected } } - + @Test - public void testIsEmpty(){ + public void testIsEmpty() { assertTrue(context.isEmpty()); context.putString("1", "test"); assertFalse(context.isEmpty()); } - + @Test - public void testDirtyFlag(){ + public void testDirtyFlag() { assertFalse(context.isDirty()); context.putString("1", "test"); assertTrue(context.isDirty()); context.clearDirtyFlag(); assertFalse(context.isDirty()); } - + @Test - public void testContains(){ + public void testContains() { context.putString("1", "testString"); assertTrue(context.containsKey("1")); assertTrue(context.containsValue("testString")); } - + @Test - public void testEquals(){ + public void testEquals() { context.putString("1", "testString"); ExecutionContext tempContext = new ExecutionContext(); assertFalse(tempContext.equals(context)); tempContext.putString("1", "testString"); assertTrue(tempContext.equals(context)); } - + @Test - public void testSerializationCheck(){ - //adding a non serializable object should cause an error. - try{ + public void testSerializationCheck() { + // adding a non serializable object should cause an error. + try { context.put("1", new Object()); fail(); } - catch(IllegalArgumentException ex){ - //expected + catch (IllegalArgumentException ex) { + // expected } } - + + /** + * Putting null value is equivalent to removing the entry for the given key. + */ @Test - public void testPutNull(){ - //putting null should work + public void testPutNull() { context.put("1", null); assertNull(context.get("1")); + assertFalse(context.containsKey("1")); } - + @Test public void testGetNull() { assertNull(context.get("does not exist")); } - + @Test public void testSerialization() { - + TestSerializable s = new TestSerializable(); s.value = 7; - + context.putString("1", "testString1"); context.putString("2", "testString2"); context.putLong("3", 3); context.putDouble("4", 4.4); context.put("5", s); - + byte[] serialized = SerializationUtils.serialize(context); - + ExecutionContext deserialized = (ExecutionContext) SerializationUtils.deserialize(serialized); - + assertEquals(context, deserialized); - assertEquals(7, ((TestSerializable)deserialized.get("5")).value); + assertEquals(7, ((TestSerializable) deserialized.get("5")).value); } - + @Test public void testCopyConstructor() throws Exception { ExecutionContext context = new ExecutionContext(); @@ -151,13 +154,13 @@ public class ExecutionContextTests { ExecutionContext copy = new ExecutionContext(context); assertEquals(copy, context); } - + @Test public void testCopyConstructorNullnNput() throws Exception { - ExecutionContext context = new ExecutionContext((ExecutionContext)null); + ExecutionContext context = new ExecutionContext((ExecutionContext) null); assertTrue(context.isEmpty()); } - + /** * Value object for testing serialization */ @@ -172,9 +175,7 @@ public class ExecutionContextTests { public int hashCode() { return HashCodeBuilder.reflectionHashCode(this); } - - - + } - + }