use of org.springframework.core.ResolvableType in project spring-framework by spring-projects.
the class ErrorsMethodArgumentResolver method getModelAttributeName.
private String getModelAttributeName(MethodParameter parameter) {
Assert.isTrue(parameter.getParameterIndex() > 0, "Errors argument must be immediately after a model attribute argument.");
int index = parameter.getParameterIndex() - 1;
MethodParameter attributeParam = new MethodParameter(parameter.getMethod(), index);
Class<?> attributeType = attributeParam.getParameterType();
ResolvableType type = ResolvableType.forMethodParameter(attributeParam);
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type.resolve());
Assert.isNull(adapter, "Errors/BindingResult cannot be used with an async model attribute. " + "Either declare the model attribute without the async wrapper type " + "or handle WebExchangeBindException through the async type.");
ModelAttribute annot = parameter.getParameterAnnotation(ModelAttribute.class);
if (annot != null && StringUtils.hasText(annot.value())) {
return annot.value();
}
// TODO: Conventions does not deal with async wrappers
return ClassUtils.getShortNameAsProperty(attributeType);
}
use of org.springframework.core.ResolvableType in project spring-framework by spring-projects.
the class ModelAttributeMethodArgumentResolver method resolveArgument.
@Override
public Mono<Object> resolveArgument(MethodParameter parameter, BindingContext context, ServerWebExchange exchange) {
ResolvableType type = ResolvableType.forMethodParameter(parameter);
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type.resolve());
ResolvableType valueType = (adapter != null ? type.getGeneric(0) : type);
Assert.state(adapter == null || !adapter.isMultiValue(), getClass().getSimpleName() + " doesn't support multi-value reactive type wrapper: " + parameter.getGenericParameterType());
String name = getAttributeName(valueType, parameter);
Mono<?> valueMono = getAttributeMono(name, valueType, context.getModel());
Map<String, Object> model = context.getModel().asMap();
MonoProcessor<BindingResult> bindingResultMono = MonoProcessor.create();
model.put(BindingResult.MODEL_KEY_PREFIX + name, bindingResultMono);
return valueMono.then(value -> {
WebExchangeDataBinder binder = context.createDataBinder(exchange, value, name);
return binder.bind(exchange).doOnError(bindingResultMono::onError).doOnSuccess(aVoid -> {
validateIfApplicable(binder, parameter);
BindingResult errors = binder.getBindingResult();
model.put(BindingResult.MODEL_KEY_PREFIX + name, errors);
model.put(name, value);
bindingResultMono.onNext(errors);
}).then(Mono.fromCallable(() -> {
BindingResult errors = binder.getBindingResult();
if (adapter != null) {
return adapter.fromPublisher(errors.hasErrors() ? Mono.error(new WebExchangeBindException(parameter, errors)) : valueMono);
} else {
if (errors.hasErrors() && !hasErrorsArgument(parameter)) {
throw new WebExchangeBindException(parameter, errors);
}
return value;
}
}));
});
}
use of org.springframework.core.ResolvableType in project spring-framework by spring-projects.
the class AbstractMessageWriterResultHandler method writeBody.
@SuppressWarnings("unchecked")
protected Mono<Void> writeBody(Object body, MethodParameter bodyParameter, ServerWebExchange exchange) {
ResolvableType bodyType = ResolvableType.forMethodParameter(bodyParameter);
Class<?> bodyClass = bodyType.resolve();
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(bodyClass, body);
Publisher<?> publisher;
ResolvableType elementType;
if (adapter != null) {
publisher = adapter.toPublisher(body);
elementType = adapter.isNoValue() ? ResolvableType.forClass(Void.class) : bodyType.getGeneric(0);
} else {
publisher = Mono.justOrEmpty(body);
elementType = (bodyClass == null && body != null ? ResolvableType.forInstance(body) : bodyType);
}
if (void.class == elementType.getRawClass() || Void.class == elementType.getRawClass()) {
return Mono.from((Publisher<Void>) publisher);
}
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
MediaType bestMediaType = selectMediaType(exchange, () -> getProducibleMediaTypes(elementType));
if (bestMediaType != null) {
for (HttpMessageWriter<?> messageWriter : getMessageWriters()) {
if (messageWriter.canWrite(elementType, bestMediaType)) {
return (messageWriter instanceof ServerHttpMessageWriter ? ((ServerHttpMessageWriter<?>) messageWriter).write((Publisher) publisher, bodyType, elementType, bestMediaType, request, response, Collections.emptyMap()) : messageWriter.write((Publisher) publisher, elementType, bestMediaType, response, Collections.emptyMap()));
}
}
} else {
if (getProducibleMediaTypes(elementType).isEmpty()) {
return Mono.error(new IllegalStateException("No converter for return value type: " + elementType));
}
}
return Mono.error(new NotAcceptableStatusException(getProducibleMediaTypes(elementType)));
}
use of org.springframework.core.ResolvableType in project spring-framework by spring-projects.
the class DefaultEntityResponseBuilderTests method fromPublisherResolvableType.
@Test
public void fromPublisherResolvableType() throws Exception {
Flux<String> body = Flux.just("foo", "bar");
ResolvableType type = ResolvableType.forClass(String.class);
EntityResponse<Flux<String>> response = EntityResponse.fromPublisher(body, type).build().block();
assertSame(body, response.entity());
}
use of org.springframework.core.ResolvableType in project spring-framework by spring-projects.
the class MessageReaderArgumentResolverTests method emptyBody.
// More extensive "empty body" tests in RequestBody- and HttpEntityArgumentResolverTests
// SPR-9942
@Test
// SPR-9942
@SuppressWarnings("unchecked")
public void emptyBody() throws Exception {
ServerWebExchange exchange = post("/path").contentType(MediaType.APPLICATION_JSON).toExchange();
ResolvableType type = forClassWithGenerics(Mono.class, TestBean.class);
MethodParameter param = this.testMethod.arg(type);
Mono<TestBean> result = (Mono<TestBean>) this.resolver.readBody(param, true, this.bindingContext, exchange).block();
StepVerifier.create(result).expectError(ServerWebInputException.class).verify();
}
Aggregations