diff --git a/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java b/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java index e0c0129cbd..a1cc3fb0df 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java @@ -263,14 +263,15 @@ public class MappingJackson2MessageConverter extends AbstractMessageConverter { if (byte[].class == getSerializedPayloadClass()) { ByteArrayOutputStream out = new ByteArrayOutputStream(1024); JsonEncoding encoding = getJsonEncoding(getMimeType(headers)); - JsonGenerator generator = this.objectMapper.getFactory().createGenerator(out, encoding); - if (view != null) { - this.objectMapper.writerWithView(view).writeValue(generator, payload); - } - else { - this.objectMapper.writeValue(generator, payload); + try (JsonGenerator generator = this.objectMapper.getFactory().createGenerator(out, encoding)) { + if (view != null) { + this.objectMapper.writerWithView(view).writeValue(generator, payload); + } + else { + this.objectMapper.writeValue(generator, payload); + } + payload = out.toByteArray(); } - payload = out.toByteArray(); } else { // Assuming a text-based target payload diff --git a/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java b/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java index 53a9009781..0c34e1232d 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java +++ b/spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Encoder.java @@ -149,7 +149,16 @@ public abstract class AbstractJackson2Encoder extends Jackson2CodecSupport imple return Flux.from(inputStream) .map(value -> encodeStreamingValue(value, bufferFactory, hints, sequenceWriter, byteBuilder, - separator)); + separator)) + .doAfterTerminate(() -> { + try { + byteBuilder.release(); + generator.close(); + } + catch (IOException ex) { + logger.error("Could not close Encoder resources", ex); + } + }); } catch (IOException ex) { return Flux.error(ex); @@ -172,30 +181,34 @@ public abstract class AbstractJackson2Encoder extends Jackson2CodecSupport imple ObjectWriter writer = createObjectWriter(valueType, mimeType, hints); ByteArrayBuilder byteBuilder = new ByteArrayBuilder(writer.getFactory()._getBufferRecycler()); - JsonEncoding encoding = getJsonEncoding(mimeType); + try { + JsonEncoding encoding = getJsonEncoding(mimeType); - logValue(hints, value); + logValue(hints, value); - try { - JsonGenerator generator = getObjectMapper().getFactory().createGenerator(byteBuilder, encoding); - writer.writeValue(generator, value); - generator.flush(); - } - catch (InvalidDefinitionException ex) { - throw new CodecException("Type definition error: " + ex.getType(), ex); - } - catch (JsonProcessingException ex) { - throw new EncodingException("JSON encoding error: " + ex.getOriginalMessage(), ex); - } - catch (IOException ex) { - throw new IllegalStateException("Unexpected I/O error while writing to byte array builder", ex); - } + try (JsonGenerator generator = getObjectMapper().getFactory().createGenerator(byteBuilder, encoding)) { + writer.writeValue(generator, value); + generator.flush(); + } + catch (InvalidDefinitionException ex) { + throw new CodecException("Type definition error: " + ex.getType(), ex); + } + catch (JsonProcessingException ex) { + throw new EncodingException("JSON encoding error: " + ex.getOriginalMessage(), ex); + } + catch (IOException ex) { + throw new IllegalStateException("Unexpected I/O error while writing to byte array builder", ex); + } - byte[] bytes = byteBuilder.toByteArray(); - DataBuffer buffer = bufferFactory.allocateBuffer(bytes.length); - buffer.write(bytes); + byte[] bytes = byteBuilder.toByteArray(); + DataBuffer buffer = bufferFactory.allocateBuffer(bytes.length); + buffer.write(bytes); - return buffer; + return buffer; + } + finally { + byteBuilder.release(); + } } private DataBuffer encodeStreamingValue(Object value, DataBufferFactory bufferFactory, @Nullable Map hints, diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java index 7f3b59fee4..65ce5fae6c 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java @@ -307,8 +307,8 @@ public abstract class AbstractJackson2HttpMessageConverter extends AbstractGener MediaType contentType = outputMessage.getHeaders().getContentType(); JsonEncoding encoding = getJsonEncoding(contentType); - JsonGenerator generator = this.objectMapper.getFactory().createGenerator(outputMessage.getBody(), encoding); - try { + + try (JsonGenerator generator = this.objectMapper.getFactory().createGenerator(outputMessage.getBody(), encoding)) { writePrefix(generator, object); Object value = object; diff --git a/spring-web/src/test/resources/log4j2-test.xml b/spring-web/src/test/resources/log4j2-test.xml index f37050e01a..c8a85fff2d 100644 --- a/spring-web/src/test/resources/log4j2-test.xml +++ b/spring-web/src/test/resources/log4j2-test.xml @@ -6,7 +6,7 @@ - + diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/AbstractJackson2View.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/AbstractJackson2View.java index ffac9fb147..6d3fea8f2b 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/AbstractJackson2View.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/AbstractJackson2View.java @@ -206,29 +206,30 @@ public abstract class AbstractJackson2View extends AbstractView { * @throws IOException if writing failed */ protected void writeContent(OutputStream stream, Object object) throws IOException { - JsonGenerator generator = this.objectMapper.getFactory().createGenerator(stream, this.encoding); - writePrefix(generator, object); - - Object value = object; - Class serializationView = null; - FilterProvider filters = null; - - if (value instanceof MappingJacksonValue) { - MappingJacksonValue container = (MappingJacksonValue) value; - value = container.getValue(); - serializationView = container.getSerializationView(); - filters = container.getFilters(); - } + try (JsonGenerator generator = this.objectMapper.getFactory().createGenerator(stream, this.encoding)) { + writePrefix(generator, object); + + Object value = object; + Class serializationView = null; + FilterProvider filters = null; + + if (value instanceof MappingJacksonValue) { + MappingJacksonValue container = (MappingJacksonValue) value; + value = container.getValue(); + serializationView = container.getSerializationView(); + filters = container.getFilters(); + } - ObjectWriter objectWriter = (serializationView != null ? - this.objectMapper.writerWithView(serializationView) : this.objectMapper.writer()); - if (filters != null) { - objectWriter = objectWriter.with(filters); - } - objectWriter.writeValue(generator, value); + ObjectWriter objectWriter = (serializationView != null ? + this.objectMapper.writerWithView(serializationView) : this.objectMapper.writer()); + if (filters != null) { + objectWriter = objectWriter.with(filters); + } + objectWriter.writeValue(generator, value); - writeSuffix(generator, object); - generator.flush(); + writeSuffix(generator, object); + generator.flush(); + } }