11[[databuffers]]
22= Data Buffers and Codecs
33
4-
5-
6-
7- == Introduction
8-
94The `DataBuffer` interface defines an abstraction over byte buffers.
10- The main reason for introducing it, and not use the standard `java.nio.ByteBuffer` instead, is Netty.
11- Netty does not use `ByteBuffer`, but instead offers `ByteBuf` as an alternative.
5+ The main reason for introducing it ( and not using the standard `java.nio.ByteBuffer` instead) is Netty.
6+ Netty does not use `ByteBuffer` but instead offers `ByteBuf` as an alternative.
127Spring's `DataBuffer` is a simple abstraction over `ByteBuf` that can also be used on non-Netty
13- platforms (i.e. Servlet 3.1+).
14-
8+ platforms (that is, Servlet 3.1+).
159
1610
1711
1812== `DataBufferFactory`
1913
20- The `DataBufferFactory` offers functionality to allocate new data buffers, as well as to wrap
14+ The `DataBufferFactory` offers functionality to allocate new data buffers as well as to wrap
2115existing data.
22- The `allocate ` methods allocate a new data buffer, with a default or given capacity.
23- Though `DataBuffer` implementation grow and shrink on demand, it is more efficient to give the
16+ The `allocateBuffer ` methods allocate a new data buffer with a default or given capacity.
17+ Though `DataBuffer` implementations grow and shrink on demand, it is more efficient to give the
2418capacity upfront, if known.
2519The `wrap` methods decorate an existing `ByteBuffer` or byte array.
26- Wrapping does not involve allocation: it simply decorates the given data with a `DataBuffer`
20+ Wrapping does not involve allocation. It decorates the given data with a `DataBuffer`
2721implementation.
2822
29- There are two implementation of `DataBufferFactory`: the `NettyDataBufferFactory` which is meant
30- to be used on Netty platforms, such as Reactor Netty.
31- The other implementation, the `DefaultDataBufferFactory`, is used on other platforms, such as
32- Servlet 3.1+ servers.
33-
23+ There are two implementation of `DataBufferFactory`: the `NettyDataBufferFactory`
24+ (for Netty platforms, such as Reactor Netty) and
25+ `DefaultDataBufferFactory` (for other platforms, such as
26+ Servlet 3.1+ servers).
3427
3528
3629
37- == The `DataBuffer` interface
30+ == The `DataBuffer` Interface
3831
39- The `DataBuffer` interface is similar to `ByteBuffer`, but offers a number of advantages.
32+ The `DataBuffer` interface is similar to `ByteBuffer` but offers a number of advantages.
4033Similar to Netty's `ByteBuf`, the `DataBuffer` abstraction offers independent read and write
4134positions.
42- This is different from the JDK's `ByteBuffer`, which only exposes one position for both reading and
43- writing, and a separate `flip()` operation to switch between the two I/O operations.
35+ This is different from the JDK's `ByteBuffer`, which exposes only one position for both reading and
36+ writing and a separate `flip()` operation to switch between the two I/O operations.
4437In general, the following invariant holds for the read position, write position, and the capacity:
4538
39+ ====
4640[literal]
4741[subs="verbatim,quotes"]
4842--
4943 0 <= read position <= write position <= capacity
5044--
45+ ====
5146
5247When reading bytes from the `DataBuffer`, the read position is automatically updated in accordance with
5348the amount of data read from the buffer.
5449Similarly, when writing bytes to the `DataBuffer`, the write position is updated with the amount of
5550data written to the buffer.
56- Also, when writing data, the capacity of a `DataBuffer` is automatically expanded, just like `StringBuilder`,
51+ Also, when writing data, the capacity of a `DataBuffer` is automatically expanded, in the same fashion as `StringBuilder`,
5752`ArrayList`, and similar types.
5853
5954Besides the reading and writing functionality mentioned above, the `DataBuffer` also has methods to
60- view a (slice of a) buffer as `ByteBuffer`, `InputStream`, or `OutputStream`.
55+ view a (slice of a) buffer as a `ByteBuffer`, an `InputStream`, or an `OutputStream`.
6156Additionally, it offers methods to determine the index of a given byte.
6257
63- There are two implementation of `DataBuffer `: the `NettyDataBuffer` which is meant to be used on
64- Netty platforms, such as Reactor Netty.
65- The other implementation, the `DefaultDataBuffer`, is used on other platforms, such as Servlet 3.1+
66- servers.
58+ As mentioned earlier, there are two implementation of `DataBufferFactory `: the `NettyDataBufferFactory`
59+ (for Netty platforms, such as Reactor Netty) and
60+ `DefaultDataBufferFactory` (for other platforms, such as
61+ Servlet 3.1+ servers) .
6762
6863
6964
7065=== `PooledDataBuffer`
7166
7267The `PooledDataBuffer` is an extension to `DataBuffer` that adds methods for reference counting.
7368The `retain` method increases the reference count by one.
74- The `release` method decreases the count by one, and releases the buffer's memory when the count
69+ The `release` method decreases the count by one and releases the buffer's memory when the count
7570reaches 0.
76- Both of these methods are related to _reference counting_ , a mechanism that is explained below .
71+ Both of these methods are related to reference counting , a mechanism that we explain <<databuffer-reference-counting,later>> .
7772
7873Note that `DataBufferUtils` offers useful utility methods for releasing and retaining pooled data
7974buffers.
80- These methods take a plain `DataBuffer` as parameter, but only call `retain` or `release` if the
75+ These methods take a plain `DataBuffer` as a parameter but only call `retain` or `release` if the
8176passed data buffer is an instance of `PooledDataBuffer`.
8277
8378
8479[[databuffer-reference-counting]]
8580==== Reference Counting
8681
87- Reference counting is not a common technique in Java; it is much more common in other programming
88- languages such as Object C and C++.
89- In and of itself, reference counting is not complex: it basically involves tracking the number of
82+ Reference counting is not a common technique in Java. It is much more common in other programming
83+ languages, such as Object C and C++.
84+ In and of itself, reference counting is not complex. It basically involves tracking the number of
9085references that apply to an object.
9186The reference count of a `PooledDataBuffer` starts at 1, is incremented by calling `retain`,
92- and decremented by calling `release`.
93- As long as the buffer's reference count is larger than 0 the buffer will not be released.
94- When the number decreases to 0, the instance will be released.
95- In practice, this means that the reserved memory captured by the buffer will be returned back to
87+ and is decremented by calling `release`.
88+ As long as the buffer's reference count is larger than 0, the buffer is not released.
89+ When the number decreases to 0, the instance is released.
90+ In practice, this means that the reserved memory captured by the buffer is returned back to
9691the memory pool, ready to be used for future allocations.
9792
98- In general, _the last component to access a `DataBuffer` is responsible for releasing it_ .
93+ In general, the last component to access a `DataBuffer` is responsible for releasing it .
9994Within Spring, there are two sorts of components that release buffers: decoders and transports.
100- Decoders are responsible for transforming a stream of buffers into other types (see <<codecs>> below ),
101- and transports are responsible for sending buffers across a network boundary, typically as an HTTP message.
102- This means that if you allocate data buffers for the purpose of putting them into an outbound HTTP
103- message (i.e. client-side request or server-side response), they do not have to be released.
95+ Decoders are responsible for transforming a stream of buffers into other types (see <<codecs>>),
96+ and transports are responsible for sending buffers across a network boundary, typically as an HTTP message.
97+ This means that, if you allocate data buffers for the purpose of putting them into an outbound HTTP
98+ message (that is, a client-side request or server-side response), they do not have to be released.
10499The other consequence of this rule is that if you allocate data buffers that do not end up in the
105- body, for instance because of a thrown exception, you will have to release them yourself.
100+ body ( for instance, because of a thrown exception) , you have to release them yourself.
106101The following snippet shows a typical `DataBuffer` usage scenario when dealing with methods that
107102throw exceptions:
108103
104+ ====
109105[source,java,indent=0]
110106[subs="verbatim,quotes"]
111107----
@@ -130,46 +126,49 @@ throw exceptions:
130126
131127<1> A new buffer is allocated.
132128<2> A boolean flag indicates whether the allocated buffer should be released.
133- <3> This example method loads data into the buffer. Note that the method can throw an `IOException`,
134- and therefore a `finally` block to release the buffer is required.
135- <4> If no exception occurred, we switch the `release` flag to `false` as the buffer will now be
129+ <3> This example method loads data into the buffer. Note that the method can throw an `IOException`.
130+ Therefore, a `finally` block to release the buffer is required.
131+ <4> If no exception occurred, we switch the `release` flag to `false` as the buffer is now
136132released as part of sending the HTTP body across the wire.
137- <5> If an exception did occur, the flag is still set to `true`, and the buffer will be released
133+ <5> If an exception did occur, the flag is still set to `true`, and the buffer is released
138134here.
135+ ====
139136
140137
141138
142- === DataBufferUtils
139+ === ` DataBufferUtils`
143140
144- `DataBufferUtils` contains various utility methods that operate on data buffers.
141+ The `DataBufferUtils` class contains various utility methods that operate on data buffers.
145142It contains methods for reading a `Flux` of `DataBuffer` objects from an `InputStream` or NIO
146- `Channel`, and methods for writing a data buffer `Flux` to an `OutputStream` or `Channel`.
143+ `Channel` and methods for writing a data buffer `Flux` to an `OutputStream` or `Channel`.
147144`DataBufferUtils` also exposes `retain` and `release` methods that operate on plain `DataBuffer`
148145instances (so that casting to a `PooledDataBuffer` is not required).
149146
150147Additionally, `DataBufferUtils` exposes `compose`, which merges a stream of data buffers into one.
151148For instance, this method can be used to convert the entire HTTP body into a single buffer (and
152- from that, a `String`, or `InputStream`).
149+ from that, a `String` or `InputStream`).
153150This is particularly useful when dealing with older, blocking APIs.
154151Note, however, that this puts the entire body in memory, and therefore uses more memory than a pure
155152streaming solution would.
156153
157- [codecs]
154+
155+
156+ [[codecs]]
158157== Codecs
159158
160159The `org.springframework.core.codec` package contains the two main abstractions for converting a
161- stream of bytes into a stream of objects, or vice-versa.
160+ stream of bytes into a stream of objects or vice-versa.
162161The `Encoder` is a strategy interface that encodes a stream of objects into an output stream of
163162data buffers.
164- The `Decoder` does the reverse: it turns a stream of data buffers into a stream of objects.
165- Note that a decoder instance needs to consider <<databuffer-reference-counting, reference counting>>.
163+ The `Decoder` does the reverse: It turns a stream of data buffers into a stream of objects.
164+ Note that a decoder instance needs to consider <<databuffer-reference-counting,reference counting>>.
166165
167- Spring comes with a wide array of default codecs, capable of converting from/ to `String`,
168- `ByteBuffer`, byte arrays, and also codecs that support marshalling libraries such as JAXB and
166+ Spring comes with a wide array of default codecs (to convert from and to `String`,
167+ `ByteBuffer`, and byte arrays) and codecs that support marshalling libraries such as JAXB and
169168Jackson (with https://github.com/FasterXML/jackson-core/issues/57[Jackson 2.9+ support for non-blocking parsing]).
170169Within the context of Spring WebFlux, codecs are used to convert the request body into a
171- `@RequestMapping` parameter, or to convert the return type into the response body that is sent back
170+ `@RequestMapping` parameter or to convert the return type into the response body that is sent back
172171to the client.
173- The default codecs are configured in the `WebFluxConfigurationSupport` class, and can easily be
174- changed by overriding the `configureHttpMessageCodecs` when inheriting from that class.
175- For more information about using codecs in WebFlux, see <<web-reactive#webflux-codecs, this section >>.
172+ The default codecs are configured in the `WebFluxConfigurationSupport` class. You can
173+ change them by overriding the `configureHttpMessageCodecs` when you inherit from that class.
174+ For more information about using codecs in WebFlux, see <<web-reactive#webflux-codecs>>.
0 commit comments