From ce6d096ef9bad0a562a43e5c9817bbc075969119 Mon Sep 17 00:00:00 2001 From: Ian Tabolt Date: Wed, 2 Nov 2016 13:37:29 -0400 Subject: [PATCH 1/3] Make ValidationProblem implement Serializable --- config/src/main/java/com/typesafe/config/ConfigException.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/src/main/java/com/typesafe/config/ConfigException.java b/config/src/main/java/com/typesafe/config/ConfigException.java index 58d541704..a6dde7c0b 100644 --- a/config/src/main/java/com/typesafe/config/ConfigException.java +++ b/config/src/main/java/com/typesafe/config/ConfigException.java @@ -310,10 +310,10 @@ public NotResolved(String message) { * {@link ConfigException.ValidationFailed} exception thrown from * checkValid() includes a list of problems encountered. */ - public static class ValidationProblem { + public static class ValidationProblem implements Serializable { final private String path; - final private ConfigOrigin origin; + final private transient ConfigOrigin origin; final private String problem; public ValidationProblem(String path, ConfigOrigin origin, String problem) { From 3448ef56b05149796adbf20faac521f2ecfd61bf Mon Sep 17 00:00:00 2001 From: Ian Tabolt Date: Wed, 2 Nov 2016 14:58:26 -0400 Subject: [PATCH 2/3] Add custom serialization to ValidationProblem --- .../com/typesafe/config/ConfigException.java | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/config/src/main/java/com/typesafe/config/ConfigException.java b/config/src/main/java/com/typesafe/config/ConfigException.java index a6dde7c0b..fce04b407 100644 --- a/config/src/main/java/com/typesafe/config/ConfigException.java +++ b/config/src/main/java/com/typesafe/config/ConfigException.java @@ -58,22 +58,22 @@ private void writeObject(java.io.ObjectOutputStream out) throws IOException { ConfigImplUtil.writeOrigin(out, origin); } - private void readObject(java.io.ObjectInputStream in) throws IOException, - ClassNotFoundException { - in.defaultReadObject(); - ConfigOrigin origin = ConfigImplUtil.readOrigin(in); + // For deserialization - uses reflection to set the final origin field on the object + private static void setOriginField(T hasOriginField, Class clazz, + ConfigOrigin origin) throws IOException { // circumvent "final" Field f; try { - f = ConfigException.class.getDeclaredField("origin"); + f = clazz.getDeclaredField("origin"); } catch (NoSuchFieldException e) { - throw new IOException("ConfigException has no origin field?", e); + throw new IOException(clazz.getSimpleName() + " has no origin field?", e); } catch (SecurityException e) { - throw new IOException("unable to fill out origin field in ConfigException", e); + throw new IOException("unable to fill out origin field in " + + clazz.getSimpleName(), e); } f.setAccessible(true); try { - f.set(this, origin); + f.set(hasOriginField, origin); } catch (IllegalArgumentException e) { throw new IOException("unable to set origin field", e); } catch (IllegalAccessException e) { @@ -81,6 +81,13 @@ private void readObject(java.io.ObjectInputStream in) throws IOException, } } + private void readObject(java.io.ObjectInputStream in) throws IOException, + ClassNotFoundException { + in.defaultReadObject(); + ConfigOrigin origin = ConfigImplUtil.readOrigin(in); + setOriginField(this, ConfigException.class, origin); + } + /** * Exception indicating that the type of a value does not match the type you * requested. @@ -347,6 +354,20 @@ public String problem() { return problem; } + // We customize serialization because ConfigOrigin isn't + // serializable and we don't want it to be + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + ConfigImplUtil.writeOrigin(out, origin); + } + + private void readObject(java.io.ObjectInputStream in) throws IOException, + ClassNotFoundException { + in.defaultReadObject(); + ConfigOrigin origin = ConfigImplUtil.readOrigin(in); + setOriginField(this, ValidationProblem.class, origin); + } + @Override public String toString() { return "ValidationProblem(" + path + "," + origin + "," + problem + ")"; From 2692aa77bdb2ec2fe23b2e6704b047c6ccfdb0da Mon Sep 17 00:00:00 2001 From: Ian Tabolt Date: Fri, 6 Oct 2017 13:50:26 -0400 Subject: [PATCH 3/3] Add test case for serializing ValidationFailed --- .../com/typesafe/config/impl/ValidationTest.scala | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/config/src/test/scala/com/typesafe/config/impl/ValidationTest.scala b/config/src/test/scala/com/typesafe/config/impl/ValidationTest.scala index 6dce7bfee..5e45aad61 100644 --- a/config/src/test/scala/com/typesafe/config/impl/ValidationTest.scala +++ b/config/src/test/scala/com/typesafe/config/impl/ValidationTest.scala @@ -97,6 +97,21 @@ class ValidationTest extends TestUtils { checkValidationException(e, expecteds) } + @Test + def validationFailedSerializable(): Unit = { + // Reusing a previous test case to generate an error + val reference = parseConfig("""{ a : [{},{},{}] }""") + val conf = parseConfig("""{ a : 42 }""") + val e = intercept[ConfigException.ValidationFailed] { + conf.checkValid(reference) + } + + val expecteds = Seq(WrongType("a", 1, "list", "number")) + + val actual = checkSerializableNoMeaningfulEquals(e) + checkValidationException(actual, expecteds) + } + @Test def validationAllowsListOverriddenWithSameTypeList() { val reference = parseConfig("""{ a : [1,2,3] }""")