Use encode with an Object value where feasible

Closes gh-22782
This commit is contained in:
Rossen Stoyanchev
2019-04-11 18:56:54 -04:00
parent 181482fa15
commit 5fc18064f2
7 changed files with 69 additions and 106 deletions

View File

@@ -33,7 +33,6 @@ import org.springframework.core.ResolvableType;
import org.springframework.core.codec.Encoder;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
@@ -148,7 +147,7 @@ public abstract class AbstractEncoderMethodReturnValueHandler implements Handler
Encoder<?> encoder = getEncoder(elementType, mimeType);
return Flux.from((Publisher) publisher).concatMap(value ->
return Flux.from((Publisher) publisher).map(value ->
encodeValue(value, elementType, encoder, bufferFactory, mimeType, hints));
}
@@ -176,7 +175,7 @@ public abstract class AbstractEncoderMethodReturnValueHandler implements Handler
}
@SuppressWarnings("unchecked")
private <T> Mono<DataBuffer> encodeValue(
private <T> DataBuffer encodeValue(
Object element, ResolvableType elementType, @Nullable Encoder<T> encoder,
DataBufferFactory bufferFactory, @Nullable MimeType mimeType,
@Nullable Map<String, Object> hints) {
@@ -184,13 +183,11 @@ public abstract class AbstractEncoderMethodReturnValueHandler implements Handler
if (encoder == null) {
encoder = getEncoder(ResolvableType.forInstance(element), mimeType);
if (encoder == null) {
return Mono.error(new MessagingException(
"No encoder for " + elementType + ", current value type is " + element.getClass()));
throw new MessagingException(
"No encoder for " + elementType + ", current value type is " + element.getClass());
}
}
Mono<T> mono = Mono.just((T) element);
Flux<DataBuffer> dataBuffers = encoder.encode(mono, bufferFactory, elementType, mimeType, hints);
return DataBufferUtils.join(dataBuffers);
return encoder.encodeValue((T) element, bufferFactory, elementType, mimeType, hints);
}
/**

View File

@@ -32,7 +32,6 @@ import org.springframework.core.ResolvableType;
import org.springframework.core.codec.Decoder;
import org.springframework.core.codec.Encoder;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.MimeType;
@@ -124,8 +123,10 @@ final class DefaultRSocketRequester implements RSocketRequester {
publisher = adapter.toPublisher(input);
}
else {
Mono<Payload> payloadMono = encodeValue(input, ResolvableType.forInstance(input), null)
Mono<Payload> payloadMono = Mono
.fromCallable(() -> encodeValue(input, ResolvableType.forInstance(input), null))
.map(this::firstPayload)
.doOnDiscard(Payload.class, Payload::release)
.switchIfEmpty(emptyPayload());
return new DefaultResponseSpec(payloadMono);
}
@@ -140,36 +141,36 @@ final class DefaultRSocketRequester implements RSocketRequester {
if (adapter != null && !adapter.isMultiValue()) {
Mono<Payload> payloadMono = Mono.from(publisher)
.flatMap(value -> encodeValue(value, dataType, encoder))
.map(value -> encodeValue(value, dataType, encoder))
.map(this::firstPayload)
.switchIfEmpty(emptyPayload());
return new DefaultResponseSpec(payloadMono);
}
Flux<Payload> payloadFlux = Flux.from(publisher)
.concatMap(value -> encodeValue(value, dataType, encoder))
.map(value -> encodeValue(value, dataType, encoder))
.switchOnFirst((signal, inner) -> {
DataBuffer data = signal.get();
if (data != null) {
return Flux.concat(
Mono.just(firstPayload(data)),
inner.skip(1).map(PayloadUtils::createPayload));
return Mono.fromCallable(() -> firstPayload(data))
.concatWith(inner.skip(1).map(PayloadUtils::createPayload));
}
else {
return inner.map(PayloadUtils::createPayload);
}
})
.doOnDiscard(Payload.class, Payload::release)
.switchIfEmpty(emptyPayload());
return new DefaultResponseSpec(payloadFlux);
}
@SuppressWarnings("unchecked")
private <T> Mono<DataBuffer> encodeValue(T value, ResolvableType valueType, @Nullable Encoder<?> encoder) {
private <T> DataBuffer encodeValue(T value, ResolvableType valueType, @Nullable Encoder<?> encoder) {
if (encoder == null) {
encoder = strategies.encoder(ResolvableType.forInstance(value), dataMimeType);
}
return DataBufferUtils.join(((Encoder<T>) encoder).encode(
Mono.just(value), strategies.dataBufferFactory(), valueType, dataMimeType, EMPTY_HINTS));
return ((Encoder<T>) encoder).encodeValue(
value, strategies.dataBufferFactory(), valueType, dataMimeType, EMPTY_HINTS);
}
private Payload firstPayload(DataBuffer data) {

View File

@@ -81,7 +81,7 @@ public class MessageMappingMessageHandlerTests {
@Test
public void handleFluxString() {
MessageMappingMessageHandler messsageHandler = initMesssageHandler();
messsageHandler.handleMessage(message("fluxString", "abc\ndef\nghi")).block(Duration.ofSeconds(5));
messsageHandler.handleMessage(message("fluxString", "abc", "def", "ghi")).block(Duration.ofSeconds(5));
verifyOutputContent(Arrays.asList("abc::response", "def::response", "ghi::response"));
}

View File

@@ -129,9 +129,10 @@ public class PayloadMethodArgumentResolverTests {
@Test
public void validateStringMono() {
TestValidator validator = new TestValidator();
ResolvableType type = ResolvableType.forClassWithGenerics(Mono.class, String.class);
MethodParameter param = this.testMethod.arg(type);
Mono<Object> mono = resolveValue(param, Mono.just(toDataBuffer("12345")), new TestValidator());
Mono<Object> mono = resolveValue(param, Mono.just(toDataBuffer("12345")), validator);
StepVerifier.create(mono).expectNextCount(0)
.expectError(MethodArgumentNotValidException.class).verify();
@@ -139,9 +140,11 @@ public class PayloadMethodArgumentResolverTests {
@Test
public void validateStringFlux() {
TestValidator validator = new TestValidator();
ResolvableType type = ResolvableType.forClassWithGenerics(Flux.class, String.class);
MethodParameter param = this.testMethod.arg(type);
Flux<Object> flux = resolveValue(param, Mono.just(toDataBuffer("12345678\n12345")), new TestValidator());
Flux<DataBuffer> content = Flux.just(toDataBuffer("12345678"), toDataBuffer("12345"));
Flux<Object> flux = resolveValue(param, content, validator);
StepVerifier.create(flux)
.expectNext("12345678")