diff --git a/api/src/org/labkey/api/action/ApiJsonWriter.java b/api/src/org/labkey/api/action/ApiJsonWriter.java index f98a4e23ade..58c8a5a32c5 100644 --- a/api/src/org/labkey/api/action/ApiJsonWriter.java +++ b/api/src/org/labkey/api/action/ApiJsonWriter.java @@ -169,11 +169,21 @@ public void writeProperty(String name, Object value) throws IOException writeObject(value); } + /** Let subclasses have a chance to do special handling on String values in the response */ + protected void writeString(String value) throws IOException + { + jg.writeString(value); + } + @Override protected void writeObject(Object value) throws IOException { ensureNotClosed(); - if (value instanceof String || value instanceof Number || value instanceof Boolean || value == null) + if (value instanceof String s) + { + writeString(s); + } + else if (value instanceof Number || value instanceof Boolean || value == null) { jg.writeObject(value); } @@ -224,9 +234,9 @@ else if (value instanceof JSONArray jsonArray) // TODO: replace the upstream cre jg.writeEndArray(); } } - else if (value instanceof Date) + else if (value instanceof Date d) { - jg.writeString(DateUtil.formatJsonDateTime((Date) value)); + writeString(DateUtil.formatJsonDateTime(d)); } // Always use Jackson serialization for SimpleResponse, Issue 47216 else if (isSerializeViaJacksonAnnotations() || value instanceof SimpleResponse) @@ -239,7 +249,7 @@ else if (value == JSONObject.NULL) } else { - jg.writeString(value.toString()); + writeString(value.toString()); } } diff --git a/api/src/org/labkey/api/action/ExtFormResponseWriter.java b/api/src/org/labkey/api/action/ExtFormResponseWriter.java index 8c8250a3b8f..5c04008ff34 100644 --- a/api/src/org/labkey/api/action/ExtFormResponseWriter.java +++ b/api/src/org/labkey/api/action/ExtFormResponseWriter.java @@ -19,6 +19,7 @@ import org.labkey.api.query.PropertyValidationError; import org.labkey.api.query.ValidationError; import org.labkey.api.query.ValidationException; +import org.labkey.api.util.MimeMap; import org.springframework.validation.Errors; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; @@ -26,15 +27,10 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import java.io.FilterWriter; import java.io.IOException; import java.io.Writer; -/* -* User: Dave -* Date: Sep 3, 2008 -* Time: 11:03:32 AM -*/ - /** * This writer extends ApiJsonWriter by writing validation errors in the format * that Ext forms require. @@ -68,27 +64,26 @@ */ public class ExtFormResponseWriter extends ApiJsonWriter { - boolean sendHtmlJsonResponse = false; - boolean startResponse = true; - - public ExtFormResponseWriter(HttpServletResponse response) throws IOException + private Writer _encodingWriter; + private boolean _closed; + + public ExtFormResponseWriter(HttpServletRequest request, HttpServletResponse response) throws IOException { - super(response); + boolean sendHtml = !"XMLHttpRequest".equals(request.getHeader("X-Requested-With")) && + request instanceof MultipartHttpServletRequest; + super(response, sendHtml ? MimeMap.MimeType.HTML.getContentType() : CONTENT_TYPE_JSON); setErrorResponseStatus(HttpServletResponse.SC_OK); } - public ExtFormResponseWriter(HttpServletRequest request, HttpServletResponse response) throws IOException + private boolean isHtml() { - this(response); - if (!"XMLHttpRequest".equals(request.getHeader("X-Requested-With")) && (request instanceof MultipartHttpServletRequest)) - sendHtmlJsonResponse = true; - response.setContentType(sendHtmlJsonResponse ? "text/html" : CONTENT_TYPE_JSON); + return getResponse().getContentType().startsWith(MimeMap.MimeType.HTML.getContentType()); } public ExtFormResponseWriter(HttpServletRequest request, HttpServletResponse response, String contentTypeOverride) throws IOException { this(request, response); - if (!sendHtmlJsonResponse && null != contentTypeOverride) + if (!isHtml() && null != contentTypeOverride) response.setContentType(contentTypeOverride); } @@ -121,8 +116,8 @@ public void toJSON(JSONObject jsonErrors, ValidationError error) { String msg = error.getMessage(); String key = "_form"; - if (error instanceof PropertyValidationError) - key = ((PropertyValidationError)error).getProperty(); + if (error instanceof PropertyValidationError pve) + key = pve.getProperty(); if (jsonErrors.has(key)) msg = jsonErrors.get(key) + "; " + msg; jsonErrors.put(key, msg); @@ -139,8 +134,8 @@ public void writeResponse(Errors errors) throws IOException if (message == null) message = msg; String key = "_form"; - if (error instanceof FieldError) - key = ((FieldError)error).getField(); + if (error instanceof FieldError fieldError) + key = fieldError.getField(); if (jsonErrors.has(key)) msg = jsonErrors.get(key) + "; " + msg; jsonErrors.put(key, msg); @@ -161,24 +156,69 @@ public void writeResponse(Errors errors) throws IOException } } + @Override + public void close() throws IOException + { + super.close(); + if (isHtml() && !_closed) + { + _encodingWriter.flush(); + Writer w = super.getWriter(); + if (w != null) + { + w.flush(); + } + } + _closed = true; + } + @Override protected Writer getWriter() { Writer w = super.getWriter(); if (null == w) return null; - if (sendHtmlJsonResponse && startResponse) + if (isHtml() && _encodingWriter == null) { - startResponse = false; - try - { - w.write("