Java Code Examples for org.springframework.http.HttpOutputMessage#getHeaders()

The following examples show how to use org.springframework.http.HttpOutputMessage#getHeaders() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ResourceRegionHttpMessageConverter.java    From java-technology-stack with MIT License 6 votes vote down vote up
protected void writeResourceRegion(ResourceRegion region, HttpOutputMessage outputMessage) throws IOException {
	Assert.notNull(region, "ResourceRegion must not be null");
	HttpHeaders responseHeaders = outputMessage.getHeaders();

	long start = region.getPosition();
	long end = start + region.getCount() - 1;
	Long resourceLength = region.getResource().contentLength();
	end = Math.min(end, resourceLength - 1);
	long rangeLength = end - start + 1;
	responseHeaders.add("Content-Range", "bytes " + start + '-' + end + '/' + resourceLength);
	responseHeaders.setContentLength(rangeLength);

	InputStream in = region.getResource().getInputStream();
	try {
		StreamUtils.copyRange(in, outputMessage.getBody(), start, end);
	}
	finally {
		try {
			in.close();
		}
		catch (IOException ex) {
			// ignore
		}
	}
}
 
Example 2
Source File: ResourceRegionHttpMessageConverter.java    From lams with GNU General Public License v2.0 6 votes vote down vote up
protected void writeResourceRegion(ResourceRegion region, HttpOutputMessage outputMessage) throws IOException {
	Assert.notNull(region, "ResourceRegion must not be null");
	HttpHeaders responseHeaders = outputMessage.getHeaders();

	long start = region.getPosition();
	long end = start + region.getCount() - 1;
	Long resourceLength = region.getResource().contentLength();
	end = Math.min(end, resourceLength - 1);
	long rangeLength = end - start + 1;
	responseHeaders.add("Content-Range", "bytes " + start + '-' + end + '/' + resourceLength);
	responseHeaders.setContentLength(rangeLength);

	InputStream in = region.getResource().getInputStream();
	try {
		StreamUtils.copyRange(in, outputMessage.getBody(), start, end);
	}
	finally {
		try {
			in.close();
		}
		catch (IOException ex) {
			// ignore
		}
	}
}
 
Example 3
Source File: FormHttpMessageConverter.java    From lams with GNU General Public License v2.0 6 votes vote down vote up
private void writeMultipart(final MultiValueMap<String, Object> parts, HttpOutputMessage outputMessage) throws IOException {
	final byte[] boundary = generateMultipartBoundary();
	Map<String, String> parameters = Collections.singletonMap("boundary", new String(boundary, "US-ASCII"));

	MediaType contentType = new MediaType(MediaType.MULTIPART_FORM_DATA, parameters);
	HttpHeaders headers = outputMessage.getHeaders();
	headers.setContentType(contentType);

	if (outputMessage instanceof StreamingHttpOutputMessage) {
		StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage;
		streamingOutputMessage.setBody(new StreamingHttpOutputMessage.Body() {
			@Override
			public void writeTo(OutputStream outputStream) throws IOException {
				writeParts(outputStream, parts, boundary);
				writeEnd(outputStream, boundary);
			}
		});
	}
	else {
		writeParts(outputMessage.getBody(), parts, boundary);
		writeEnd(outputMessage.getBody(), boundary);
	}
}
 
Example 4
Source File: PropertiesHttpMessageConverter.java    From SpringAll with MIT License 6 votes vote down vote up
@Override
protected void writeInternal(Properties properties, Type type, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
    // 获取请求头
    HttpHeaders headers = outputMessage.getHeaders();
    // 获取 content-type
    MediaType contentType = headers.getContentType();
    // 获取编码
    Charset charset = null;
    if (contentType != null) {
        charset = contentType.getCharset();
    }

    charset = charset == null ? Charset.forName("UTF-8") : charset;

    // 获取请求体
    OutputStream body = outputMessage.getBody();
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(body, charset);

    properties.store(outputStreamWriter, "Serialized by PropertiesHttpMessageConverter#writeInternal");
}
 
