Spring Web module providing web application infrastructure including HTTP integration, servlet filters, Spring web MVC framework, and reactive web stack support
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.
Traditional message converters for converting between HTTP messages and Java objects in servlet-based applications.
/**
* Contract for HTTP message converters
*/
interface HttpMessageConverter<T> {
/** Check if this converter can read the given class and media type */
boolean canRead(Class<?> clazz, MediaType mediaType);
/** Check if this converter can write the given class and media type */
boolean canWrite(Class<?> clazz, MediaType mediaType);
/** Get the supported media types for this converter */
List<MediaType> getSupportedMediaTypes();
/** Read object from HTTP input message */
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
/** Write object to HTTP output message */
void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
/**
* Generic version supporting parameterized types
*/
interface GenericHttpMessageConverter<T> extends HttpMessageConverter<T> {
/** Check if converter can read the generic type */
boolean canRead(Type type, Class<?> contextClass, MediaType mediaType);
/** Check if converter can write the generic type */
boolean canWrite(Type type, Class<?> clazz, MediaType mediaType);
/** Read generic type from HTTP message */
T read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
/** Write generic type to HTTP message */
void write(T t, Type type, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}Built-in converters for common data formats and types.
/**
* Base class for message converter implementations
*/
abstract class AbstractHttpMessageConverter<T> implements HttpMessageConverter<T> {
protected AbstractHttpMessageConverter(MediaType supportedMediaType);
protected AbstractHttpMessageConverter(MediaType... supportedMediaTypes);
/** Set supported media types */
void setSupportedMediaTypes(List<MediaType> supportedMediaTypes);
/** Get supported media types */
List<MediaType> getSupportedMediaTypes();
// Template methods for subclasses
protected abstract boolean supports(Class<?> clazz);
protected abstract T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
protected abstract void writeInternal(T t, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
/**
* String message converter
*/
class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> {
StringHttpMessageConverter();
StringHttpMessageConverter(Charset defaultCharset);
/** Set whether to write Accept-Charset header */
void setWriteAcceptCharset(boolean writeAcceptCharset);
/** Set available charsets for Accept-Charset header */
void setAvailableCharsets(List<Charset> availableCharsets);
}
/**
* Byte array message converter
*/
class ByteArrayHttpMessageConverter extends AbstractHttpMessageConverter<byte[]> {
ByteArrayHttpMessageConverter();
// Supports application/octet-stream and all other media types
}
/**
* Resource message converter
*/
class ResourceHttpMessageConverter extends AbstractHttpMessageConverter<Resource> {
ResourceHttpMessageConverter();
ResourceHttpMessageConverter(boolean supportsReadStreaming);
// Automatically detects content type from resource
}
/**
* Form data message converter
*/
class FormHttpMessageConverter implements HttpMessageConverter<MultiValueMap<String, ?>> {
FormHttpMessageConverter();
/** Set default charset for form encoding */
void setCharset(Charset charset);
/** Set supported media types */
void setSupportedMediaTypes(List<MediaType> supportedMediaTypes);
/** Set multipart character sets */
void setMultipartCharsets(Map<String, Charset> multipartCharsets);
}
/**
* Enhanced form converter with multipart support
*/
class AllEncompassingFormHttpMessageConverter extends FormHttpMessageConverter {
AllEncompassingFormHttpMessageConverter();
// Adds support for multipart/form-data with part converters
}Converters for JSON serialization using popular libraries.
/**
* Jackson 2 JSON message converter
*/
class MappingJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {
MappingJackson2HttpMessageConverter();
MappingJackson2HttpMessageConverter(ObjectMapper objectMapper);
/** Set the ObjectMapper to use */
void setObjectMapper(ObjectMapper objectMapper);
/** Get the current ObjectMapper */
ObjectMapper getObjectMapper();
/** Set JSON prefix for security */
void setJsonPrefix(String jsonPrefix);
/** Set whether to prefix JSON output */
void setPrefixJson(boolean prefixJson);
}
/**
* Base class for Jackson converters
*/
abstract class AbstractJackson2HttpMessageConverter extends AbstractGenericHttpMessageConverter<Object> {
/** Set pretty print formatting */
void setPrettyPrint(boolean prettyPrint);
/** Add supported media types */
protected void addDefaultMediaTypes(MediaType... mediaTypes);
}
/**
* Google Gson JSON message converter
*/
class GsonHttpMessageConverter extends AbstractGenericHttpMessageConverter<Object> {
GsonHttpMessageConverter();
GsonHttpMessageConverter(Gson gson);
/** Set the Gson instance to use */
void setGson(Gson gson);
/** Get the current Gson instance */
Gson getGson();
/** Set JSON prefix for security */
void setJsonPrefix(String jsonPrefix);
}
/**
* JSON-B message converter
*/
class JsonbHttpMessageConverter extends AbstractGenericHttpMessageConverter<Object> {
JsonbHttpMessageConverter();
JsonbHttpMessageConverter(Jsonb jsonb);
/** Set the Jsonb instance to use */
void setJsonb(Jsonb jsonb);
/** Get the current Jsonb instance */
Jsonb getJsonb();
}Converters for XML serialization and deserialization.
/**
* JAXB2 XML message converter
*/
class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessageConverter<Object> {
Jaxb2RootElementHttpMessageConverter();
// Supports classes annotated with @XmlRootElement or @XmlType
}
/**
* Marshalling XML message converter using Spring's marshalling abstractions
*/
class MarshallingHttpMessageConverter extends AbstractHttpMessageConverter<Object> {
MarshallingHttpMessageConverter();
MarshallingHttpMessageConverter(Marshaller marshaller);
MarshallingHttpMessageConverter(Marshaller marshaller, Unmarshaller unmarshaller);
/** Set the marshaller for writing XML */
void setMarshaller(Marshaller marshaller);
/** Set the unmarshaller for reading XML */
void setUnmarshaller(Unmarshaller unmarshaller);
}
/**
* Base class for JAXB2 converters
*/
abstract class AbstractJaxb2HttpMessageConverter<T> extends AbstractGenericHttpMessageConverter<T> {
/** Set whether to process external entities */
void setProcessExternalEntities(boolean processExternalEntities);
/** Set whether to support DTD parsing */
void setSupportDtd(boolean supportDtd);
}Usage Examples:
// Configure message converters in RestTemplate
RestTemplate restTemplate = new RestTemplate();
// Add custom Jackson converter
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(objectMapper);
List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
converters.add(0, jsonConverter); // Add as first converter
// Configure form converter
FormHttpMessageConverter formConverter = new FormHttpMessageConverter();
formConverter.setCharset(StandardCharsets.UTF_8);
converters.add(formConverter);
// Use converters automatically
User user = restTemplate.getForObject("/api/users/1", User.class); // Uses JSON converter
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.add("username", "john");
restTemplate.postForObject("/api/login", form, String.class); // Uses form converterReactive message readers and writers for non-blocking streaming applications.
/**
* Contract to read HTTP messages reactively
*/
interface HttpMessageReader<T> {
/** Check if this reader can read the given type and media type */
boolean canRead(ResolvableType elementType, MediaType mediaType);
/** Get readable media types */
List<MediaType> getReadableMediaTypes();
/** Get readable media types for a specific type */
default List<MediaType> getReadableMediaTypes(ResolvableType elementType) {
return getReadableMediaTypes();
}
/** Read object stream from reactive HTTP input */
Flux<T> read(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints);
/** Read single object from reactive HTTP input */
Mono<T> readMono(ResolvableType elementType, ReactiveHttpInputMessage message, Map<String, Object> hints);
}
/**
* Contract to write HTTP messages reactively
*/
interface HttpMessageWriter<T> {
/** Check if this writer can write the given type and media type */
boolean canWrite(ResolvableType elementType, MediaType mediaType);
/** Get writable media types */
List<MediaType> getWritableMediaTypes();
/** Get writable media types for a specific type */
default List<MediaType> getWritableMediaTypes(ResolvableType elementType) {
return getWritableMediaTypes();
}
/** Write object stream to reactive HTTP output */
Mono<Void> write(Publisher<? extends T> inputStream, ResolvableType elementType,
MediaType mediaType, ReactiveHttpOutputMessage message,
Map<String, Object> hints);
}Configuration interfaces for managing HTTP message readers and writers.
/**
* Contract to configure HTTP message readers and writers
*/
interface CodecConfigurer {
/** Configure default codecs */
DefaultCodecs defaultCodecs();
/** Configure custom codecs */
CustomCodecs customCodecs();
/** Set whether to register default codecs */
void registerDefaults(boolean registerDefaults);
/** Get configured readers */
List<HttpMessageReader<?>> getReaders();
/** Get configured writers */
List<HttpMessageWriter<?>> getWriters();
/** Clone this configurer */
CodecConfigurer clone();
}
/**
* Client-specific codec configurer
*/
interface ClientCodecConfigurer extends CodecConfigurer {
/** Configure default codecs for client use */
ClientDefaultCodecs defaultCodecs();
interface ClientDefaultCodecs extends DefaultCodecs {
/** Set max in-memory buffer size */
void maxInMemorySize(int byteCount);
/** Configure multipart codecs */
MultipartCodecs multipartCodecs();
/** Set enable logging request details */
void enableLoggingRequestDetails(boolean enable);
}
}
/**
* Server-specific codec configurer
*/
interface ServerCodecConfigurer extends CodecConfigurer {
/** Configure default codecs for server use */
ServerDefaultCodecs defaultCodecs();
interface ServerDefaultCodecs extends DefaultCodecs {
/** Set max in-memory buffer size */
void maxInMemorySize(int byteCount);
/** Configure multipart codecs */
MultipartCodecs multipartCodecs();
/** Set enable logging request details */
void enableLoggingRequestDetails(boolean enable);
}
}
/**
* Default codec configuration
*/
interface DefaultCodecs {
/** Configure Jackson JSON codec */
void jackson2JsonDecoder(Decoder<?> decoder);
void jackson2JsonEncoder(Encoder<?> encoder);
/** Configure Jackson Smile codec */
void jackson2SmileDecoder(Decoder<?> decoder);
void jackson2SmileEncoder(Encoder<?> encoder);
/** Configure protobuf codec */
void protobufDecoder(Decoder<?> decoder);
void protobufEncoder(Encoder<?> encoder);
/** Configure JAXB2 codec */
void jaxb2Decoder(Decoder<?> decoder);
void jaxb2Encoder(Encoder<?> encoder);
/** Configure multipart reader */
void multipartReader(HttpMessageReader<?> reader);
/** Configure multipart writer */
void multipartWriter(HttpMessageWriter<?> writer);
}
/**
* Custom codec configuration
*/
interface CustomCodecs {
/** Register custom reader */
void register(HttpMessageReader<?> reader);
/** Register custom writer */
void register(HttpMessageWriter<?> writer);
/** Register reader with order */
void registerWithDefaultConfig(HttpMessageReader<?> reader);
/** Register writer with order */
void registerWithDefaultConfig(HttpMessageWriter<?> writer);
}Built-in reactive codecs for common data formats.
/**
* Decoder-based HTTP message reader
*/
class DecoderHttpMessageReader<T> implements HttpMessageReader<T> {
DecoderHttpMessageReader(Decoder<T> decoder);
/** Get the underlying decoder */
Decoder<T> getDecoder();
}
/**
* Encoder-based HTTP message writer
*/
class EncoderHttpMessageWriter<T> implements HttpMessageWriter<T> {
EncoderHttpMessageWriter(Encoder<T> encoder);
/** Get the underlying encoder */
Encoder<T> getEncoder();
}
/**
* Jackson 2 JSON encoder for reactive streams
*/
class Jackson2JsonEncoder extends Jackson2CodecSupport implements HttpMessageEncoder<Object> {
Jackson2JsonEncoder();
Jackson2JsonEncoder(ObjectMapper mapper, MimeType... mimeTypes);
/** Set streaming media types */
void setStreamingMediaTypes(List<MediaType> mediaTypes);
}
/**
* Jackson 2 JSON decoder for reactive streams
*/
class Jackson2JsonDecoder extends Jackson2CodecSupport implements HttpMessageDecoder<Object> {
Jackson2JsonDecoder();
Jackson2JsonDecoder(ObjectMapper mapper, MimeType... mimeTypes);
/** Set max object count in array */
void setMaxInMemorySize(int byteCount);
}
/**
* Form data reader for reactive streams
*/
class FormHttpMessageReader extends LoggingCodecSupport
implements HttpMessageReader<MultiValueMap<String, String>> {
FormHttpMessageReader();
/** Set default charset */
void setDefaultCharset(Charset defaultCharset);
/** Set max in-memory size */
void setMaxInMemorySize(int byteCount);
}
/**
* Form data writer for reactive streams
*/
class FormHttpMessageWriter extends LoggingCodecSupport
implements HttpMessageWriter<MultiValueMap<String, ?>> {
FormHttpMessageWriter();
/** Set default charset */
void setDefaultCharset(Charset defaultCharset);
}
/**
* Server-Sent Events reader
*/
class ServerSentEventHttpMessageReader implements HttpMessageReader<Object> {
ServerSentEventHttpMessageReader();
ServerSentEventHttpMessageReader(Decoder<?> decoder);
/** Set max in-memory size */
void setMaxInMemorySize(int byteCount);
}
/**
* Server-Sent Events writer
*/
class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Object> {
ServerSentEventHttpMessageWriter();
ServerSentEventHttpMessageWriter(Encoder<?> encoder);
}Usage Examples:
// Configure reactive codecs
WebClient webClient = WebClient.builder()
.codecs(configurer -> {
// Configure Jackson
configurer.defaultCodecs().jackson2JsonDecoder(
new Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON)
);
// Add custom codec
configurer.customCodecs().register(new MyCustomMessageReader());
// Set buffer limits
configurer.defaultCodecs().maxInMemorySize(1024 * 1024); // 1MB
})
.build();
// Server codec configuration
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.defaultCodecs().jackson2JsonEncoder(customJsonEncoder());
configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024); // 2MB
}
}
// Use codecs automatically
Mono<User> user = webClient.get()
.uri("/api/users/1")
.retrieve()
.bodyToMono(User.class); // Uses JSON decoder
Flux<String> events = webClient.get()
.uri("/api/events")
.accept(MediaType.TEXT_EVENT_STREAM)
.retrieve()
.bodyToFlux(String.class); // Uses SSE readerSupport for multipart message processing in both servlet and reactive environments.
/**
* Multipart HTTP message reader
*/
class MultipartHttpMessageReader implements HttpMessageReader<MultiValueMap<String, Part>> {
MultipartHttpMessageReader();
MultipartHttpMessageReader(HttpMessageReader<?> partReader);
/** Set max parts count */
void setMaxParts(int maxParts);
/** Set max disk usage per part */
void setMaxDiskUsagePerPart(long maxDiskUsagePerPart);
/** Set max memory per part */
void setMaxInMemorySize(int maxInMemorySize);
/** Set streaming media types */
void setStreamingMediaTypes(List<MediaType> streamingMediaTypes);
}
/**
* Multipart HTTP message writer
*/
class MultipartHttpMessageWriter implements HttpMessageWriter<MultiValueMap<String, ?>> {
MultipartHttpMessageWriter();
MultipartHttpMessageWriter(List<HttpMessageWriter<?>> partWriters);
/** Set boundary generation strategy */
void setBoundaryGenerator(Supplier<String> boundaryGenerator);
/** Set multipart charset */
void setCharset(Charset charset);
}
/**
* Part interface for multipart content
*/
interface Part {
/** Get part name */
String name();
/** Get part headers */
HttpHeaders headers();
/** Get part content as data buffer flux */
Flux<DataBuffer> content();
}
/**
* File part for multipart file uploads
*/
interface FilePart extends Part {
/** Get original filename */
String filename();
/** Transfer part content to file */
Mono<Void> transferTo(Path dest);
/** Transfer part content to file */
Mono<Void> transferTo(File dest);
}
/**
* Form field part for multipart forms
*/
interface FormFieldPart extends Part {
/** Get form field value */
String value();
}Usage Examples:
// Handle multipart upload in reactive controller
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Mono<String> handleUpload(@RequestPart("file") Mono<FilePart> filePartMono) {
return filePartMono
.flatMap(part -> part.transferTo(Paths.get("/uploads/" + part.filename())))
.then(Mono.just("File uploaded successfully"));
}
// Send multipart request with WebClient
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
parts.add("field", "value");
parts.add("file", new FileSystemResource("/path/to/file.txt"));
Mono<String> response = webClient.post()
.uri("/api/upload")
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData(parts))
.retrieve()
.bodyToMono(String.class);Exception types thrown during message conversion and processing.
/**
* Exception thrown when message conversion fails during reading
*/
class HttpMessageNotReadableException extends HttpMessageConversionException {
HttpMessageNotReadableException(String msg);
HttpMessageNotReadableException(String msg, Throwable cause);
HttpMessageNotReadableException(String msg, HttpInputMessage httpInputMessage);
HttpMessageNotReadableException(String msg, Throwable cause, HttpInputMessage httpInputMessage);
}
/**
* Exception thrown when message conversion fails during writing
*/
class HttpMessageNotWritableException extends HttpMessageConversionException {
HttpMessageNotWritableException(String msg);
HttpMessageNotWritableException(String msg, Throwable cause);
}
/**
* Base exception for message conversion issues
*/
abstract class HttpMessageConversionException extends NestedRuntimeException {
HttpMessageConversionException(String msg);
HttpMessageConversionException(String msg, Throwable cause);
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework--spring-web