From 045ed34a61e160e56210f007279924bd6116dbd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Lambert?= Date: Thu, 18 Apr 2019 17:32:06 +0200 Subject: [PATCH] May put any kind of extra field value - adds a method in ServiceException to put an extra field value that may be unsafe (array, List, Map, ...) - adds a unit test --- .../api/server/spi/ServiceException.java | 20 +++++ .../RestResponseResultWriterTest.java | 80 +++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/endpoints-framework/src/main/java/com/google/api/server/spi/ServiceException.java b/endpoints-framework/src/main/java/com/google/api/server/spi/ServiceException.java index 62d93e79..b010f3f3 100644 --- a/endpoints-framework/src/main/java/com/google/api/server/spi/ServiceException.java +++ b/endpoints-framework/src/main/java/com/google/api/server/spi/ServiceException.java @@ -153,6 +153,26 @@ public ServiceException putExtraField(String fieldName, Number value) { return putExtraFieldInternal(fieldName, value); } + /** + * Associates to this exception an extra field as a field name/value pair. If a field + * with the same name was previously set, the old value is replaced by the specified + * value.
+ * This unsafe version accepts any POJO as is: + * + * These constraints must be taken into consideration when overriding this method. + * @return this + * @throws NullPointerException if {@code fieldName} is {@code null}. + * @throws IllegalArgumentException if {@code fieldName} is one of the reserved field + * names {@link #EXTRA_FIELDS_RESERVED_NAMES}. + */ + protected ServiceException putExtraFieldUnsafe(String fieldName, Object value) { + return putExtraFieldInternal(fieldName, value); + } + private ServiceException putExtraFieldInternal(String fieldName, Object value) { Preconditions.checkNotNull(fieldName); Preconditions.checkArgument(!EXTRA_FIELDS_RESERVED_NAMES.contains(fieldName), "The field name '%s' is reserved", fieldName); diff --git a/endpoints-framework/src/test/java/com/google/api/server/spi/response/RestResponseResultWriterTest.java b/endpoints-framework/src/test/java/com/google/api/server/spi/response/RestResponseResultWriterTest.java index 95bc6cc5..46092a03 100644 --- a/endpoints-framework/src/test/java/com/google/api/server/spi/response/RestResponseResultWriterTest.java +++ b/endpoints-framework/src/test/java/com/google/api/server/spi/response/RestResponseResultWriterTest.java @@ -32,6 +32,11 @@ import org.skyscreamer.jsonassert.JSONAssert; import org.springframework.mock.web.MockHttpServletResponse; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * Tests for {@link RestResponseResultWriter}. */ @@ -269,4 +274,79 @@ public void writeError_extraFields() throws Exception { writer.writeError(serviceException); JSONAssert.assertEquals(expectedError, response.getContentAsString(), true); } + + @Test + public void writeError_extraFieldsUnsafe() throws Exception { + + MockHttpServletResponse response = new MockHttpServletResponse(); + RestResponseResultWriter writer = new RestResponseResultWriter(response, null, true /* prettyPrint */, + true /* addContentLength */, true /* enableExceptionCompatibility */); + + TestServiceExceptionExtraFieldUnsafe serviceException = new TestServiceExceptionExtraFieldUnsafe(400, "customMessage", "customReason", "customDomain"); + + // Extra field array + Boolean[] booleans = new Boolean[] { TRUE, FALSE, TRUE }; + + // Extra field List + List stringList = Arrays.asList("First", "Second", "Last"); + + // Extra field Map + Map map = new HashMap<>(); + map.put(1, new TestValue("Alice", 7, TestEnum.VALUE1)); + map.put(2, new TestValue("Bob", 12, TestEnum.VALUE2)); + map.put(3, new TestValue("Clark", 31, TestEnum.VALUE3)); + + serviceException.putExtraFieldUnsafe("someExtraNull", null) + .putExtraFieldUnsafe("someExtraArray", booleans) + .putExtraFieldUnsafe("someExtraList", stringList) + .putExtraFieldUnsafe("someExtraMap", map); + + String expectedError = "{\"error\": {\"errors\": [{" + + " \"domain\": \"customDomain\"," + + " \"reason\": \"customReason\"," + + " \"message\": \"customMessage\"," + + " \"someExtraNull\": null," + + " \"someExtraArray\": [true, false, true]," + + " \"someExtraList\": [\"First\", \"Second\", \"Last\"]," + + " \"someExtraMap\": {" + + " \"1\": {\"name\": \"Alice\", \"age\": 7, \"testEnum\": \"VALUE1\"}," + + " \"2\": {\"name\": \"Bob\", \"age\": 12, \"testEnum\": \"VALUE2\"}," + + " \"3\": {\"name\": \"Clark\", \"age\": 31, \"testEnum\": \"VALUE3\"}" + + " }" + + " }]," + + " \"code\": 400," + + " \"message\": \"customMessage\"" + + "}}"; + + writer.writeError(serviceException); + JSONAssert.assertEquals(expectedError, response.getContentAsString(), true); + } + + enum TestEnum { + VALUE1, VALUE2, VALUE3; + } + + class TestValue { + public String name; + public int age; + public TestEnum testEnum; + + TestValue(String name, int age, TestEnum testEnum) { + this.name = name; + this.age = age; + this.testEnum = testEnum; + } + } + + class TestServiceExceptionExtraFieldUnsafe extends ServiceException { + + TestServiceExceptionExtraFieldUnsafe(int statusCode, String statusMessage, String reason, String domain) { + super(statusCode, statusMessage, reason, domain); + } + + @Override + public TestServiceExceptionExtraFieldUnsafe putExtraFieldUnsafe(String fieldName, Object value) { + return (TestServiceExceptionExtraFieldUnsafe) super.putExtraFieldUnsafe(fieldName, value); + } + } }