Example 5
Source File: AbstractHttpMessageConverter.java    From spring-analysis-note with MIT License 6 votes vote down vote up
/**
 * This implementation sets the default headers by calling {@link #addDefaultHeaders},
 * and then calls {@link #writeInternal}.
 */
@Override
public final void write(final T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
		throws IOException, HttpMessageNotWritableException {

	final HttpHeaders headers = outputMessage.getHeaders();
	addDefaultHeaders(headers, t, contentType);

	if (outputMessage instanceof StreamingHttpOutputMessage) {
		StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage;
		streamingOutputMessage.setBody(outputStream -> writeInternal(t, new HttpOutputMessage() {
			@Override
			public OutputStream getBody() {
				return outputStream;
			}
			@Override
			public HttpHeaders getHeaders() {
				return headers;
			}
		}));
	}
	else {
		writeInternal(t, outputMessage);
		outputMessage.getBody().flush();
	}
}
 
Example 6
Source File: AbstractGenericHttpMessageConverter.java    From java-technology-stack with MIT License 6 votes vote down vote up
/**
 * This implementation sets the default headers by calling {@link #addDefaultHeaders},
 * and then calls {@link #writeInternal}.
 */
public final void write(final T t, @Nullable final Type type, @Nullable MediaType contentType,
		HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

	final HttpHeaders headers = outputMessage.getHeaders();
	addDefaultHeaders(headers, t, contentType);

	if (outputMessage instanceof StreamingHttpOutputMessage) {
		StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage;
		streamingOutputMessage.setBody(outputStream -> writeInternal(t, type, new HttpOutputMessage() {
			@Override
			public OutputStream getBody() {
				return outputStream;
			}
			@Override
			public HttpHeaders getHeaders() {
				return headers;
			}
		}));
	}
	else {
		writeInternal(t, type, outputMessage);
		outputMessage.getBody().flush();
	}
}
 
Example 7
Source File: AbstractHttpMessageConverter.java    From java-technology-stack with MIT License 6 votes vote down vote up
/**
 * This implementation sets the default headers by calling {@link #addDefaultHeaders},
 * and then calls {@link #writeInternal}.
 */
@Override
public final void write(final T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
		throws IOException, HttpMessageNotWritableException {

	final HttpHeaders headers = outputMessage.getHeaders();
	addDefaultHeaders(headers, t, contentType);

	if (outputMessage instanceof StreamingHttpOutputMessage) {
		StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage;
		streamingOutputMessage.setBody(outputStream -> writeInternal(t, new HttpOutputMessage() {
			@Override
			public OutputStream getBody() {
				return outputStream;
			}
			@Override
			public HttpHeaders getHeaders() {
				return headers;
			}
		}));
	}
	else {
		writeInternal(t, outputMessage);
		outputMessage.getBody().flush();
	}
}
 
Example 8
Source File: ResourceRegionHttpMessageConverter.java    From spring-analysis-note with MIT License 6 votes vote down vote up
protected void writeResourceRegion(ResourceRegion region, HttpOutputMessage outputMessage) throws IOException {
	Assert.notNull(region, "ResourceRegion must not be null");
	HttpHeaders responseHeaders = outputMessage.getHeaders();

	long start = region.getPosition();
	long end = start + region.getCount() - 1;
	Long resourceLength = region.getResource().contentLength();
	end = Math.min(end, resourceLength - 1);
	long rangeLength = end - start + 1;
	responseHeaders.add("Content-Range", "bytes " + start + '-' + end + '/' + resourceLength);
	responseHeaders.setContentLength(rangeLength);

	InputStream in = region.getResource().getInputStream();
	try {
		StreamUtils.copyRange(in, outputMessage.getBody(), start, end);
	}
	finally {
		try {
			in.close();
		}
		catch (IOException ex) {
			// ignore
		}
	}
}
 
Example 9
Source File: AbstractGenericHttpMessageConverter.java    From spring-analysis-note with MIT License 6 votes vote down vote up
/**
 * This implementation sets the default headers by calling {@link #addDefaultHeaders},
 * and then calls {@link #writeInternal}.
 */
public final void write(final T t, @Nullable final Type type, @Nullable MediaType contentType,
		HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

	final HttpHeaders headers = outputMessage.getHeaders();
	addDefaultHeaders(headers, t, contentType);

	if (outputMessage instanceof StreamingHttpOutputMessage) {
		StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage;
		streamingOutputMessage.setBody(outputStream -> writeInternal(t, type, new HttpOutputMessage() {
			@Override
			public OutputStream getBody() {
				return outputStream;
			}
			@Override
			public HttpHeaders getHeaders() {
				return headers;
			}
		}));
	}
	else {
		writeInternal(t, type, outputMessage);
		outputMessage.getBody().flush();
	}
}
 
Example 10
Source File: FormHttpMessageConverter.java    From spring-analysis-note with MIT License 6 votes vote down vote up
private void writeMultipart(final MultiValueMap<String, Object> parts, HttpOutputMessage outputMessage)
		throws IOException {

	final byte[] boundary = generateMultipartBoundary();
	Map<String, String> parameters = new LinkedHashMap<>(2);
	if (!isFilenameCharsetSet()) {
		parameters.put("charset", this.charset.name());
	}
	parameters.put("boundary", new String(boundary, StandardCharsets.US_ASCII));

	MediaType contentType = new MediaType(MediaType.MULTIPART_FORM_DATA, parameters);
	HttpHeaders headers = outputMessage.getHeaders();
	headers.setContentType(contentType);

	if (outputMessage instanceof StreamingHttpOutputMessage) {
		StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage;
		streamingOutputMessage.setBody(outputStream -> {
			writeParts(outputStream, parts, boundary);
			writeEnd(outputStream, boundary);
		});
	}
	else {
		writeParts(outputMessage.getBody(), parts, boundary);
		writeEnd(outputMessage.getBody(), boundary);
	}
}
 
Example 11
Source File: InputStreamMessageConverter.java    From n2o-framework with Apache License 2.0 5 votes vote down vote up
@Override
protected void writeInternal(DataInputStream in, HttpOutputMessage outputMessage)
        throws IOException, HttpMessageNotWritableException {
    HttpHeaders httpHeaders = outputMessage.getHeaders();
    String subtype = httpHeaders.getContentType().getSubtype();
    logger.debug("Trying write DataInputStream into servlet OutputStream. Output subtype:{}", subtype);
    IOUtils.copy(in, outputMessage.getBody());
    in.close();
    outputMessage.getBody().close();
}
 
Example 12
Source File: FastJsonHttpMessageConverter.java    From mcg-helper with Apache License 2.0 5 votes vote down vote up
protected void writeInternal(Object obj, HttpOutputMessage outputMessage)
        throws IOException, HttpMessageNotWritableException {
    HttpHeaders headers = outputMessage.getHeaders();
    String text = null;
    this.writeBefore(obj);
    if (!(obj instanceof JsonpResult)) {
        text = JSON.toJSONString(obj, //
                SerializeConfig.globalInstance, //
                filters, //
                dateFormat, //
                JSON.DEFAULT_GENERATE_FEATURE, //
                features);          
    } else {
        JsonpResult jsonp = (JsonpResult) obj;
        text = new StringBuilder(jsonp.getJsonpFunction())
                .append('(')
                .append(JSON.toJSONString(
                        jsonp.getValue(), //
                        SerializeConfig.globalInstance,
                        filters,
                        dateFormat,
                        JSON.DEFAULT_GENERATE_FEATURE,
                        features))
                .append(");").toString();
    }
    this.writeAfter(text);
    byte[] bytes = text.getBytes(charset);
    headers.setContentLength(bytes.length);
    OutputStream out = outputMessage.getBody();
    out.write(bytes);
    out.flush();
}
 
Example 13
Source File: AbstractHttpMessageConverter.java    From lams with GNU General Public License v2.0 5 votes vote down vote up
/**
 * This implementation sets the default headers by calling {@link #addDefaultHeaders},
 * and then calls {@link #writeInternal}.
 */
@Override
public final void write(final T t, MediaType contentType, HttpOutputMessage outputMessage)
		throws IOException, HttpMessageNotWritableException {

	final HttpHeaders headers = outputMessage.getHeaders();
	addDefaultHeaders(headers, t, contentType);

	if (outputMessage instanceof StreamingHttpOutputMessage) {
		StreamingHttpOutputMessage streamingOutputMessage =
				(StreamingHttpOutputMessage) outputMessage;
		streamingOutputMessage.setBody(new StreamingHttpOutputMessage.Body() {
			@Override
			public void writeTo(final OutputStream outputStream) throws IOException {
				writeInternal(t, new HttpOutputMessage() {
					@Override
					public OutputStream getBody() throws IOException {
						return outputStream;
					}
					@Override
					public HttpHeaders getHeaders() {
						return headers;
					}
				});
			}
		});
	}
	else {
		writeInternal(t, outputMessage);
		outputMessage.getBody().flush();
	}
}
 
Example 14
Source File: StringHttpMessageConverter.java    From spring-analysis-note with MIT License 5 votes vote down vote up
@Override
protected void writeInternal(String str, HttpOutputMessage outputMessage) throws IOException {
	HttpHeaders headers = outputMessage.getHeaders();
	if (this.writeAcceptCharset && headers.get(HttpHeaders.ACCEPT_CHARSET) == null) {
		headers.setAcceptCharset(getAcceptedCharsets());
	}
	Charset charset = getContentTypeCharset(headers.getContentType());
	StreamUtils.copy(str, charset, outputMessage.getBody());
}
 
Example 15
Source File: AbstractGenericHttpMessageConverter.java    From lams with GNU General Public License v2.0 5 votes vote down vote up
/**
 * This implementation sets the default headers by calling {@link #addDefaultHeaders},
 * and then calls {@link #writeInternal}.
 */
public final void write(final T t, final Type type, MediaType contentType, HttpOutputMessage outputMessage)
		throws IOException, HttpMessageNotWritableException {

	final HttpHeaders headers = outputMessage.getHeaders();
	addDefaultHeaders(headers, t, contentType);

	if (outputMessage instanceof StreamingHttpOutputMessage) {
		StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) outputMessage;
		streamingOutputMessage.setBody(new StreamingHttpOutputMessage.Body() {
			@Override
			public void writeTo(final OutputStream outputStream) throws IOException {
				writeInternal(t, type, new HttpOutputMessage() {
					@Override
					public OutputStream getBody() throws IOException {
						return outputStream;
					}
					@Override
					public HttpHeaders getHeaders() {
						return headers;
					}
				});
			}
		});
	}
	else {
		writeInternal(t, type, outputMessage);
		outputMessage.getBody().flush();
	}
}
 
Example 16
Source File: FastJsonHttpMessageConverter.java    From uavstack with Apache License 2.0 4 votes vote down vote up
@Override
protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

    ByteArrayOutputStream outnew = new ByteArrayOutputStream();
    try {
        HttpHeaders headers = outputMessage.getHeaders();

        //获取全局配置的filter
        SerializeFilter[] globalFilters = fastJsonConfig.getSerializeFilters();
        List<SerializeFilter> allFilters = new ArrayList<SerializeFilter>(Arrays.asList(globalFilters));

        boolean isJsonp = false;

        //不知道为什么会有这行代码, 但是为了保持和原来的行为一致,还是保留下来
        Object value = strangeCodeForJackson(object);

        if (value instanceof FastJsonContainer) {
            FastJsonContainer fastJsonContainer = (FastJsonContainer) value;
            PropertyPreFilters filters = fastJsonContainer.getFilters();
            allFilters.addAll(filters.getFilters());
            value = fastJsonContainer.getValue();
        }

        //revise 2017-10-23 ,
        // 保持原有的MappingFastJsonValue对象的contentType不做修改 保持旧版兼容。
        // 但是新的JSONPObject将返回标准的contentType:application/javascript ,不对是否有function进行判断
        if (value instanceof MappingFastJsonValue) {
            if(!StringUtils.isEmpty(((MappingFastJsonValue) value).getJsonpFunction())){
                isJsonp = true;
            }
        } else if (value instanceof JSONPObject) {
            isJsonp = true;
        }


        int len = JSON.writeJSONString(outnew, //
                fastJsonConfig.getCharset(), //
                value, //
                fastJsonConfig.getSerializeConfig(), //
                //fastJsonConfig.getSerializeFilters(), //
                allFilters.toArray(new SerializeFilter[allFilters.size()]),
                fastJsonConfig.getDateFormat(), //
                JSON.DEFAULT_GENERATE_FEATURE, //
                fastJsonConfig.getSerializerFeatures());

        if (isJsonp) {
            headers.setContentType(APPLICATION_JAVASCRIPT);
        }

        if (fastJsonConfig.isWriteContentLength()) {
            headers.setContentLength(len);
        }

        outnew.writeTo(outputMessage.getBody());

    } catch (JSONException ex) {
        throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
    } finally {
        outnew.close();
    }
}
 
