Merge pull request #300 from aguibert/serialize-improve-err-msg
Include property name when serialization fails
diff --git a/src/main/java/org/eclipse/yasson/internal/properties/MessageKeys.java b/src/main/java/org/eclipse/yasson/internal/properties/MessageKeys.java
index 3336dda..95fb57e 100644
--- a/src/main/java/org/eclipse/yasson/internal/properties/MessageKeys.java
+++ b/src/main/java/org/eclipse/yasson/internal/properties/MessageKeys.java
@@ -68,6 +68,7 @@
INCOMPATIBLE_FACTORY_CREATOR_RETURN_TYPE("incompatibleFactoryCreatorReturnType"),
MULTIPLE_JSONB_CREATORS("multipleJsonbCreators"),
INTERNAL_ERROR("internalError"),
+ SERIALIZE_PROPERTY_ERROR("serializePropertyError"),
DESERIALIZE_VALUE_ERROR("deserializeValueError"),
PARSING_NUMBER("parsingNumber"),
UNKNOWN_BINARY_DATA_STRATEGY("unknownBinaryDataStrategy"),
diff --git a/src/main/java/org/eclipse/yasson/internal/serializer/AbstractValueTypeSerializer.java b/src/main/java/org/eclipse/yasson/internal/serializer/AbstractValueTypeSerializer.java
index 242a3e9..ab81280 100644
--- a/src/main/java/org/eclipse/yasson/internal/serializer/AbstractValueTypeSerializer.java
+++ b/src/main/java/org/eclipse/yasson/internal/serializer/AbstractValueTypeSerializer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
diff --git a/src/main/java/org/eclipse/yasson/internal/serializer/ObjectSerializer.java b/src/main/java/org/eclipse/yasson/internal/serializer/ObjectSerializer.java
index 0194151..7ab0f6a 100644
--- a/src/main/java/org/eclipse/yasson/internal/serializer/ObjectSerializer.java
+++ b/src/main/java/org/eclipse/yasson/internal/serializer/ObjectSerializer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
@@ -17,7 +17,10 @@
import org.eclipse.yasson.internal.ReflectionUtils;
import org.eclipse.yasson.internal.model.ClassModel;
import org.eclipse.yasson.internal.model.PropertyModel;
+import org.eclipse.yasson.internal.properties.MessageKeys;
+import org.eclipse.yasson.internal.properties.Messages;
+import javax.json.bind.JsonbException;
import javax.json.bind.serializer.JsonbSerializer;
import javax.json.bind.serializer.SerializationContext;
import javax.json.stream.JsonGenerator;
@@ -56,9 +59,15 @@
@Override
protected void serializeInternal(T object, JsonGenerator generator, SerializationContext ctx) {
- final PropertyModel[] allProperties = ((Marshaller) ctx).getMappingContext().getOrCreateClassModel(object.getClass()).getSortedProperties();
+ final PropertyModel[] allProperties = ((Marshaller) ctx).getMappingContext()
+ .getOrCreateClassModel(object.getClass()).getSortedProperties();
for (PropertyModel model : allProperties) {
- marshallProperty(object, generator, ctx, model);
+ try {
+ marshallProperty(object, generator, ctx, model);
+ } catch (Exception e) {
+ throw new JsonbException(Messages.getMessage(MessageKeys.SERIALIZE_PROPERTY_ERROR, model.getWriteName(),
+ object.getClass().getCanonicalName()), e);
+ }
}
}
@@ -72,7 +81,6 @@
generator.writeStartObject(key);
}
- @SuppressWarnings("unchecked")
private void marshallProperty(T object, JsonGenerator generator, SerializationContext ctx, PropertyModel propertyModel) {
Marshaller marshaller = (Marshaller) ctx;
diff --git a/src/main/resources/yasson-messages.properties b/src/main/resources/yasson-messages.properties
index 59b8a68..b0efc2b 100644
--- a/src/main/resources/yasson-messages.properties
+++ b/src/main/resources/yasson-messages.properties
@@ -63,6 +63,7 @@
incompatibleFactoryCreatorReturnType=Return type of creator {0} must be of type {1}.
multipleJsonbCreators=More than one @JsonbCreator declared in class {0}.
internalError=Internal error: {0}
+serializePropertyError=Unable to serialize property ''{0}'' from {1}
deserializeValueError=Error deserialize JSON value into type: {0}.
parsingNumber=Error parsing number {0} with format {1}.
unknownBinaryDataStrategy=Unknown binary data strategy: {0}
diff --git a/src/test/java/org/eclipse/yasson/Assertions.java b/src/test/java/org/eclipse/yasson/Assertions.java
new file mode 100644
index 0000000..509ba75
--- /dev/null
+++ b/src/test/java/org/eclipse/yasson/Assertions.java
@@ -0,0 +1,67 @@
+package org.eclipse.yasson;
+
+import static org.junit.Assert.fail;
+
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import javax.json.bind.JsonbException;
+
+public class Assertions {
+
+ /**
+ * Asserts that the given operation will fail with a JsonbException
+ * @param operation The operation that is expected to fail
+ */
+ public static void shouldFail(Supplier<?> operation) {
+ shouldFail(operation, JsonbException.class, msg -> true);
+ }
+
+ public static void shouldFail(Runnable operation) {
+ shouldFail(() -> {
+ operation.run();
+ return null;
+ });
+ }
+
+ /**
+ * Asserts that the given operation will fail with a JsonbException
+ * @param operation The operation that is expected to fail
+ * @param checkExceptionMessage Any checks that should be made on the exception message. For example, ensuring the exception
+ * includes a specific token.
+ */
+ public static void shouldFail(Supplier<?> operation, Function<String,Boolean> checkExceptionMessage) {
+ shouldFail(operation, JsonbException.class, checkExceptionMessage);
+ }
+
+ /**
+ * Asserts that the given operation will fail
+ * @param operation The operation that is expected to fail
+ * @param expectedType The expected exception type to receive when evaluating the operation
+ * @param checkExceptionMessage Any checks that should be made on the exception message. For example, ensuring the exception
+ * includes a specific token.
+ */
+ public static void shouldFail(Supplier<?> operation, Class<? extends Throwable> expectedType, Function<String,Boolean> checkExceptionMessage) {
+ try {
+ operation.get();
+ fail("The operation should have failed with a " + expectedType.getCanonicalName() + " but it succeeded.");
+ } catch (Throwable t) {
+ String fullErrorMessage = "";
+ for (Throwable current = t; current != null && current.getCause() != current; current = current.getCause()) {
+ fullErrorMessage += current.getClass().getCanonicalName() + ": ";
+ fullErrorMessage += current.getMessage() + "\n";
+ }
+ if (expectedType.isAssignableFrom(t.getClass())) {
+ if (!checkExceptionMessage.apply(fullErrorMessage)) {
+ t.printStackTrace();
+ fail("Exception did not contain the proper content: " + fullErrorMessage);
+ }
+ } else {
+ t.printStackTrace();
+ fail("Expected to get an exception of " + expectedType + " but instead was " + t.getClass());
+ }
+ }
+
+ }
+
+}
diff --git a/src/test/java/org/eclipse/yasson/defaultmapping/basic/NumberTest.java b/src/test/java/org/eclipse/yasson/defaultmapping/basic/NumberTest.java
index a2cbadc..16d5e5d 100644
--- a/src/test/java/org/eclipse/yasson/defaultmapping/basic/NumberTest.java
+++ b/src/test/java/org/eclipse/yasson/defaultmapping/basic/NumberTest.java
@@ -14,6 +14,7 @@
package org.eclipse.yasson.defaultmapping.basic;
+import static org.eclipse.yasson.Assertions.*;
import org.eclipse.yasson.TestTypeToken;
import org.eclipse.yasson.defaultmapping.basic.model.BigDecimalInNumber;
import org.eclipse.yasson.defaultmapping.generics.model.ScalarValueWrapper;
@@ -26,10 +27,18 @@
import javax.json.JsonWriter;
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
+import javax.json.bind.JsonbException;
import javax.json.stream.JsonGenerator;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import java.io.StringWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
/**
* @author Roman Grigoriadi
@@ -207,5 +216,37 @@
"\"unsafeBigDecimalValue\":9223372036854775807}", w.toString());
}
+
+ public static class NumberContainer {
+ public Double doubleProp;
+ public Collection<Double> collectionProp;
+ public Map<String,Double> mapProp;
+ }
+
+ @Test
+ public void testSerializeInvalidDouble() {
+ shouldFail(() -> jsonb.toJson(Double.POSITIVE_INFINITY));
+
+ NumberContainer obj = new NumberContainer();
+ obj.doubleProp = Double.POSITIVE_INFINITY;
+ shouldFail(() -> jsonb.toJson(obj), msg -> msg.contains("doubleProp") && msg.contains("NumberContainer"));
+ }
+
+
+ @Test
+ public void testSerializeInvalidDoubleCollection() {
+ NumberContainer obj = new NumberContainer();
+ obj.collectionProp = Collections.singleton(Double.POSITIVE_INFINITY);
+ shouldFail(() -> jsonb.toJson(obj),
+ msg -> msg.contains("collectionProp") && msg.contains("NumberContainer"));
+ }
+
+ @Test
+ public void testSerializeInvalidDoubleMap() {
+ NumberContainer obj = new NumberContainer();
+ obj.mapProp = Collections.singletonMap("doubleKey", Double.POSITIVE_INFINITY);
+ shouldFail(() -> jsonb.toJson(obj),
+ msg -> msg.contains("mapProp") && msg.contains("NumberContainer"));
+ }
}
diff --git a/src/test/java/org/eclipse/yasson/defaultmapping/modifiers/ClassModifiersTest.java b/src/test/java/org/eclipse/yasson/defaultmapping/modifiers/ClassModifiersTest.java
index bf2a7b4..8bb67eb 100644
--- a/src/test/java/org/eclipse/yasson/defaultmapping/modifiers/ClassModifiersTest.java
+++ b/src/test/java/org/eclipse/yasson/defaultmapping/modifiers/ClassModifiersTest.java
@@ -17,6 +17,7 @@
import javax.json.bind.JsonbBuilder;
import javax.json.bind.JsonbException;
+import org.eclipse.yasson.Assertions;
import org.eclipse.yasson.defaultmapping.modifiers.model.ChildOfPackagePrivateParent;
import org.eclipse.yasson.defaultmapping.modifiers.model.FieldModifiersClass;
import org.junit.Before;
@@ -67,14 +68,9 @@
NestedPackageChild child = new NestedPackageChild();
child.id = 1;
child.name = "SomeName";
- try {
- jsonb.toJson(child);
- fail();
- } catch (JsonbException ex) {
- if (!(ex.getCause() instanceof IllegalAccessException)) {
- fail();
- }
- }
+ Assertions.shouldFail(() -> jsonb.toJson(child),
+ msg -> msg.contains("Unable to serialize property 'id'") &&
+ msg.contains("java.lang.IllegalAccessException"));
}
private class NestedPrivateParent {
@@ -90,14 +86,8 @@
NestedPrivateChild child = new NestedPrivateChild();
child.id = 1;
child.name = "SomeName";
- try {
- jsonb.toJson(child);
- fail();
- } catch (JsonbException ex) {
- if (!(ex.getCause() instanceof IllegalAccessException)) {
- fail();
- }
- }
+ Assertions.shouldFail(() -> jsonb.toJson(child),
+ msg -> msg.contains("java.lang.IllegalAccessException"));
}
@@ -114,14 +104,8 @@
NestedStaticPackageChild child = new NestedStaticPackageChild();
child.id = 1;
child.name = "SomeName";
- try {
- jsonb.toJson(child);
- fail();
- } catch (JsonbException ex) {
- if (!(ex.getCause() instanceof IllegalAccessException)) {
- fail();
- }
- }
+ Assertions.shouldFail(() -> jsonb.toJson(child),
+ msg -> msg.contains("java.lang.IllegalAccessException"));
}
private static class NestedStaticPrivateParent {
@@ -137,14 +121,8 @@
NestedStaticPrivateChild child = new NestedStaticPrivateChild();
child.id = 1;
child.name = "SomeName";
- try {
- jsonb.toJson(child);
- fail();
- } catch (JsonbException ex) {
- if (!(ex.getCause() instanceof IllegalAccessException)) {
- fail();
- }
- }
+ Assertions.shouldFail(() -> jsonb.toJson(child),
+ msg -> msg.contains("java.lang.IllegalAccessException"));
}
}
diff --git a/src/test/java/org/eclipse/yasson/jsonpsubstitution/PreinstantiatedJsonpTest.java b/src/test/java/org/eclipse/yasson/jsonpsubstitution/PreinstantiatedJsonpTest.java
index 63337b0..d72b799 100644
--- a/src/test/java/org/eclipse/yasson/jsonpsubstitution/PreinstantiatedJsonpTest.java
+++ b/src/test/java/org/eclipse/yasson/jsonpsubstitution/PreinstantiatedJsonpTest.java
@@ -9,6 +9,7 @@
******************************************************************************/
package org.eclipse.yasson.jsonpsubstitution;
+import org.eclipse.yasson.Assertions;
import org.eclipse.yasson.JsonBindingProvider;
import org.eclipse.yasson.TestTypeToken;
import org.eclipse.yasson.YassonJsonb;
@@ -165,12 +166,7 @@
generator.writeStartObject();
//key not written
- try {
- jsonb.toJson(dog, generator);
- Assert.fail("JsonbException not thrown");
- } catch (JsonbException e) {
- //OK
- }
+ Assertions.shouldFail(() -> jsonb.toJson(dog, generator));
}
@Test