Sync semantics for WebExchangeDataBinder factory
The createBinder method in BindingContext now returns the binder instance rather than a Mono with the expectation that binder initialization (e.g. @InitBinder) does not require blocking. Issue: SPR-14543
This commit is contained in:
@@ -17,8 +17,6 @@ package org.springframework.web.reactive.result.method;
|
|||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import org.springframework.beans.TypeConverter;
|
import org.springframework.beans.TypeConverter;
|
||||||
import org.springframework.beans.TypeMismatchException;
|
import org.springframework.beans.TypeMismatchException;
|
||||||
import org.springframework.core.MethodParameter;
|
import org.springframework.core.MethodParameter;
|
||||||
@@ -42,7 +40,7 @@ public class BindingContext implements TypeConverter {
|
|||||||
|
|
||||||
private final WebBindingInitializer initializer;
|
private final WebBindingInitializer initializer;
|
||||||
|
|
||||||
private final WebDataBinder simpleValueDataBinder;
|
private final TypeConverter simpleValueTypeConverter;
|
||||||
|
|
||||||
|
|
||||||
public BindingContext() {
|
public BindingContext() {
|
||||||
@@ -51,10 +49,15 @@ public class BindingContext implements TypeConverter {
|
|||||||
|
|
||||||
public BindingContext(WebBindingInitializer initializer) {
|
public BindingContext(WebBindingInitializer initializer) {
|
||||||
this.initializer = initializer;
|
this.initializer = initializer;
|
||||||
this.simpleValueDataBinder = new WebExchangeDataBinder(null);
|
this.simpleValueTypeConverter = initTypeConverter(initializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WebExchangeDataBinder initTypeConverter(WebBindingInitializer initializer) {
|
||||||
|
WebExchangeDataBinder binder = new WebExchangeDataBinder(null);
|
||||||
if (initializer != null) {
|
if (initializer != null) {
|
||||||
initializer.initBinder(this.simpleValueDataBinder);
|
initializer.initBinder(binder);
|
||||||
}
|
}
|
||||||
|
return binder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -73,7 +76,7 @@ public class BindingContext implements TypeConverter {
|
|||||||
* @param objectName the name of the target object
|
* @param objectName the name of the target object
|
||||||
* @return a Mono for the created {@link WebDataBinder} instance
|
* @return a Mono for the created {@link WebDataBinder} instance
|
||||||
*/
|
*/
|
||||||
public Mono<WebExchangeDataBinder> createBinder(ServerWebExchange exchange, Object target,
|
public WebExchangeDataBinder createBinder(ServerWebExchange exchange, Object target,
|
||||||
String objectName) {
|
String objectName) {
|
||||||
|
|
||||||
WebExchangeDataBinder dataBinder = createBinderInstance(target, objectName);
|
WebExchangeDataBinder dataBinder = createBinderInstance(target, objectName);
|
||||||
@@ -87,24 +90,24 @@ public class BindingContext implements TypeConverter {
|
|||||||
return new WebExchangeDataBinder(target, objectName);
|
return new WebExchangeDataBinder(target, objectName);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Mono<WebExchangeDataBinder> initBinder(WebExchangeDataBinder binder, ServerWebExchange exchange) {
|
protected WebExchangeDataBinder initBinder(WebExchangeDataBinder binder, ServerWebExchange exchange) {
|
||||||
return Mono.just(binder);
|
return binder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T convertIfNecessary(Object value, Class<T> requiredType) throws TypeMismatchException {
|
public <T> T convertIfNecessary(Object value, Class<T> requiredType) throws TypeMismatchException {
|
||||||
return this.simpleValueDataBinder.convertIfNecessary(value, requiredType);
|
return this.simpleValueTypeConverter.convertIfNecessary(value, requiredType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T convertIfNecessary(Object value, Class<T> requiredType, MethodParameter methodParam)
|
public <T> T convertIfNecessary(Object value, Class<T> requiredType, MethodParameter methodParam)
|
||||||
throws TypeMismatchException {
|
throws TypeMismatchException {
|
||||||
|
|
||||||
return this.simpleValueDataBinder.convertIfNecessary(value, requiredType, methodParam);
|
return this.simpleValueTypeConverter.convertIfNecessary(value, requiredType, methodParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T convertIfNecessary(Object value, Class<T> requiredType, Field field)
|
public <T> T convertIfNecessary(Object value, Class<T> requiredType, Field field)
|
||||||
throws TypeMismatchException {
|
throws TypeMismatchException {
|
||||||
|
|
||||||
return this.simpleValueDataBinder.convertIfNecessary(value, requiredType, field);
|
return this.simpleValueTypeConverter.convertIfNecessary(value, requiredType, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import java.lang.annotation.Annotation;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
@@ -39,6 +38,7 @@ import org.springframework.http.server.reactive.ServerHttpResponse;
|
|||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.validation.Validator;
|
import org.springframework.validation.Validator;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.WebExchangeDataBinder;
|
||||||
import org.springframework.web.reactive.result.method.BindingContext;
|
import org.springframework.web.reactive.result.method.BindingContext;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
import org.springframework.web.server.ServerWebInputException;
|
import org.springframework.web.server.ServerWebInputException;
|
||||||
@@ -143,7 +143,8 @@ public abstract class AbstractMessageReaderArgumentResolver {
|
|||||||
}
|
}
|
||||||
Object[] hints = extractValidationHints(bodyParameter);
|
Object[] hints = extractValidationHints(bodyParameter);
|
||||||
if (hints != null) {
|
if (hints != null) {
|
||||||
flux = flux.concatMap(getValidator(hints, bodyParameter, bindingContext, exchange));
|
flux = flux.doOnNext(target ->
|
||||||
|
validate(target, hints, bodyParameter, bindingContext, exchange));
|
||||||
}
|
}
|
||||||
return Mono.just(adapter.fromPublisher(flux));
|
return Mono.just(adapter.fromPublisher(flux));
|
||||||
}
|
}
|
||||||
@@ -162,7 +163,8 @@ public abstract class AbstractMessageReaderArgumentResolver {
|
|||||||
}
|
}
|
||||||
Object[] hints = extractValidationHints(bodyParameter);
|
Object[] hints = extractValidationHints(bodyParameter);
|
||||||
if (hints != null) {
|
if (hints != null) {
|
||||||
mono = mono.then(getValidator(hints, bodyParameter, bindingContext, exchange));
|
mono = mono.doOnNext(target ->
|
||||||
|
validate(target, hints, bodyParameter, bindingContext, exchange));
|
||||||
}
|
}
|
||||||
if (adapter != null) {
|
if (adapter != null) {
|
||||||
return Mono.just(adapter.fromPublisher(mono));
|
return Mono.just(adapter.fromPublisher(mono));
|
||||||
@@ -207,19 +209,15 @@ public abstract class AbstractMessageReaderArgumentResolver {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected <T> Function<T, Mono<T>> getValidator(Object[] validationHints,
|
protected void validate(Object target, Object[] validationHints,
|
||||||
MethodParameter param, BindingContext binding, ServerWebExchange exchange) {
|
MethodParameter param, BindingContext binding, ServerWebExchange exchange) {
|
||||||
|
|
||||||
String name = Conventions.getVariableNameForParameter(param);
|
String name = Conventions.getVariableNameForParameter(param);
|
||||||
|
WebExchangeDataBinder binder = binding.createBinder(exchange, target, name);
|
||||||
return target -> binding.createBinder(exchange, target, name)
|
binder.validate(validationHints);
|
||||||
.map(binder -> {
|
if (binder.getBindingResult().hasErrors()) {
|
||||||
binder.validate(validationHints);
|
throw new ServerWebInputException("Validation failed", param);
|
||||||
if (binder.getBindingResult().hasErrors()) {
|
}
|
||||||
throw new ServerWebInputException("Validation failed", param);
|
|
||||||
}
|
|
||||||
return target;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user