0
# Message Conversion
1
2
HTTP message conversion and encoding support for transforming between Java objects and HTTP message bodies. Includes both servlet-based converters for traditional web applications and reactive codecs for streaming applications.
3
4
## Capabilities
5
6
### HTTP Message Converters (Servlet-Based)
7
8
Traditional message converters for converting between HTTP messages and Java objects in servlet-based applications.
9
10
```java { .api }
11
/**
12
* Contract for HTTP message converters
13
*/
14
interface HttpMessageConverter<T> {
15
/** Check if this converter can read the given class and media type */
16
boolean canRead(Class<?> clazz, MediaType mediaType);
17
/** Check if this converter can write the given class and media type */
18
boolean canWrite(Class<?> clazz, MediaType mediaType);
19
/** Get the supported media types for this converter */
20
List<MediaType> getSupportedMediaTypes();
21
22
/** Read object from HTTP input message */
23
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
24
throws IOException, HttpMessageNotReadableException;
25
/** Write object to HTTP output message */
26
void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
27
throws IOException, HttpMessageNotWritableException;
28
}
29
30
/**
31
* Generic version supporting parameterized types
32
*/
33
interface GenericHttpMessageConverter<T> extends HttpMessageConverter<T> {
34
/** Check if converter can read the generic type */
35
boolean canRead(Type type, Class<?> contextClass, MediaType mediaType);
36
/** Check if converter can write the generic type */
37
boolean canWrite(Type type, Class<?> clazz, MediaType mediaType);
38
39
/** Read generic type from HTTP message */
40
T read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
41
throws IOException, HttpMessageNotReadableException;
42
/** Write generic type to HTTP message */
43
void write(T t, Type type, MediaType contentType, HttpOutputMessage outputMessage)
44
throws IOException, HttpMessageNotWritableException;
45
}
46
```
47
48
### Common Message Converter Implementations
49
50
Built-in converters for common data formats and types.
51
52
```java { .api }
53
/**
54
* Base class for message converter implementations
55
*/
56
abstract class AbstractHttpMessageConverter<T> implements HttpMessageConverter<T> {
57
protected AbstractHttpMessageConverter(MediaType supportedMediaType);
58
protected AbstractHttpMessageConverter(MediaType... supportedMediaTypes);
59
60
/** Set supported media types */
61
void setSupportedMediaTypes(List<MediaType> supportedMediaTypes);
62
/** Get supported media types */
63
List<MediaType> getSupportedMediaTypes();
64
65
// Template methods for subclasses
66
protected abstract boolean supports(Class<?> clazz);
67
protected abstract T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)
68
throws IOException, HttpMessageNotReadableException;
69
protected abstract void writeInternal(T t, HttpOutputMessage outputMessage)
70
throws IOException, HttpMessageNotWritableException;
71
}
72
73
/**
74
* String message converter
75
*/
76
class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
77
StringHttpMessageConverter();
78
StringHttpMessageConverter(Charset defaultCharset);
79
80
/** Set whether to write Accept-Charset header */
81
void setWriteAcceptCharset(boolean writeAcceptCharset);
82
/** Set available charsets for Accept-Charset header */
83
void setAvailableCharsets(List<Charset> availableCharsets);
84
}
85
86
/**
87
* Byte array message converter
88
*/
89
class ByteArrayHttpMessageConverter extends AbstractHttpMessageConverter<byte[]> {
90
ByteArrayHttpMessageConverter();
91
92
// Supports application/octet-stream and all other media types
93
}
94
95
/**
96
* Resource message converter
97
*/
98
class ResourceHttpMessageConverter extends AbstractHttpMessageConverter<Resource> {
99
ResourceHttpMessageConverter();
100
ResourceHttpMessageConverter(boolean supportsReadStreaming);
101
102
// Automatically detects content type from resource
103
}
104
105
/**
106
* Form data message converter
107
*/
108
class FormHttpMessageConverter implements HttpMessageConverter<MultiValueMap<String, ?>> {
109
FormHttpMessageConverter();
110
111
/** Set default charset for form encoding */
112
void setCharset(Charset charset);
113
/** Set supported media types */
114
void setSupportedMediaTypes(List<MediaType> supportedMediaTypes);
115
/** Set multipart character sets */
116
void setMultipartCharsets(Map<String, Charset> multipartCharsets);
117
}
118
119
/**
120
* Enhanced form converter with multipart support
121
*/
122
class AllEncompassingFormHttpMessageConverter extends FormHttpMessageConverter {
123
AllEncompassingFormHttpMessageConverter();
124
125
// Adds support for multipart/form-data with part converters
126
}
127
```
128
129
### JSON Message Converters
130
131
Converters for JSON serialization using popular libraries.
132
133
```java { .api }
134
/**
135
* Jackson 2 JSON message converter
136
*/
137
class MappingJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {
138
MappingJackson2HttpMessageConverter();
139
MappingJackson2HttpMessageConverter(ObjectMapper objectMapper);
140
141
/** Set the ObjectMapper to use */
142
void setObjectMapper(ObjectMapper objectMapper);
143
/** Get the current ObjectMapper */
144
ObjectMapper getObjectMapper();
145
146
/** Set JSON prefix for security */
147
void setJsonPrefix(String jsonPrefix);
148
/** Set whether to prefix JSON output */
149
void setPrefixJson(boolean prefixJson);
150
}
151
152
/**
153
* Base class for Jackson converters
154
*/
155
abstract class AbstractJackson2HttpMessageConverter extends AbstractGenericHttpMessageConverter<Object> {
156
/** Set pretty print formatting */
157
void setPrettyPrint(boolean prettyPrint);
158
/** Add supported media types */
159
protected void addDefaultMediaTypes(MediaType... mediaTypes);
160
}
161
162
/**
163
* Google Gson JSON message converter
164
*/
165
class GsonHttpMessageConverter extends AbstractGenericHttpMessageConverter<Object> {
166
GsonHttpMessageConverter();
167
GsonHttpMessageConverter(Gson gson);
168
169
/** Set the Gson instance to use */
170
void setGson(Gson gson);
171
/** Get the current Gson instance */
172
Gson getGson();
173
174
/** Set JSON prefix for security */
175
void setJsonPrefix(String jsonPrefix);
176
}
177
178
/**
179
* JSON-B message converter
180
*/
181
class JsonbHttpMessageConverter extends AbstractGenericHttpMessageConverter<Object> {
182
JsonbHttpMessageConverter();
183
JsonbHttpMessageConverter(Jsonb jsonb);
184
185
/** Set the Jsonb instance to use */
186
void setJsonb(Jsonb jsonb);
187
/** Get the current Jsonb instance */
188
Jsonb getJsonb();
189
}
190
```
191
192
### XML Message Converters
193
194
Converters for XML serialization and deserialization.
195
196
```java { .api }
197
/**
198
* JAXB2 XML message converter
199
*/
200
class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessageConverter<Object> {
201
Jaxb2RootElementHttpMessageConverter();
202
203
// Supports classes annotated with @XmlRootElement or @XmlType
204
}
205
206
/**
207
* Marshalling XML message converter using Spring's marshalling abstractions
208
*/
209
class MarshallingHttpMessageConverter extends AbstractHttpMessageConverter<Object> {
210
MarshallingHttpMessageConverter();
211
MarshallingHttpMessageConverter(Marshaller marshaller);
212
MarshallingHttpMessageConverter(Marshaller marshaller, Unmarshaller unmarshaller);
213
214
/** Set the marshaller for writing XML */
215
void setMarshaller(Marshaller marshaller);
216
/** Set the unmarshaller for reading XML */
217
void setUnmarshaller(Unmarshaller unmarshaller);
218
}
219
220
/**
221
* Base class for JAXB2 converters
222
*/
223
abstract class AbstractJaxb2HttpMessageConverter<T> extends AbstractGenericHttpMessageConverter<T> {
224
/** Set whether to process external entities */
225
void setProcessExternalEntities(boolean processExternalEntities);
226
/** Set whether to support DTD parsing */
227
void setSupportDtd(boolean supportDtd);
228
}
229
```
230
231
**Usage Examples:**
232
233
```java
234
// Configure message converters in RestTemplate
235
RestTemplate restTemplate = new RestTemplate();
236
237
// Add custom Jackson converter
238
ObjectMapper objectMapper = new ObjectMapper();
239
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
240
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(objectMapper);
241
242
List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
243
converters.add(0, jsonConverter); // Add as first converter
244
245
// Configure form converter
246
FormHttpMessageConverter formConverter = new FormHttpMessageConverter();
247
formConverter.setCharset(StandardCharsets.UTF_8);
248
converters.add(formConverter);
249
250
// Use converters automatically
251
User user = restTemplate.getForObject("/api/users/1", User.class); // Uses JSON converter
252
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
253
form.add("username", "john");
254
restTemplate.postForObject("/api/login", form, String.class); // Uses form converter
255
```
256
257
### Reactive HTTP Codecs
258
259
Reactive message readers and writers for non-blocking streaming applications.
260
261
```java { .api }
262
/**
263
* Contract to read HTTP messages reactively
264
*/
265
interface HttpMessageReader<T> {
266
/** Check if this reader can read the given type and media type */
267
boolean canRead(ResolvableType elementType, MediaType mediaType);
268
/** Get readable media types */
269
List<MediaType> getReadableMediaTypes();
270
/** Get readable media types for a specific type */
271
default List<MediaType> getReadableMediaTypes(ResolvableType elementType) {
272
return getReadableMediaTypes();
273
}
274
275
/** Read object stream from reactive HTTP input */
276
Flux<T> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints);
277
/** Read single object from reactive HTTP input */
278
Mono<T> readMono(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints);
279
}
280
281
/**
282
* Contract to write HTTP messages reactively
283
*/
284
interface HttpMessageWriter<T> {
285
/** Check if this writer can write the given type and media type */
286
boolean canWrite(ResolvableType elementType, MediaType mediaType);
287
/** Get writable media types */
288
List<MediaType> getWritableMediaTypes();
289
/** Get writable media types for a specific type */
290
default List<MediaType> getWritableMediaTypes(ResolvableType elementType) {
291
return getWritableMediaTypes();
292
}
293
294
/** Write object stream to reactive HTTP output */
295
Mono<Void> write(Publisher<? extends T> inputStream, ResolvableType elementType,
296
MediaType mediaType, ReactiveHttpOutputMessage message,
297
Map<String, Object> hints);
298
}
299
```
300
301
### Codec Configuration
302
303
Configuration interfaces for managing HTTP message readers and writers.
304
305
```java { .api }
306
/**
307
* Contract to configure HTTP message readers and writers
308
*/
309
interface CodecConfigurer {
310
/** Configure default codecs */
311
DefaultCodecs defaultCodecs();
312
/** Configure custom codecs */
313
CustomCodecs customCodecs();
314
/** Set whether to register default codecs */
315
void registerDefaults(boolean registerDefaults);
316
317
/** Get configured readers */
318
List<HttpMessageReader<?>> getReaders();
319
/** Get configured writers */
320
List<HttpMessageWriter<?>> getWriters();
321
322
/** Clone this configurer */
323
CodecConfigurer clone();
324
}
325
326
/**
327
* Client-specific codec configurer
328
*/
329
interface ClientCodecConfigurer extends CodecConfigurer {
330
/** Configure default codecs for client use */
331
ClientDefaultCodecs defaultCodecs();
332
333
interface ClientDefaultCodecs extends DefaultCodecs {
334
/** Set max in-memory buffer size */
335
void maxInMemorySize(int byteCount);
336
/** Configure multipart codecs */
337
MultipartCodecs multipartCodecs();
338
/** Set enable logging request details */
339
void enableLoggingRequestDetails(boolean enable);
340
}
341
}
342
343
/**
344
* Server-specific codec configurer
345
*/
346
interface ServerCodecConfigurer extends CodecConfigurer {
347
/** Configure default codecs for server use */
348
ServerDefaultCodecs defaultCodecs();
349
350
interface ServerDefaultCodecs extends DefaultCodecs {
351
/** Set max in-memory buffer size */
352
void maxInMemorySize(int byteCount);
353
/** Configure multipart codecs */
354
MultipartCodecs multipartCodecs();
355
/** Set enable logging request details */
356
void enableLoggingRequestDetails(boolean enable);
357
}
358
}
359
360
/**
361
* Default codec configuration
362
*/
363
interface DefaultCodecs {
364
/** Configure Jackson JSON codec */
365
void jackson2JsonDecoder(Decoder<?> decoder);
366
void jackson2JsonEncoder(Encoder<?> encoder);
367
368
/** Configure Jackson Smile codec */
369
void jackson2SmileDecoder(Decoder<?> decoder);
370
void jackson2SmileEncoder(Encoder<?> encoder);
371
372
/** Configure protobuf codec */
373
void protobufDecoder(Decoder<?> decoder);
374
void protobufEncoder(Encoder<?> encoder);
375
376
/** Configure JAXB2 codec */
377
void jaxb2Decoder(Decoder<?> decoder);
378
void jaxb2Encoder(Encoder<?> encoder);
379
380
/** Configure multipart reader */
381
void multipartReader(HttpMessageReader<?> reader);
382
/** Configure multipart writer */
383
void multipartWriter(HttpMessageWriter<?> writer);
384
}
385
386
/**
387
* Custom codec configuration
388
*/
389
interface CustomCodecs {
390
/** Register custom reader */
391
void register(HttpMessageReader<?> reader);
392
/** Register custom writer */
393
void register(HttpMessageWriter<?> writer);
394
395
/** Register reader with order */
396
void registerWithDefaultConfig(HttpMessageReader<?> reader);
397
/** Register writer with order */
398
void registerWithDefaultConfig(HttpMessageWriter<?> writer);
399
}
400
```
401
402
### Common Reactive Codec Implementations
403
404
Built-in reactive codecs for common data formats.
405
406
```java { .api }
407
/**
408
* Decoder-based HTTP message reader
409
*/
410
class DecoderHttpMessageReader<T> implements HttpMessageReader<T> {
411
DecoderHttpMessageReader(Decoder<T> decoder);
412
413
/** Get the underlying decoder */
414
Decoder<T> getDecoder();
415
}
416
417
/**
418
* Encoder-based HTTP message writer
419
*/
420
class EncoderHttpMessageWriter<T> implements HttpMessageWriter<T> {
421
EncoderHttpMessageWriter(Encoder<T> encoder);
422
423
/** Get the underlying encoder */
424
Encoder<T> getEncoder();
425
}
426
427
/**
428
* Jackson 2 JSON encoder for reactive streams
429
*/
430
class Jackson2JsonEncoder extends Jackson2CodecSupport implements HttpMessageEncoder<Object> {
431
Jackson2JsonEncoder();
432
Jackson2JsonEncoder(ObjectMapper mapper, MimeType... mimeTypes);
433
434
/** Set streaming media types */
435
void setStreamingMediaTypes(List<MediaType> mediaTypes);
436
}
437
438
/**
439
* Jackson 2 JSON decoder for reactive streams
440
*/
441
class Jackson2JsonDecoder extends Jackson2CodecSupport implements HttpMessageDecoder<Object> {
442
Jackson2JsonDecoder();
443
Jackson2JsonDecoder(ObjectMapper mapper, MimeType... mimeTypes);
444
445
/** Set max object count in array */
446
void setMaxInMemorySize(int byteCount);
447
}
448
449
/**
450
* Form data reader for reactive streams
451
*/
452
class FormHttpMessageReader extends LoggingCodecSupport
453
implements HttpMessageReader<MultiValueMap<String, String>> {
454
FormHttpMessageReader();
455
456
/** Set default charset */
457
void setDefaultCharset(Charset defaultCharset);
458
/** Set max in-memory size */
459
void setMaxInMemorySize(int byteCount);
460
}
461
462
/**
463
* Form data writer for reactive streams
464
*/
465
class FormHttpMessageWriter extends LoggingCodecSupport
466
implements HttpMessageWriter<MultiValueMap<String, ?>> {
467
FormHttpMessageWriter();
468
469
/** Set default charset */
470
void setDefaultCharset(Charset defaultCharset);
471
}
472
473
/**
474
* Server-Sent Events reader
475
*/
476
class ServerSentEventHttpMessageReader implements HttpMessageReader<Object> {
477
ServerSentEventHttpMessageReader();
478
ServerSentEventHttpMessageReader(Decoder<?> decoder);
479
480
/** Set max in-memory size */
481
void setMaxInMemorySize(int byteCount);
482
}
483
484
/**
485
* Server-Sent Events writer
486
*/
487
class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Object> {
488
ServerSentEventHttpMessageWriter();
489
ServerSentEventHttpMessageWriter(Encoder<?> encoder);
490
}
491
```
492
493
**Usage Examples:**
494
495
```java
496
// Configure reactive codecs
497
WebClient webClient = WebClient.builder()
498
.codecs(configurer -> {
499
// Configure Jackson
500
configurer.defaultCodecs().jackson2JsonDecoder(
501
new Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON)
502
);
503
504
// Add custom codec
505
configurer.customCodecs().register(new MyCustomMessageReader());
506
507
// Set buffer limits
508
configurer.defaultCodecs().maxInMemorySize(1024 * 1024); // 1MB
509
})
510
.build();
511
512
// Server codec configuration
513
@Configuration
514
public class WebConfig implements WebFluxConfigurer {
515
@Override
516
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
517
configurer.defaultCodecs().jackson2JsonEncoder(customJsonEncoder());
518
configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024); // 2MB
519
}
520
}
521
522
// Use codecs automatically
523
Mono<User> user = webClient.get()
524
.uri("/api/users/1")
525
.retrieve()
526
.bodyToMono(User.class); // Uses JSON decoder
527
528
Flux<String> events = webClient.get()
529
.uri("/api/events")
530
.accept(MediaType.TEXT_EVENT_STREAM)
531
.retrieve()
532
.bodyToFlux(String.class); // Uses SSE reader
533
```
534
535
### Multipart Support
536
537
Support for multipart message processing in both servlet and reactive environments.
538
539
```java { .api }
540
/**
541
* Multipart HTTP message reader
542
*/
543
class MultipartHttpMessageReader implements HttpMessageReader<MultiValueMap<String, Part>> {
544
MultipartHttpMessageReader();
545
MultipartHttpMessageReader(HttpMessageReader<?> partReader);
546
547
/** Set max parts count */
548
void setMaxParts(int maxParts);
549
/** Set max disk usage per part */
550
void setMaxDiskUsagePerPart(long maxDiskUsagePerPart);
551
/** Set max memory per part */
552
void setMaxInMemorySize(int maxInMemorySize);
553
/** Set streaming media types */
554
void setStreamingMediaTypes(List<MediaType> streamingMediaTypes);
555
}
556
557
/**
558
* Multipart HTTP message writer
559
*/
560
class MultipartHttpMessageWriter implements HttpMessageWriter<MultiValueMap<String, ?>> {
561
MultipartHttpMessageWriter();
562
MultipartHttpMessageWriter(List<HttpMessageWriter<?>> partWriters);
563
564
/** Set boundary generation strategy */
565
void setBoundaryGenerator(Supplier<String> boundaryGenerator);
566
/** Set multipart charset */
567
void setCharset(Charset charset);
568
}
569
570
/**
571
* Part interface for multipart content
572
*/
573
interface Part {
574
/** Get part name */
575
String name();
576
/** Get part headers */
577
HttpHeaders headers();
578
/** Get part content as data buffer flux */
579
Flux<DataBuffer> content();
580
}
581
582
/**
583
* File part for multipart file uploads
584
*/
585
interface FilePart extends Part {
586
/** Get original filename */
587
String filename();
588
/** Transfer part content to file */
589
Mono<Void> transferTo(Path dest);
590
/** Transfer part content to file */
591
Mono<Void> transferTo(File dest);
592
}
593
594
/**
595
* Form field part for multipart forms
596
*/
597
interface FormFieldPart extends Part {
598
/** Get form field value */
599
String value();
600
}
601
```
602
603
**Usage Examples:**
604
605
```java
606
// Handle multipart upload in reactive controller
607
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
608
public Mono<String> handleUpload(@RequestPart("file") Mono<FilePart> filePartMono) {
609
return filePartMono
610
.flatMap(part -> part.transferTo(Paths.get("/uploads/" + part.filename())))
611
.then(Mono.just("File uploaded successfully"));
612
}
613
614
// Send multipart request with WebClient
615
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
616
parts.add("field", "value");
617
parts.add("file", new FileSystemResource("/path/to/file.txt"));
618
619
Mono<String> response = webClient.post()
620
.uri("/api/upload")
621
.contentType(MediaType.MULTIPART_FORM_DATA)
622
.body(BodyInserters.fromMultipartData(parts))
623
.retrieve()
624
.bodyToMono(String.class);
625
```
626
627
## Exception Handling
628
629
Exception types thrown during message conversion and processing.
630
631
```java { .api }
632
/**
633
* Exception thrown when message conversion fails during reading
634
*/
635
class HttpMessageNotReadableException extends HttpMessageConversionException {
636
HttpMessageNotReadableException(String msg);
637
HttpMessageNotReadableException(String msg, Throwable cause);
638
HttpMessageNotReadableException(String msg, HttpInputMessage httpInputMessage);
639
HttpMessageNotReadableException(String msg, Throwable cause, HttpInputMessage httpInputMessage);
640
}
641
642
/**
643
* Exception thrown when message conversion fails during writing
644
*/
645
class HttpMessageNotWritableException extends HttpMessageConversionException {
646
HttpMessageNotWritableException(String msg);
647
HttpMessageNotWritableException(String msg, Throwable cause);
648
}
649
650
/**
651
* Base exception for message conversion issues
652
*/
653
abstract class HttpMessageConversionException extends NestedRuntimeException {
654
HttpMessageConversionException(String msg);
655
HttpMessageConversionException(String msg, Throwable cause);
656
}
657
```