Example 17
Source File: ResourceRegionHttpMessageConverter.java    From lams with GNU General Public License v2.0 4 votes vote down vote up
private void writeResourceRegionCollection(Collection<ResourceRegion> resourceRegions,
		HttpOutputMessage outputMessage) throws IOException {

	Assert.notNull(resourceRegions, "Collection of ResourceRegion should not be null");
	HttpHeaders responseHeaders = outputMessage.getHeaders();

	MediaType contentType = responseHeaders.getContentType();
	String boundaryString = MimeTypeUtils.generateMultipartBoundaryString();
	responseHeaders.set(HttpHeaders.CONTENT_TYPE, "multipart/byteranges; boundary=" + boundaryString);
	OutputStream out = outputMessage.getBody();

	for (ResourceRegion region : resourceRegions) {
		long start = region.getPosition();
		long end = start + region.getCount() - 1;
		InputStream in = region.getResource().getInputStream();
		try {
			// Writing MIME header.
			println(out);
			print(out, "--" + boundaryString);
			println(out);
			if (contentType != null) {
				print(out, "Content-Type: " + contentType.toString());
				println(out);
			}
			Long resourceLength = region.getResource().contentLength();
			end = Math.min(end, resourceLength - 1);
			print(out, "Content-Range: bytes " + start + '-' + end + '/' + resourceLength);
			println(out);
			println(out);
			// Printing content
			StreamUtils.copyRange(in, out, start, end);
		}
		finally {
			try {
				in.close();
			}
			catch (IOException ex) {
				// ignore
			}
		}
	}

	println(out);
	print(out, "--" + boundaryString + "--");
}
 
