This is an automated email from the ASF dual-hosted git repository. heneveld pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
commit e8ee84dd8affcbb1f3f7e63f6fe12c9875d4e185 Author: Alex Heneveld <a...@cloudsoft.io> AuthorDate: Mon Feb 26 10:52:52 2024 +0000 better error handling in rest api --- .../ErrorAndToStringUnknownTypeSerializer.java | 35 +++++++++++++++------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/apache/brooklyn/util/core/json/ErrorAndToStringUnknownTypeSerializer.java b/core/src/main/java/org/apache/brooklyn/util/core/json/ErrorAndToStringUnknownTypeSerializer.java index 5a540cf11f..3c7ffc7e9e 100644 --- a/core/src/main/java/org/apache/brooklyn/util/core/json/ErrorAndToStringUnknownTypeSerializer.java +++ b/core/src/main/java/org/apache/brooklyn/util/core/json/ErrorAndToStringUnknownTypeSerializer.java @@ -26,7 +26,6 @@ import javax.annotation.Nullable; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonStreamContext; -import com.fasterxml.jackson.core.json.JsonWriteContext; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.annotation.JsonSerialize; @@ -74,25 +73,28 @@ public class ErrorAndToStringUnknownTypeSerializer extends UnknownSerializer { // if nested very deeply, come out, because there will be errors writing deeper things int closed = 0; - while (jgen.getOutputContext().getNestingDepth() > 30 && writeEndCurrentThing(jgen, closed++)) {} - if (jgen.getOutputContext().getNestingDepth() > 30) { - throw new IllegalStateException("Cannot recover from serialization object; nesting is too deep"); + if (error!=null) { + while (jgen.getOutputContext().getNestingDepth() > 30 && writeEndCurrentThing(jgen, closed++)) { + } + if (jgen.getOutputContext().getNestingDepth() > 30) { + throw new IllegalStateException("Cannot recover from serialization object; nesting is too deep"); + } } boolean createObject = !jgen.getOutputContext().inObject(); + if (error==null && jgen.getOutputContext().hasCurrentName()) createObject = true; if (createObject) { // create if we're not in an object (ie in an array) - // or if we're in an object, but we've just written the field name + // or if we're in an object, it's not an error, and we've just written the field name jgen.writeStartObject(); } else { // we might need to write a value, and then write the error fields next - writeErrorValueIfNeeded(jgen); + if (error!=null) writeErrorValueIfNeeded(jgen, true); } if (allowEmpty(value.getClass())) { // write nothing } else { - jgen.writeFieldName("error"); jgen.writeBoolean(true); @@ -128,25 +130,36 @@ public class ErrorAndToStringUnknownTypeSerializer extends UnknownSerializer { return true; } if (jgen.getOutputContext().inObject()) { - if (count==0) writeErrorValueIfNeeded(jgen); + if (count==0) writeErrorValueIfNeeded(jgen, true); jgen.writeEndObject(); return true; } return false; } - private static void writeErrorValueIfNeeded(JsonGenerator jgen) { + private static void writeErrorValueIfNeeded(JsonGenerator jgen, boolean fallbackToWritingRaw) { try { // at count 0, we usually need to write a value // (but there is no way to tell for sure; the internal status on JsonWriteContext is protected, // and the jgen methods are closely coupled to their state; and any attempt to mutate will insert an extra colon etc) if (jgen.getOutputContext().hasCurrentName()) { // assume it wrote the name, but the output context might not have the correct state; - // have tried updated output context but it is mostly protected; instead just write this, usually good enough. - jgen.writeRaw("\"ERROR\""); + // have tried updated output context but it is mostly protected; instead just write this, + // good enough if it was in a healthy state + jgen.writeString("\"ERROR\""); } } catch (Exception e) { Exceptions.propagateIfFatal(e); + if (fallbackToWritingRaw) { + try { + // if it wasn't in a healthy state, probably it wrote a colon and failed in the value, + // so we need to do this; caller may then end the object (confirmed) or + // if writing a field immediately after, the jgen tool should detect a comma is needed + jgen.writeRaw("\"ERROR\""); + } catch (Exception e2) { + Exceptions.propagateIfFatal(e2); + } + } // if we couldn't write, we're probably at a place where a field would be written, so just end } }