diff --git a/config/src/main/java/com/typesafe/config/impl/SerializedConfigValue.java b/config/src/main/java/com/typesafe/config/impl/SerializedConfigValue.java index 55970857..a18a1899 100644 --- a/config/src/main/java/com/typesafe/config/impl/SerializedConfigValue.java +++ b/config/src/main/java/com/typesafe/config/impl/SerializedConfigValue.java @@ -14,6 +14,7 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.ObjectStreamException; import java.util.ArrayList; +import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; import java.util.List; @@ -199,7 +200,12 @@ class SerializedConfigValue extends AbstractConfigValue implements Externalizabl // not private because we use it to serialize ConfigException static void writeOrigin(DataOutput out, SimpleConfigOrigin origin, SimpleConfigOrigin baseOrigin) throws IOException { - Map<SerializedField, Object> m = origin.toFieldsDelta(baseOrigin); + Map<SerializedField, Object> m; + // to serialize a null origin, we write out no fields at all + if (origin != null) + m = origin.toFieldsDelta(baseOrigin); + else + m = Collections.emptyMap(); for (Map.Entry<SerializedField, Object> e : m.entrySet()) { FieldOut field = new FieldOut(e.getKey()); Object v = e.getValue(); diff --git a/config/src/main/java/com/typesafe/config/impl/SimpleConfigOrigin.java b/config/src/main/java/com/typesafe/config/impl/SimpleConfigOrigin.java index 7af380aa..457597a3 100644 --- a/config/src/main/java/com/typesafe/config/impl/SimpleConfigOrigin.java +++ b/config/src/main/java/com/typesafe/config/impl/SimpleConfigOrigin.java @@ -466,6 +466,10 @@ final class SimpleConfigOrigin implements ConfigOrigin { } static SimpleConfigOrigin fromFields(Map<SerializedField, Object> m) throws IOException { + // we represent a null origin as one with no fields at all + if (m.isEmpty()) + return null; + String description = (String) m.get(SerializedField.ORIGIN_DESCRIPTION); Integer lineNumber = (Integer) m.get(SerializedField.ORIGIN_LINE_NUMBER); Integer endLineNumber = (Integer) m.get(SerializedField.ORIGIN_END_LINE_NUMBER); diff --git a/config/src/test/scala/com/typesafe/config/impl/PublicApiTest.scala b/config/src/test/scala/com/typesafe/config/impl/PublicApiTest.scala index e20057f8..3c8be585 100644 --- a/config/src/test/scala/com/typesafe/config/impl/PublicApiTest.scala +++ b/config/src/test/scala/com/typesafe/config/impl/PublicApiTest.scala @@ -857,6 +857,16 @@ class PublicApiTest extends TestUtils { assertTrue("origins equal after deserialize", e.origin().equals(eCopy.origin())) } + @Test + def exceptionSerializableWithNullOrigin() { + val e = new ConfigException.Missing("this is a message", new RuntimeException("this is a cause")) + assertTrue("origin null before serialize", e.origin() == null) + val eCopy = checkSerializableNoMeaningfulEquals(e) + assertTrue("messages equal after deserialize", e.getMessage.equals(eCopy.getMessage)) + assertTrue("cause messages equal after deserialize", e.getCause().getMessage.equals(eCopy.getCause().getMessage)) + assertTrue("origin null after deserialize", e.origin() == null) + } + @Test def invalidateCaches() { val conf0 = ConfigFactory.load()