Example 18
Source File: ResourceRegionHttpMessageConverter.java    From spring-analysis-note with MIT License 4 votes vote down vote up
private void writeResourceRegionCollection(Collection<ResourceRegion> resourceRegions,
		HttpOutputMessage outputMessage) throws IOException {

	Assert.notNull(resourceRegions, "Collection of ResourceRegion should not be null");
	HttpHeaders responseHeaders = outputMessage.getHeaders();

	MediaType contentType = responseHeaders.getContentType();
	String boundaryString = MimeTypeUtils.generateMultipartBoundaryString();
	responseHeaders.set(HttpHeaders.CONTENT_TYPE, "multipart/byteranges; boundary=" + boundaryString);
	OutputStream out = outputMessage.getBody();

	for (ResourceRegion region : resourceRegions) {
		long start = region.getPosition();
		long end = start + region.getCount() - 1;
		InputStream in = region.getResource().getInputStream();
		try {
			// Writing MIME header.
			println(out);
			print(out, "--" + boundaryString);
			println(out);
			if (contentType != null) {
				print(out, "Content-Type: " + contentType.toString());
				println(out);
			}
			Long resourceLength = region.getResource().contentLength();
			end = Math.min(end, resourceLength - 1);
			print(out, "Content-Range: bytes " + start + '-' + end + '/' + resourceLength);
			println(out);
			println(out);
			// Printing content
			StreamUtils.copyRange(in, out, start, end);
		}
		finally {
			try {
				in.close();
			}
			catch (IOException ex) {
				// ignore
			}
		}
	}

	println(out);
	print(out, "--" + boundaryString + "--");
}
 
