Merge branch '7.0.x'

This commit is contained in:
rstoyanchev
2026-06-05 14:36:23 +01:00
11 changed files with 56 additions and 42 deletions
@@ -105,9 +105,10 @@ public class JacksonJsonDecoder extends AbstractJacksonDecoder<JsonMapper> {
super(mapper, mimeTypes);
}
@Override
public boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType) {
return super.canDecode(elementType, mimeType) && !CharSequence.class.isAssignableFrom(elementType.toClass());
return (super.canDecode(elementType, mimeType) && String.class != elementType.toClass());
}
@Override
@@ -124,7 +124,7 @@ public class JacksonJsonEncoder extends AbstractJacksonEncoder<JsonMapper> {
@Override
public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) {
return super.canEncode(elementType, mimeType) && !String.class.isAssignableFrom(elementType.toClass());
return (super.canEncode(elementType, mimeType) && String.class != elementType.toClass());
}
@Override
@@ -675,13 +675,14 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
if (JACKSON_CBOR_PRESENT || JACKSON_2_CBOR_PRESENT) {
addCodec(this.objectReaders, new DecoderHttpMessageReader<>(getJacksonCborDecoder()));
}
if (JAXB_2_PRESENT) {
// Jackson supports Jackson and JAXB annotations, prefer it if present
if (JACKSON_XML_PRESENT) {
addCodec(this.objectReaders, new DecoderHttpMessageReader<>(getJacksonXmlDecoder()));
}
else if (JAXB_2_PRESENT) {
addCodec(this.objectReaders, new DecoderHttpMessageReader<>(this.jaxb2Decoder != null ?
(Jaxb2XmlDecoder) this.jaxb2Decoder : new Jaxb2XmlDecoder()));
}
else if(JACKSON_XML_PRESENT) {
addCodec(this.objectReaders, new DecoderHttpMessageReader<>(getJacksonXmlDecoder()));
}
if (KOTLIN_SERIALIZATION_PROTOBUF_PRESENT) {
addCodec(this.objectReaders,
new DecoderHttpMessageReader<>(getKotlinSerializationProtobufDecoder()));
@@ -817,13 +818,14 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
if (JACKSON_CBOR_PRESENT || JACKSON_2_CBOR_PRESENT) {
addCodec(writers, new EncoderHttpMessageWriter<>(getJacksonCborEncoder()));
}
if (JAXB_2_PRESENT) {
// Jackson supports Jackson and JAXB annotations, prefer it if present
if (JACKSON_XML_PRESENT) {
addCodec(writers, new EncoderHttpMessageWriter<>(getJacksonXmlEncoder()));
}
else if (JAXB_2_PRESENT) {
addCodec(writers, new EncoderHttpMessageWriter<>(this.jaxb2Encoder != null ?
(Jaxb2XmlEncoder) this.jaxb2Encoder : new Jaxb2XmlEncoder()));
}
else if (JACKSON_XML_PRESENT) {
addCodec(writers, new EncoderHttpMessageWriter<>(getJacksonXmlEncoder()));
}
if (KOTLIN_SERIALIZATION_PROTOBUF_PRESENT) {
addCodec(writers, new EncoderHttpMessageWriter<>(getKotlinSerializationProtobufEncoder()));
}
@@ -102,6 +102,11 @@ public class JacksonXmlDecoder extends AbstractJacksonDecoder<XmlMapper> {
}
@Override
public boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType) {
return (super.canDecode(elementType, mimeType) && String.class != elementType.toClass());
}
@Override
public Flux<Object> decode(Publisher<DataBuffer> input, ResolvableType elementType, @Nullable MimeType mimeType,
@Nullable Map<String, Object> hints) {
@@ -97,6 +97,11 @@ public class JacksonXmlEncoder extends AbstractJacksonEncoder<XmlMapper> {
}
@Override
public boolean canEncode(ResolvableType elementType, @Nullable MimeType mimeType) {
return (super.canEncode(elementType, mimeType) && String.class != elementType.toClass());
}
@Override
public Flux<DataBuffer> encode(Publisher<?> inputStream, DataBufferFactory bufferFactory, ResolvableType elementType,
@Nullable MimeType mimeType, @Nullable Map<String, Object> hints) {
@@ -90,6 +90,7 @@ class JacksonJsonEncoderTests extends AbstractEncoderTests<JacksonJsonEncoder> {
// SPR-15910
assertThat(this.encoder.canEncode(ResolvableType.forClass(Object.class), APPLICATION_OCTET_STREAM)).isFalse();
assertThat(this.encoder.canEncode(ResolvableType.forClass(String.class), null)).isFalse();
assertThatThrownBy(() -> this.encoder.canEncode(ResolvableType.forClass(MappingJacksonValue.class), APPLICATION_JSON))
.isInstanceOf(UnsupportedOperationException.class);
@@ -72,8 +72,8 @@ import org.springframework.http.codec.protobuf.ProtobufDecoder;
import org.springframework.http.codec.protobuf.ProtobufHttpMessageWriter;
import org.springframework.http.codec.smile.JacksonSmileDecoder;
import org.springframework.http.codec.smile.JacksonSmileEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlDecoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.http.codec.xml.JacksonXmlDecoder;
import org.springframework.http.codec.xml.JacksonXmlEncoder;
import org.springframework.util.MimeTypeUtils;
import static org.assertj.core.api.Assertions.assertThat;
@@ -113,7 +113,7 @@ class ClientCodecConfigurerTests {
assertThat(getNextDecoder(readers).getClass()).isEqualTo(JacksonSmileDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationCborDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(JacksonCborDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(Jaxb2XmlDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(JacksonXmlDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationProtobufDecoder.class);
assertSseReader(readers);
assertStringDecoder(getNextDecoder(readers), false);
@@ -138,7 +138,7 @@ class ClientCodecConfigurerTests {
assertThat(getNextEncoder(writers).getClass()).isEqualTo(JacksonSmileEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationCborEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(JacksonCborEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(Jaxb2XmlEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(JacksonXmlEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationProtobufEncoder.class);
assertStringEncoder(getNextEncoder(writers), false);
}
@@ -186,7 +186,7 @@ class ClientCodecConfigurerTests {
assertThat(((JacksonSmileDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((KotlinSerializationCborDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((JacksonCborDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((Jaxb2XmlDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((JacksonXmlDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((KotlinSerializationProtobufDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
ServerSentEventHttpMessageReader reader = (ServerSentEventHttpMessageReader) nextReader(readers);
@@ -68,8 +68,8 @@ import org.springframework.http.codec.protobuf.ProtobufEncoder;
import org.springframework.http.codec.protobuf.ProtobufHttpMessageWriter;
import org.springframework.http.codec.smile.JacksonSmileDecoder;
import org.springframework.http.codec.smile.JacksonSmileEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlDecoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.http.codec.xml.JacksonXmlDecoder;
import org.springframework.http.codec.xml.JacksonXmlEncoder;
import org.springframework.util.MimeTypeUtils;
import static org.assertj.core.api.Assertions.assertThat;
@@ -109,7 +109,7 @@ class CodecConfigurerTests {
assertThat(getNextDecoder(readers).getClass()).isEqualTo(JacksonSmileDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationCborDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(JacksonCborDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(Jaxb2XmlDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(JacksonXmlDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationProtobufDecoder.class);
assertStringDecoder(getNextDecoder(readers), false);
}
@@ -133,7 +133,7 @@ class CodecConfigurerTests {
assertThat(getNextEncoder(writers).getClass()).isEqualTo(JacksonSmileEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationCborEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(JacksonCborEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(Jaxb2XmlEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(JacksonXmlEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationProtobufEncoder.class);
assertStringEncoder(getNextEncoder(writers), false);
}
@@ -181,7 +181,7 @@ class CodecConfigurerTests {
assertThat(getNextDecoder(readers).getClass()).isEqualTo(JacksonSmileDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationCborDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(JacksonCborDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(Jaxb2XmlDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(JacksonXmlDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationProtobufDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(StringDecoder.class);
}
@@ -228,7 +228,7 @@ class CodecConfigurerTests {
assertThat(getNextEncoder(writers).getClass()).isEqualTo(JacksonSmileEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationCborEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(JacksonCborEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(Jaxb2XmlEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(JacksonXmlEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationProtobufEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(CharSequenceEncoder.class);
}
@@ -303,8 +303,8 @@ class CodecConfigurerTests {
JacksonSmileEncoder smileEncoder = new JacksonSmileEncoder();
ProtobufDecoder protobufDecoder = new ProtobufDecoder(ExtensionRegistry.newInstance());
ProtobufEncoder protobufEncoder = new ProtobufEncoder();
Jaxb2XmlEncoder jaxb2Encoder = new Jaxb2XmlEncoder();
Jaxb2XmlDecoder jaxb2Decoder = new Jaxb2XmlDecoder();
JacksonXmlEncoder jacksonXmlEncoder = new JacksonXmlEncoder();
JacksonXmlDecoder jacksonXmlDecoder = new JacksonXmlDecoder();
this.configurer.defaultCodecs().jacksonJsonDecoder(jacksonDecoder);
this.configurer.defaultCodecs().jacksonJsonEncoder(jacksonEncoder);
@@ -312,17 +312,17 @@ class CodecConfigurerTests {
this.configurer.defaultCodecs().jacksonSmileEncoder(smileEncoder);
this.configurer.defaultCodecs().protobufDecoder(protobufDecoder);
this.configurer.defaultCodecs().protobufEncoder(protobufEncoder);
this.configurer.defaultCodecs().jaxb2Decoder(jaxb2Decoder);
this.configurer.defaultCodecs().jaxb2Encoder(jaxb2Encoder);
this.configurer.defaultCodecs().jacksonXmlDecoder(jacksonXmlDecoder);
this.configurer.defaultCodecs().jacksonXmlEncoder(jacksonXmlEncoder);
assertDecoderInstance(jacksonDecoder);
assertDecoderInstance(smileDecoder);
assertDecoderInstance(protobufDecoder);
assertDecoderInstance(jaxb2Decoder);
assertDecoderInstance(jacksonXmlDecoder);
assertEncoderInstance(jacksonEncoder);
assertEncoderInstance(smileEncoder);
assertEncoderInstance(protobufEncoder);
assertEncoderInstance(jaxb2Encoder);
assertEncoderInstance(jacksonXmlEncoder);
}
@Test
@@ -369,15 +369,15 @@ class CodecConfigurerTests {
JacksonJsonDecoder jacksonDecoder = new JacksonJsonDecoder();
JacksonJsonEncoder jacksonEncoder = new JacksonJsonEncoder();
Jaxb2XmlDecoder jaxb2Decoder = new Jaxb2XmlDecoder();
Jaxb2XmlEncoder jaxb2Encoder = new Jaxb2XmlEncoder();
JacksonXmlDecoder jacksonXmlDecoder = new JacksonXmlDecoder();
JacksonXmlEncoder jacksonXmlEncoder = new JacksonXmlEncoder();
ProtobufDecoder protoDecoder = new ProtobufDecoder();
ProtobufEncoder protoEncoder = new ProtobufEncoder();
clone.defaultCodecs().jacksonJsonDecoder(jacksonDecoder);
clone.defaultCodecs().jacksonJsonEncoder(jacksonEncoder);
clone.defaultCodecs().jaxb2Decoder(jaxb2Decoder);
clone.defaultCodecs().jaxb2Encoder(jaxb2Encoder);
clone.defaultCodecs().jacksonXmlDecoder(jacksonXmlDecoder);
clone.defaultCodecs().jacksonXmlEncoder(jacksonXmlEncoder);
clone.defaultCodecs().protobufDecoder(protoDecoder);
clone.defaultCodecs().protobufEncoder(protoEncoder);
@@ -393,8 +393,8 @@ class CodecConfigurerTests {
.map(reader -> ((EncoderHttpMessageWriter<?>) reader).getEncoder())
.collect(Collectors.toList());
assertThat(decoders).contains(jacksonDecoder, jaxb2Decoder, protoDecoder);
assertThat(encoders).contains(jacksonEncoder, jaxb2Encoder, protoEncoder);
assertThat(decoders).contains(jacksonDecoder, jacksonXmlDecoder, protoDecoder);
assertThat(encoders).contains(jacksonEncoder, jacksonXmlEncoder, protoEncoder);
// Original does not have the customizations
@@ -408,8 +408,8 @@ class CodecConfigurerTests {
.map(reader -> ((EncoderHttpMessageWriter<?>) reader).getEncoder())
.collect(Collectors.toList());
assertThat(decoders).doesNotContain(jacksonDecoder, jaxb2Decoder, protoDecoder);
assertThat(encoders).doesNotContain(jacksonEncoder, jaxb2Encoder, protoEncoder);
assertThat(decoders).doesNotContain(jacksonDecoder, jacksonXmlDecoder, protoDecoder);
assertThat(encoders).doesNotContain(jacksonEncoder, jacksonXmlEncoder, protoEncoder);
}
private Decoder<?> getNextDecoder(List<HttpMessageReader<?>> readers) {
@@ -72,8 +72,8 @@ import org.springframework.http.codec.protobuf.ProtobufDecoder;
import org.springframework.http.codec.protobuf.ProtobufHttpMessageWriter;
import org.springframework.http.codec.smile.JacksonSmileDecoder;
import org.springframework.http.codec.smile.JacksonSmileEncoder;
import org.springframework.http.codec.xml.Jaxb2XmlDecoder;
import org.springframework.http.codec.xml.Jaxb2XmlEncoder;
import org.springframework.http.codec.xml.JacksonXmlDecoder;
import org.springframework.http.codec.xml.JacksonXmlEncoder;
import org.springframework.util.MimeTypeUtils;
import static org.assertj.core.api.Assertions.assertThat;
@@ -112,7 +112,7 @@ class ServerCodecConfigurerTests {
assertThat(getNextDecoder(readers).getClass()).isEqualTo(JacksonSmileDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationCborDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(JacksonCborDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(Jaxb2XmlDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(JacksonXmlDecoder.class);
assertThat(getNextDecoder(readers).getClass()).isEqualTo(KotlinSerializationProtobufDecoder.class);
assertStringDecoder(getNextDecoder(readers), false);
}
@@ -136,7 +136,7 @@ class ServerCodecConfigurerTests {
assertThat(getNextEncoder(writers).getClass()).isEqualTo(JacksonSmileEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationCborEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(JacksonCborEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(Jaxb2XmlEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(JacksonXmlEncoder.class);
assertThat(getNextEncoder(writers).getClass()).isEqualTo(KotlinSerializationProtobufEncoder.class);
assertSseWriter(writers);
assertStringEncoder(getNextEncoder(writers), false);
@@ -185,7 +185,7 @@ class ServerCodecConfigurerTests {
assertThat(((JacksonSmileDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((KotlinSerializationCborDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((JacksonCborDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((Jaxb2XmlDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((JacksonXmlDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((KotlinSerializationProtobufDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
assertThat(((StringDecoder) getNextDecoder(readers)).getMaxInMemorySize()).isEqualTo(size);
}
@@ -59,7 +59,7 @@ class JacksonXmlDecoderTests extends AbstractDecoderTests<JacksonXmlDecoder> {
assertThat(decoder.canDecode(ResolvableType.forClass(Pojo.class), MediaType.TEXT_XML)).isTrue();
assertThat(decoder.canDecode(ResolvableType.forClass(Pojo.class), new MediaType("application", "soap+xml"))).isTrue();
assertThat(decoder.canDecode(ResolvableType.forClass(Pojo.class), null)).isTrue();
assertThat(decoder.canDecode(ResolvableType.forClass(String.class), null)).isTrue();
assertThat(decoder.canDecode(ResolvableType.forClass(String.class), null)).isFalse();
assertThat(decoder.canDecode(ResolvableType.forClass(Pojo.class), MediaType.APPLICATION_JSON)).isFalse();
}
@@ -52,7 +52,7 @@ class JacksonXmlEncoderTests extends AbstractLeakCheckingTests {
assertThat(this.encoder.canEncode(pojoType, MediaType.TEXT_XML)).isTrue();
assertThat(this.encoder.canEncode(pojoType, new MediaType("application", "soap+xml"))).isTrue();
assertThat(this.encoder.canEncode(pojoType, null)).isTrue();
assertThat(this.encoder.canEncode(ResolvableType.forClass(String.class), null)).isTrue();
assertThat(this.encoder.canEncode(ResolvableType.forClass(String.class), null)).isFalse();
assertThat(this.encoder.canEncode(ResolvableType.NONE, null)).isTrue();
assertThat(this.encoder.canEncode(ResolvableType.forClass(Pojo.class), MediaType.APPLICATION_JSON)).isFalse();
}