Example 19
Source File: ResourceRegionHttpMessageConverter.java    From java-technology-stack with MIT License 4 votes vote down vote up
private void writeResourceRegionCollection(Collection<ResourceRegion> resourceRegions,
		HttpOutputMessage outputMessage) throws IOException {

	Assert.notNull(resourceRegions, "Collection of ResourceRegion should not be null");
	HttpHeaders responseHeaders = outputMessage.getHeaders();

	MediaType contentType = responseHeaders.getContentType();
	String boundaryString = MimeTypeUtils.generateMultipartBoundaryString();
	responseHeaders.set(HttpHeaders.CONTENT_TYPE, "multipart/byteranges; boundary=" + boundaryString);
	OutputStream out = outputMessage.getBody();

	for (ResourceRegion region : resourceRegions) {
		long start = region.getPosition();
		long end = start + region.getCount() - 1;
		InputStream in = region.getResource().getInputStream();
		try {
			// Writing MIME header.
			println(out);
			print(out, "--" + boundaryString);
			println(out);
			if (contentType != null) {
				print(out, "Content-Type: " + contentType.toString());
				println(out);
			}
			Long resourceLength = region.getResource().contentLength();
			end = Math.min(end, resourceLength - 1);
			print(out, "Content-Range: bytes " + start + '-' + end + '/' + resourceLength);
			println(out);
			println(out);
			// Printing content
			StreamUtils.copyRange(in, out, start, end);
		}
		finally {
			try {
				in.close();
			}
			catch (IOException ex) {
				// ignore
			}
		}
	}

	println(out);
	print(out, "--" + boundaryString + "--");
}
 
Example 20
Source File: JsonMessageConverter.java    From DDMQ with Apache License 2.0 4 votes vote down vote up
@Override
protected void writeInternal(Object object, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
    try (ByteArrayOutputStream outnew = new ByteArrayOutputStream()) {
        HttpHeaders headers = outputMessage.getHeaders();

        //获取全局配置的filter
        SerializeFilter[] globalFilters = getFastJsonConfig().getSerializeFilters();
        List<SerializeFilter> allFilters = new ArrayList<>(Arrays.asList(globalFilters));

        boolean isJsonp = false;
        Object value = strangeCodeForJackson(object);

        if (value instanceof FastJsonContainer) {
            FastJsonContainer fastJsonContainer = (FastJsonContainer) value;
            PropertyPreFilters filters = fastJsonContainer.getFilters();
            allFilters.addAll(filters.getFilters());
            value = fastJsonContainer.getValue();
        }

        if (value instanceof MappingFastJsonValue) {
            isJsonp = true;
            value = ((MappingFastJsonValue) value).getValue();
        } else if (value instanceof JSONPObject) {
            isJsonp = true;
        }


        int len = writePrefix(outnew, object);
        len += JSON.writeJSONString(outnew, //
                getFastJsonConfig().getCharset(), //
                value, //
                getFastJsonConfig().getSerializeConfig(), //
                allFilters.toArray(new SerializeFilter[allFilters.size()]),
                getFastJsonConfig().getDateFormat(), //
                JSON.DEFAULT_GENERATE_FEATURE, //
                getFastJsonConfig().getSerializerFeatures());
        len += writeSuffix(outnew, object);

        if (isJsonp) {
            headers.setContentType(APPLICATION_JAVASCRIPT);
        }
        if (getFastJsonConfig().isWriteContentLength()) {
            headers.setContentLength(len);
        }

        headers.set("carrera_logid", RequestContext.getLogId());
        RequestContext.sendJsonResponse(outnew.toString());

        outnew.writeTo(outputMessage.getBody());

    } catch (JSONException ex) {
        throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
    }
}