Here are the examples of the java api org.springframework.core.ReactiveAdapterRegistry taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.
95 Examples
19
View Source File : RequestMappingHandlerAdapter.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Configure the registry for reactive library types to be supported as
* return values from controller methods.
* @since 5.0.5
*/
public void setReactiveAdapterRegistry(ReactiveAdapterRegistry reactiveAdapterRegistry) {
this.reactiveAdapterRegistry = reactiveAdapterRegistry;
}
19
View Source File : InvocableHandlerMethod.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Configure a reactive adapter registry. This is needed for cases where the response is
* fully handled within the controller in combination with an async void return value.
* <p>By default this is a {@link ReactiveAdapterRegistry} with default settings.
*/
public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) {
this.reactiveAdapterRegistry = registry;
}
19
View Source File : RequestMappingHandlerAdapter.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Configure the registry for adapting various reactive types.
* <p>By default this is an instance of {@link ReactiveAdapterRegistry} with
* default settings.
*/
public void setReactiveAdapterRegistry(@Nullable ReactiveAdapterRegistry registry) {
this.reactiveAdapterRegistry = registry;
}
19
View Source File : ModelInitializer.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Package-private clreplaced to replacedist {@link RequestMappingHandlerAdapter} with
* default model initialization through {@code @ModelAttribute} methods.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
clreplaced ModelInitializer {
private final ControllerMethodResolver methodResolver;
private final ReactiveAdapterRegistry adapterRegistry;
public ModelInitializer(ControllerMethodResolver methodResolver, ReactiveAdapterRegistry adapterRegistry) {
replacedert.notNull(methodResolver, "ControllerMethodResolver is required");
replacedert.notNull(adapterRegistry, "ReactiveAdapterRegistry is required");
this.methodResolver = methodResolver;
this.adapterRegistry = adapterRegistry;
}
/**
* Initialize the {@link org.springframework.ui.Model Model} based on a
* (type-level) {@code @SessionAttributes} annotation and
* {@code @ModelAttribute} methods.
* @param handlerMethod the target controller method
* @param bindingContext the context containing the model
* @param exchange the current exchange
* @return a {@code Mono} for when the model is populated.
*/
@SuppressWarnings("Convert2MethodRef")
public Mono<Void> initModel(HandlerMethod handlerMethod, InitBinderBindingContext bindingContext, ServerWebExchange exchange) {
List<InvocableHandlerMethod> modelMethods = this.methodResolver.getModelAttributeMethods(handlerMethod);
SessionAttributesHandler sessionAttributesHandler = this.methodResolver.getSessionAttributesHandler(handlerMethod);
if (!sessionAttributesHandler.hreplacedessionAttributes()) {
return invokeModelAttributeMethods(bindingContext, modelMethods, exchange);
}
return exchange.getSession().flatMap(session -> {
Map<String, Object> attributes = sessionAttributesHandler.retrieveAttributes(session);
bindingContext.getModel().mergeAttributes(attributes);
bindingContext.setSessionContext(sessionAttributesHandler, session);
return invokeModelAttributeMethods(bindingContext, modelMethods, exchange).doOnSuccess(aVoid -> findModelAttributes(handlerMethod, sessionAttributesHandler).forEach(name -> {
if (!bindingContext.getModel().containsAttribute(name)) {
Object value = session.getRequiredAttribute(name);
bindingContext.getModel().addAttribute(name, value);
}
}));
});
}
private Mono<Void> invokeModelAttributeMethods(BindingContext bindingContext, List<InvocableHandlerMethod> modelMethods, ServerWebExchange exchange) {
List<Mono<HandlerResult>> resultList = new ArrayList<>();
modelMethods.forEach(invocable -> resultList.add(invocable.invoke(exchange, bindingContext)));
return Mono.zip(resultList, objectArray -> Arrays.stream(objectArray).map(object -> handleResult(((HandlerResult) object), bindingContext)).collect(Collectors.toList())).flatMap(Mono::when);
}
private Mono<Void> handleResult(HandlerResult handlerResult, BindingContext bindingContext) {
Object value = handlerResult.getReturnValue();
if (value != null) {
ResolvableType type = handlerResult.getReturnType();
ReactiveAdapter adapter = this.adapterRegistry.getAdapter(type.resolve(), value);
if (isAsyncVoidType(type, adapter)) {
return Mono.from(adapter.toPublisher(value));
}
String name = getAttributeName(handlerResult.getReturnTypeSource());
bindingContext.getModel().asMap().putIfAbsent(name, value);
}
return Mono.empty();
}
private boolean isAsyncVoidType(ResolvableType type, @Nullable ReactiveAdapter adapter) {
return (adapter != null && (adapter.isNoValue() || type.resolveGeneric() == Void.clreplaced));
}
private String getAttributeName(MethodParameter param) {
return Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(param.getAnnotatedElement(), ModelAttribute.clreplaced)).filter(ann -> StringUtils.hasText(ann.value())).map(ModelAttribute::value).orElseGet(() -> Conventions.getVariableNameForParameter(param));
}
/**
* Find {@code @ModelAttribute} arguments also listed as {@code @SessionAttributes}.
*/
private List<String> findModelAttributes(HandlerMethod handlerMethod, SessionAttributesHandler sessionAttributesHandler) {
List<String> result = new ArrayList<>();
for (MethodParameter parameter : handlerMethod.getMethodParameters()) {
if (parameter.hasParameterAnnotation(ModelAttribute.clreplaced)) {
String name = getNameForParameter(parameter);
Clreplaced<?> paramType = parameter.getParameterType();
if (sessionAttributesHandler.isHandlerSessionAttribute(name, paramType)) {
result.add(name);
}
}
}
return result;
}
/**
* Derive the model attribute name for the given method parameter based on
* a {@code @ModelAttribute} parameter annotation (if present) or falling
* back on parameter type based conventions.
* @param parameter a descriptor for the method parameter
* @return the derived name
* @see Conventions#getVariableNameForParameter(MethodParameter)
*/
public static String getNameForParameter(MethodParameter parameter) {
ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.clreplaced);
String name = (ann != null ? ann.value() : null);
return (StringUtils.hasText(name) ? name : Conventions.getVariableNameForParameter(parameter));
}
}
19
View Source File : WebFluxConfigurationSupport.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
@Bean
public ResponseBodyResultHandler responseBodyResultHandler(ReactiveAdapterRegistry webFluxAdapterRegistry, ServerCodecConfigurer serverCodecConfigurer, RequestedContentTypeResolver webFluxContentTypeResolver) {
return new ResponseBodyResultHandler(serverCodecConfigurer.getWriters(), webFluxContentTypeResolver, webFluxAdapterRegistry);
}
19
View Source File : WebFluxConfigurationSupport.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
@Bean
public ResponseEnreplacedyResultHandler responseEnreplacedyResultHandler(ReactiveAdapterRegistry webFluxAdapterRegistry, ServerCodecConfigurer serverCodecConfigurer, RequestedContentTypeResolver webFluxContentTypeResolver) {
return new ResponseEnreplacedyResultHandler(serverCodecConfigurer.getWriters(), webFluxContentTypeResolver, webFluxAdapterRegistry);
}
19
View Source File : WebFluxConfigurationSupport.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
@Bean
public ViewResolutionResultHandler viewResolutionResultHandler(ReactiveAdapterRegistry webFluxAdapterRegistry, RequestedContentTypeResolver webFluxContentTypeResolver) {
ViewResolverRegistry registry = getViewResolverRegistry();
List<ViewResolver> resolvers = registry.getViewResolvers();
ViewResolutionResultHandler handler = new ViewResolutionResultHandler(resolvers, webFluxContentTypeResolver, webFluxAdapterRegistry);
handler.setDefaultViews(registry.getDefaultViews());
handler.setOrder(registry.getOrder());
return handler;
}
19
View Source File : ReactiveReturnValueHandler.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Support for single-value reactive types (like {@code Mono} or {@code Single})
* as a return value type.
*
* @author Sebastien Deleuze
* @since 5.1
*/
public clreplaced ReactiveReturnValueHandler extends AbstractAsyncReturnValueHandler {
private final ReactiveAdapterRegistry adapterRegistry;
public ReactiveReturnValueHandler() {
this(ReactiveAdapterRegistry.getSharedInstance());
}
public ReactiveReturnValueHandler(ReactiveAdapterRegistry adapterRegistry) {
this.adapterRegistry = adapterRegistry;
}
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return (this.adapterRegistry.getAdapter(returnType.getParameterType()) != null);
}
@Override
public boolean isAsyncReturnValue(Object returnValue, MethodParameter returnType) {
ReactiveAdapter adapter = this.adapterRegistry.getAdapter(returnType.getParameterType(), returnValue);
return (adapter != null && !adapter.isMultiValue() && !adapter.isNoValue());
}
@Override
public ListenableFuture<?> toListenableFuture(Object returnValue, MethodParameter returnType) {
ReactiveAdapter adapter = this.adapterRegistry.getAdapter(returnType.getParameterType(), returnValue);
replacedert.state(adapter != null, () -> "No ReactiveAdapter found for " + returnType.getParameterType());
return new MonoToListenableFutureAdapter<>(Mono.from(adapter.toPublisher(returnValue)));
}
}
19
View Source File : InvocableHandlerMethod.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Configure a reactive adapter registry. This is needed for async return values.
* <p>By default this is a {@link ReactiveAdapterRegistry} with default settings.
*/
public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) {
this.reactiveAdapterRegistry = registry;
}
19
View Source File : AbstractMethodMessageHandler.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Configure the registry for adapting various reactive types.
* <p>By default this is an instance of {@link ReactiveAdapterRegistry} with
* default settings.
*/
public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) {
this.invocableHelper.setReactiveAdapterRegistry(registry);
}
19
View Source File : WebFluxConfigurationSupport.java
License : Apache License 2.0
Project Creator : SourceHot
License : Apache License 2.0
Project Creator : SourceHot
@Bean
public ResponseEnreplacedyResultHandler responseEnreplacedyResultHandler(@Qualifier("webFluxAdapterRegistry") ReactiveAdapterRegistry reactiveAdapterRegistry, ServerCodecConfigurer serverCodecConfigurer, @Qualifier("webFluxContentTypeResolver") RequestedContentTypeResolver contentTypeResolver) {
return new ResponseEnreplacedyResultHandler(serverCodecConfigurer.getWriters(), contentTypeResolver, reactiveAdapterRegistry);
}
19
View Source File : WebFluxConfigurationSupport.java
License : Apache License 2.0
Project Creator : SourceHot
License : Apache License 2.0
Project Creator : SourceHot
@Bean
public ViewResolutionResultHandler viewResolutionResultHandler(@Qualifier("webFluxAdapterRegistry") ReactiveAdapterRegistry reactiveAdapterRegistry, @Qualifier("webFluxContentTypeResolver") RequestedContentTypeResolver contentTypeResolver) {
ViewResolverRegistry registry = getViewResolverRegistry();
List<ViewResolver> resolvers = registry.getViewResolvers();
ViewResolutionResultHandler handler = new ViewResolutionResultHandler(resolvers, contentTypeResolver, reactiveAdapterRegistry);
handler.setDefaultViews(registry.getDefaultViews());
handler.setOrder(registry.getOrder());
return handler;
}
19
View Source File : WebFluxConfigurationSupport.java
License : Apache License 2.0
Project Creator : SourceHot
License : Apache License 2.0
Project Creator : SourceHot
@Bean
public ResponseBodyResultHandler responseBodyResultHandler(@Qualifier("webFluxAdapterRegistry") ReactiveAdapterRegistry reactiveAdapterRegistry, ServerCodecConfigurer serverCodecConfigurer, @Qualifier("webFluxContentTypeResolver") RequestedContentTypeResolver contentTypeResolver) {
return new ResponseBodyResultHandler(serverCodecConfigurer.getWriters(), contentTypeResolver, reactiveAdapterRegistry);
}
19
View Source File : ReactiveReturnValueHandler.java
License : Apache License 2.0
Project Creator : SourceHot
License : Apache License 2.0
Project Creator : SourceHot
/**
* Support for single-value reactive types (like {@code Mono} or {@code Single})
* as a return value type.
*
* @author Sebastien Deleuze
* @since 5.1
*/
public clreplaced ReactiveReturnValueHandler extends AbstractAsyncReturnValueHandler {
private final ReactiveAdapterRegistry adapterRegistry;
public ReactiveReturnValueHandler() {
this(ReactiveAdapterRegistry.getSharedInstance());
}
public ReactiveReturnValueHandler(ReactiveAdapterRegistry adapterRegistry) {
this.adapterRegistry = adapterRegistry;
}
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return (this.adapterRegistry.getAdapter(returnType.getParameterType()) != null);
}
@Override
public boolean isAsyncReturnValue(Object returnValue, MethodParameter returnType) {
ReactiveAdapter adapter = this.adapterRegistry.getAdapter(returnType.getParameterType(), returnValue);
return (adapter != null && !adapter.isMultiValue() && !adapter.isNoValue());
}
@Override
public ListenableFuture<?> toListenableFuture(Object returnValue, MethodParameter returnType) {
ReactiveAdapter adapter = this.adapterRegistry.getAdapter(returnType.getParameterType(), returnValue);
if (adapter != null) {
return new MonoToListenableFutureAdapter<>(Mono.from(adapter.toPublisher(returnValue)));
}
return null;
}
}
19
View Source File : InvocableHandlerMethod.java
License : MIT License
Project Creator : mindcarver
License : MIT License
Project Creator : mindcarver
/**
* Configure a reactive registry. This is needed for cases where the response
* is fully handled within the controller in combination with an async void
* return value.
* <p>By default this is an instance of {@link ReactiveAdapterRegistry} with
* default settings.
* @param registry the registry to use
*/
public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) {
this.reactiveAdapterRegistry = registry;
}
19
View Source File : ReactiveReturnValueHandler.java
License : MIT License
Project Creator : mindcarver
License : MIT License
Project Creator : mindcarver
/**
* Support for single-value reactive types (like {@code Mono} or {@code Single})
* as a return value type.
*
* @author Sebastien Deleuze
* @since 5.1
*/
public clreplaced ReactiveReturnValueHandler extends AbstractAsyncReturnValueHandler {
private final ReactiveAdapterRegistry adapterRegistry;
public ReactiveReturnValueHandler() {
this(ReactiveAdapterRegistry.getSharedInstance());
}
public ReactiveReturnValueHandler(ReactiveAdapterRegistry adapterRegistry) {
this.adapterRegistry = adapterRegistry;
}
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return this.adapterRegistry.getAdapter(returnType.getParameterType()) != null;
}
@Override
public boolean isAsyncReturnValue(Object returnValue, MethodParameter returnType) {
ReactiveAdapter adapter = this.adapterRegistry.getAdapter(returnType.getParameterType(), returnValue);
return (adapter != null && !adapter.isMultiValue() && !adapter.isNoValue());
}
@Override
public ListenableFuture<?> toListenableFuture(Object returnValue, MethodParameter returnType) {
ReactiveAdapter adapter = this.adapterRegistry.getAdapter(returnType.getParameterType(), returnValue);
replacedert.state(adapter != null, () -> "No ReactiveAdapter found for " + returnType.getParameterType());
return new MonoToListenableFutureAdapter<>(Mono.from(adapter.toPublisher(returnValue)));
}
}
18
View Source File : HandlerMethodArgumentResolverSupport.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Base clreplaced for {@link HandlerMethodArgumentResolver} implementations with access to a
* {@code ReactiveAdapterRegistry} and methods to check for method parameter support.
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 5.0
*/
public abstract clreplaced HandlerMethodArgumentResolverSupport implements HandlerMethodArgumentResolver {
protected final Log logger = LogFactory.getLog(getClreplaced());
private final ReactiveAdapterRegistry adapterRegistry;
protected HandlerMethodArgumentResolverSupport(ReactiveAdapterRegistry adapterRegistry) {
replacedert.notNull(adapterRegistry, "ReactiveAdapterRegistry is required");
this.adapterRegistry = adapterRegistry;
}
/**
* Return the configured {@link ReactiveAdapterRegistry}.
*/
public ReactiveAdapterRegistry getAdapterRegistry() {
return this.adapterRegistry;
}
/**
* Evaluate the {@code Predicate} on the method parameter type or on
* the generic type within a reactive type wrapper.
*/
protected boolean checkParameterType(MethodParameter parameter, Predicate<Clreplaced<?>> predicate) {
Clreplaced<?> type = parameter.getParameterType();
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type);
if (adapter != null) {
replacedertHasValues(adapter, parameter);
type = parameter.nested().getNestedParameterType();
}
return predicate.test(type);
}
private void replacedertHasValues(ReactiveAdapter adapter, MethodParameter param) {
if (adapter.isNoValue()) {
throw new IllegalArgumentException("No value reactive types not supported: " + param.getGenericParameterType());
}
}
/**
* Evaluate the {@code Predicate} on the method parameter type but raise an
* {@code IllegalStateException} if the same matches the generic type
* within a reactive type wrapper.
*/
protected boolean checkParameterTypeNoReactiveWrapper(MethodParameter parameter, Predicate<Clreplaced<?>> predicate) {
Clreplaced<?> type = parameter.getParameterType();
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type);
if (adapter != null) {
replacedertHasValues(adapter, parameter);
type = parameter.nested().getNestedParameterType();
}
if (predicate.test(type)) {
if (adapter == null) {
return true;
}
throw buildReactiveWrapperException(parameter);
}
return false;
}
private IllegalStateException buildReactiveWrapperException(MethodParameter parameter) {
return new IllegalStateException(getClreplaced().getSimpleName() + " does not support reactive type wrapper: " + parameter.getGenericParameterType());
}
/**
* Evaluate the {@code Predicate} on the method parameter type if it has the
* given annotation, nesting within {@link java.util.Optional} if necessary,
* but raise an {@code IllegalStateException} if the same matches the generic
* type within a reactive type wrapper.
*/
protected <A extends Annotation> boolean checkAnnotatedParamNoReactiveWrapper(MethodParameter parameter, Clreplaced<A> annotationType, BiPredicate<A, Clreplaced<?>> typePredicate) {
A annotation = parameter.getParameterAnnotation(annotationType);
if (annotation == null) {
return false;
}
parameter = parameter.nestedIfOptional();
Clreplaced<?> type = parameter.getNestedParameterType();
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type);
if (adapter != null) {
replacedertHasValues(adapter, parameter);
parameter = parameter.nested();
type = parameter.getNestedParameterType();
}
if (typePredicate.test(annotation, type)) {
if (adapter == null) {
return true;
}
throw buildReactiveWrapperException(parameter);
}
return false;
}
}
18
View Source File : ControllerMethodResolver.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
private static List<HandlerMethodArgumentResolver> requestMappingResolvers(ArgumentResolverConfigurer customResolvers, ReactiveAdapterRegistry adapterRegistry, ConfigurableApplicationContext context, List<HttpMessageReader<?>> readers) {
return initResolvers(customResolvers, adapterRegistry, context, true, readers);
}
18
View Source File : WebFluxConfigurationSupport.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(ReactiveAdapterRegistry webFluxAdapterRegistry, ServerCodecConfigurer serverCodecConfigurer, FormattingConversionService webFluxConversionService, Validator webfluxValidator) {
RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
adapter.setMessageReaders(serverCodecConfigurer.getReaders());
adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(webFluxConversionService, webfluxValidator));
adapter.setReactiveAdapterRegistry(webFluxAdapterRegistry);
ArgumentResolverConfigurer configurer = new ArgumentResolverConfigurer();
configureArgumentResolvers(configurer);
adapter.setArgumentResolverConfigurer(configurer);
return adapter;
}
18
View Source File : InvocableHelper.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Configure the registry for adapting various reactive types.
* <p>By default this is an instance of {@link ReactiveAdapterRegistry} with
* default settings.
*/
public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) {
replacedert.notNull(registry, "ReactiveAdapterRegistry is required");
this.reactiveAdapterRegistry = registry;
}
18
View Source File : BodyInserters.java
License : Apache License 2.0
Project Creator : SourceHot
License : Apache License 2.0
Project Creator : SourceHot
/**
* Static factory methods for {@link BodyInserter} implementations.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @author Sebastien Deleuze
* @since 5.0
*/
public abstract clreplaced BodyInserters {
private static final ResolvableType RESOURCE_TYPE = ResolvableType.forClreplaced(Resource.clreplaced);
private static final ResolvableType SSE_TYPE = ResolvableType.forClreplaced(ServerSentEvent.clreplaced);
private static final ResolvableType FORM_DATA_TYPE = ResolvableType.forClreplacedWithGenerics(MultiValueMap.clreplaced, String.clreplaced, String.clreplaced);
private static final ResolvableType MULTIPART_DATA_TYPE = ResolvableType.forClreplacedWithGenerics(MultiValueMap.clreplaced, String.clreplaced, Object.clreplaced);
private static final BodyInserter<Void, ReactiveHttpOutputMessage> EMPTY_INSERTER = (response, context) -> response.setComplete();
private static final ReactiveAdapterRegistry registry = ReactiveAdapterRegistry.getSharedInstance();
/**
* Inserter that does not write.
* @return the inserter
*/
@SuppressWarnings("unchecked")
public static <T> BodyInserter<T, ReactiveHttpOutputMessage> empty() {
return (BodyInserter<T, ReactiveHttpOutputMessage>) EMPTY_INSERTER;
}
/**
* Inserter to write the given value.
* <p>Alternatively, consider using the {@code bodyValue(Object)} shortcuts on
* {@link org.springframework.web.reactive.function.client.WebClient WebClient} and
* {@link org.springframework.web.reactive.function.server.ServerResponse ServerResponse}.
* @param body the value to write
* @param <T> the type of the body
* @return the inserter to write a single value
* @throws IllegalArgumentException if {@code body} is a {@link Publisher} or an
* instance of a type supported by {@link ReactiveAdapterRegistry#getSharedInstance()},
* for which {@link #fromPublisher(Publisher, Clreplaced)} or
* {@link #fromProducer(Object, Clreplaced)} should be used.
* @see #fromPublisher(Publisher, Clreplaced)
* @see #fromProducer(Object, Clreplaced)
*/
public static <T> BodyInserter<T, ReactiveHttpOutputMessage> fromValue(T body) {
replacedert.notNull(body, "'body' must not be null");
replacedert.isNull(registry.getAdapter(body.getClreplaced()), "'body' should be an object, for reactive types use a variant specifying a publisher/producer and its related element type");
return (message, context) -> writeWithMessageWriters(message, context, Mono.just(body), ResolvableType.forInstance(body), null);
}
/**
* Inserter to write the given object.
* <p>Alternatively, consider using the {@code bodyValue(Object)} shortcuts on
* {@link org.springframework.web.reactive.function.client.WebClient WebClient} and
* {@link org.springframework.web.reactive.function.server.ServerResponse ServerResponse}.
* @param body the body to write to the response
* @param <T> the type of the body
* @return the inserter to write a single object
* @throws IllegalArgumentException if {@code body} is a {@link Publisher} or an
* instance of a type supported by {@link ReactiveAdapterRegistry#getSharedInstance()},
* for which {@link #fromPublisher(Publisher, Clreplaced)} or
* {@link #fromProducer(Object, Clreplaced)} should be used.
* @see #fromPublisher(Publisher, Clreplaced)
* @see #fromProducer(Object, Clreplaced)
* @deprecated As of Spring Framework 5.2, in favor of {@link #fromValue(Object)}
*/
@Deprecated
public static <T> BodyInserter<T, ReactiveHttpOutputMessage> fromObject(T body) {
return fromValue(body);
}
/**
* Inserter to write the given producer of value(s) which must be a {@link Publisher}
* or another producer adaptable to a {@code Publisher} via
* {@link ReactiveAdapterRegistry}.
* <p>Alternatively, consider using the {@code body} shortcuts on
* {@link org.springframework.web.reactive.function.client.WebClient WebClient} and
* {@link org.springframework.web.reactive.function.server.ServerResponse ServerResponse}.
* @param <T> the type of the body
* @param producer the source of body value(s).
* @param elementClreplaced the clreplaced of values to be produced
* @return the inserter to write a producer
* @since 5.2
*/
public static <T> BodyInserter<T, ReactiveHttpOutputMessage> fromProducer(T producer, Clreplaced<?> elementClreplaced) {
replacedert.notNull(producer, "'producer' must not be null");
replacedert.notNull(elementClreplaced, "'elementClreplaced' must not be null");
ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(producer.getClreplaced());
replacedert.notNull(adapter, "'producer' type is unknown to ReactiveAdapterRegistry");
return (message, context) -> writeWithMessageWriters(message, context, producer, ResolvableType.forClreplaced(elementClreplaced), adapter);
}
/**
* Inserter to write the given producer of value(s) which must be a {@link Publisher}
* or another producer adaptable to a {@code Publisher} via
* {@link ReactiveAdapterRegistry}.
* <p>Alternatively, consider using the {@code body} shortcuts on
* {@link org.springframework.web.reactive.function.client.WebClient WebClient} and
* {@link org.springframework.web.reactive.function.server.ServerResponse ServerResponse}.
* @param <T> the type of the body
* @param producer the source of body value(s).
* @param elementTypeRef the type of values to be produced
* @return the inserter to write a producer
* @since 5.2
*/
public static <T> BodyInserter<T, ReactiveHttpOutputMessage> fromProducer(T producer, ParameterizedTypeReference<?> elementTypeRef) {
replacedert.notNull(producer, "'producer' must not be null");
replacedert.notNull(elementTypeRef, "'elementTypeRef' must not be null");
ReactiveAdapter adapter = ReactiveAdapterRegistry.getSharedInstance().getAdapter(producer.getClreplaced());
replacedert.notNull(adapter, "'producer' type is unknown to ReactiveAdapterRegistry");
return (message, context) -> writeWithMessageWriters(message, context, producer, ResolvableType.forType(elementTypeRef), adapter);
}
/**
* Inserter to write the given {@link Publisher}.
* <p>Alternatively, consider using the {@code body} shortcuts on
* {@link org.springframework.web.reactive.function.client.WebClient WebClient} and
* {@link org.springframework.web.reactive.function.server.ServerResponse ServerResponse}.
* @param publisher the publisher to write with
* @param elementClreplaced the clreplaced of elements in the publisher
* @param <T> the type of the elements contained in the publisher
* @param <P> the {@code Publisher} type
* @return the inserter to write a {@code Publisher}
*/
public static <T, P extends Publisher<T>> BodyInserter<P, ReactiveHttpOutputMessage> fromPublisher(P publisher, Clreplaced<T> elementClreplaced) {
replacedert.notNull(publisher, "'publisher' must not be null");
replacedert.notNull(elementClreplaced, "'elementClreplaced' must not be null");
return (message, context) -> writeWithMessageWriters(message, context, publisher, ResolvableType.forClreplaced(elementClreplaced), null);
}
/**
* Inserter to write the given {@link Publisher}.
* <p>Alternatively, consider using the {@code body} shortcuts on
* {@link org.springframework.web.reactive.function.client.WebClient WebClient} and
* {@link org.springframework.web.reactive.function.server.ServerResponse ServerResponse}.
* @param publisher the publisher to write with
* @param elementTypeRef the type of elements contained in the publisher
* @param <T> the type of the elements contained in the publisher
* @param <P> the {@code Publisher} type
* @return the inserter to write a {@code Publisher}
*/
public static <T, P extends Publisher<T>> BodyInserter<P, ReactiveHttpOutputMessage> fromPublisher(P publisher, ParameterizedTypeReference<T> elementTypeRef) {
replacedert.notNull(publisher, "'publisher' must not be null");
replacedert.notNull(elementTypeRef, "'elementTypeRef' must not be null");
return (message, context) -> writeWithMessageWriters(message, context, publisher, ResolvableType.forType(elementTypeRef.getType()), null);
}
/**
* Inserter to write the given {@code Resource}.
* <p>If the resource can be resolved to a {@linkplain Resource#getFile() file}, it will
* be copied using <a href="https://en.wikipedia.org/wiki/Zero-copy">zero-copy</a>.
* @param resource the resource to write to the output message
* @param <T> the type of the {@code Resource}
* @return the inserter to write a {@code Publisher}
*/
public static <T extends Resource> BodyInserter<T, ReactiveHttpOutputMessage> fromResource(T resource) {
replacedert.notNull(resource, "'resource' must not be null");
return (outputMessage, context) -> {
ResolvableType elementType = RESOURCE_TYPE;
HttpMessageWriter<Resource> writer = findWriter(context, elementType, null);
return write(Mono.just(resource), elementType, null, outputMessage, context, writer);
};
}
/**
* Inserter to write the given {@code ServerSentEvent} publisher.
* <p>Alternatively, you can provide event data objects via
* {@link #fromPublisher(Publisher, Clreplaced)} or {@link #fromProducer(Object, Clreplaced)},
* and set the "Content-Type" to {@link MediaType#TEXT_EVENT_STREAM text/event-stream}.
* @param eventsPublisher the {@code ServerSentEvent} publisher to write to the response body
* @param <T> the type of the data elements in the {@link ServerSentEvent}
* @return the inserter to write a {@code ServerSentEvent} publisher
* @see <a href="https://www.w3.org/TR/eventsource/">Server-Sent Events W3C recommendation</a>
*/
// Parameterized for server-side use
public static <T, S extends Publisher<ServerSentEvent<T>>> BodyInserter<S, ServerHttpResponse> fromServerSentEvents(S eventsPublisher) {
replacedert.notNull(eventsPublisher, "'eventsPublisher' must not be null");
return (serverResponse, context) -> {
ResolvableType elementType = SSE_TYPE;
MediaType mediaType = MediaType.TEXT_EVENT_STREAM;
HttpMessageWriter<ServerSentEvent<T>> writer = findWriter(context, elementType, mediaType);
return write(eventsPublisher, elementType, mediaType, serverResponse, context, writer);
};
}
/**
* Return a {@link FormInserter} to write the given {@code MultiValueMap}
* as URL-encoded form data. The returned inserter allows for additional
* entries to be added via {@link FormInserter#with(String, Object)}.
* <p>Note that you can also use the {@code bodyValue(Object)} method in the
* request builders of both the {@code WebClient} and {@code WebTestClient}.
* In that case the setting of the request content type is also not required,
* just be sure the map contains String values only or otherwise it would be
* interpreted as a multipart request.
* @param formData the form data to write to the output message
* @return the inserter that allows adding more form data
*/
public static FormInserter<String> fromFormData(MultiValueMap<String, String> formData) {
return new DefaultFormInserter().with(formData);
}
/**
* Return a {@link FormInserter} to write the given key-value pair as
* URL-encoded form data. The returned inserter allows for additional
* entries to be added via {@link FormInserter#with(String, Object)}.
* @param name the key to add to the form
* @param value the value to add to the form
* @return the inserter that allows adding more form data
*/
public static FormInserter<String> fromFormData(String name, String value) {
replacedert.notNull(name, "'name' must not be null");
replacedert.notNull(value, "'value' must not be null");
return new DefaultFormInserter().with(name, value);
}
/**
* Return a {@link MultipartInserter} to write the given
* {@code MultiValueMap} as multipart data. Values in the map can be an
* Object or an {@link HttpEnreplacedy}.
* <p>Note that you can also build the multipart data externally with
* {@link MultipartBodyBuilder}, and preplaced the resulting map directly to the
* {@code bodyValue(Object)} shortcut method in {@code WebClient}.
* @param multipartData the form data to write to the output message
* @return the inserter that allows adding more parts
* @see MultipartBodyBuilder
*/
public static MultipartInserter fromMultipartData(MultiValueMap<String, ?> multipartData) {
replacedert.notNull(multipartData, "'multipartData' must not be null");
return new DefaultMultipartInserter().withInternal(multipartData);
}
/**
* Return a {@link MultipartInserter} to write the given parts,
* as multipart data. Values in the map can be an Object or an
* {@link HttpEnreplacedy}.
* <p>Note that you can also build the multipart data externally with
* {@link MultipartBodyBuilder}, and preplaced the resulting map directly to the
* {@code bodyValue(Object)} shortcut method in {@code WebClient}.
* @param name the part name
* @param value the part value, an Object or {@code HttpEnreplacedy}
* @return the inserter that allows adding more parts
*/
public static MultipartInserter fromMultipartData(String name, Object value) {
replacedert.notNull(name, "'name' must not be null");
replacedert.notNull(value, "'value' must not be null");
return new DefaultMultipartInserter().with(name, value);
}
/**
* Return a {@link MultipartInserter} to write the given asynchronous parts,
* as multipart data.
* <p>Note that you can also build the multipart data externally with
* {@link MultipartBodyBuilder}, and preplaced the resulting map directly to the
* {@code bodyValue(Object)} shortcut method in {@code WebClient}.
* @param name the part name
* @param publisher the publisher that forms the part value
* @param elementClreplaced the clreplaced contained in the {@code publisher}
* @return the inserter that allows adding more parts
*/
public static <T, P extends Publisher<T>> MultipartInserter fromMultipartAsyncData(String name, P publisher, Clreplaced<T> elementClreplaced) {
return new DefaultMultipartInserter().withPublisher(name, publisher, elementClreplaced);
}
/**
* Variant of {@link #fromMultipartAsyncData(String, Publisher, Clreplaced)} that
* accepts a {@link ParameterizedTypeReference} for the element type, which
* allows specifying generic type information.
* <p>Note that you can also build the multipart data externally with
* {@link MultipartBodyBuilder}, and preplaced the resulting map directly to the
* {@code bodyValue(Object)} shortcut method in {@code WebClient}.
* @param name the part name
* @param publisher the publisher that forms the part value
* @param typeReference the type contained in the {@code publisher}
* @return the inserter that allows adding more parts
*/
public static <T, P extends Publisher<T>> MultipartInserter fromMultipartAsyncData(String name, P publisher, ParameterizedTypeReference<T> typeReference) {
return new DefaultMultipartInserter().withPublisher(name, publisher, typeReference);
}
/**
* Inserter to write the given {@code Publisher<DataBuffer>} to the body.
* @param publisher the data buffer publisher to write
* @param <T> the type of the publisher
* @return the inserter to write directly to the body
* @see ReactiveHttpOutputMessage#writeWith(Publisher)
*/
public static <T extends Publisher<DataBuffer>> BodyInserter<T, ReactiveHttpOutputMessage> fromDataBuffers(T publisher) {
replacedert.notNull(publisher, "'publisher' must not be null");
return (outputMessage, context) -> outputMessage.writeWith(publisher);
}
private static <M extends ReactiveHttpOutputMessage> Mono<Void> writeWithMessageWriters(M outputMessage, BodyInserter.Context context, Object body, ResolvableType bodyType, @Nullable ReactiveAdapter adapter) {
Publisher<?> publisher;
if (body instanceof Publisher) {
publisher = (Publisher<?>) body;
} else if (adapter != null) {
publisher = adapter.toPublisher(body);
} else {
publisher = Mono.just(body);
}
MediaType mediaType = outputMessage.getHeaders().getContentType();
return context.messageWriters().stream().filter(messageWriter -> messageWriter.canWrite(bodyType, mediaType)).findFirst().map(BodyInserters::cast).map(writer -> write(publisher, bodyType, mediaType, outputMessage, context, writer)).orElseGet(() -> Mono.error(unsupportedError(bodyType, context, mediaType)));
}
private static UnsupportedMediaTypeException unsupportedError(ResolvableType bodyType, BodyInserter.Context context, @Nullable MediaType mediaType) {
List<MediaType> supportedMediaTypes = context.messageWriters().stream().flatMap(reader -> reader.getWritableMediaTypes().stream()).collect(Collectors.toList());
return new UnsupportedMediaTypeException(mediaType, supportedMediaTypes, bodyType);
}
private static <T> Mono<Void> write(Publisher<? extends T> input, ResolvableType type, @Nullable MediaType mediaType, ReactiveHttpOutputMessage message, BodyInserter.Context context, HttpMessageWriter<T> writer) {
return context.serverRequest().map(request -> {
ServerHttpResponse response = (ServerHttpResponse) message;
return writer.write(input, type, type, mediaType, request, response, context.hints());
}).orElseGet(() -> writer.write(input, type, mediaType, message, context.hints()));
}
private static <T> HttpMessageWriter<T> findWriter(BodyInserter.Context context, ResolvableType elementType, @Nullable MediaType mediaType) {
return context.messageWriters().stream().filter(messageWriter -> messageWriter.canWrite(elementType, mediaType)).findFirst().map(BodyInserters::<T>cast).orElseThrow(() -> new IllegalStateException("No HttpMessageWriter for \"" + mediaType + "\" and \"" + elementType + "\""));
}
@SuppressWarnings("unchecked")
private static <T> HttpMessageWriter<T> cast(HttpMessageWriter<?> messageWriter) {
return (HttpMessageWriter<T>) messageWriter;
}
/**
* Extension of {@link BodyInserter} that allows for adding form data or
* multipart form data.
*
* @param <T> the value type
*/
public interface FormInserter<T> extends BodyInserter<MultiValueMap<String, T>, ClientHttpRequest> {
// FormInserter is parameterized to ClientHttpRequest (for client-side use only)
/**
* Adds the specified key-value pair to the form.
* @param key the key to be added
* @param value the value to be added
* @return this inserter for adding more parts
*/
FormInserter<T> with(String key, T value);
/**
* Adds the specified values to the form.
* @param values the values to be added
* @return this inserter for adding more parts
*/
FormInserter<T> with(MultiValueMap<String, T> values);
}
/**
* Extension of {@link FormInserter} that allows for adding asynchronous parts.
*/
public interface MultipartInserter extends FormInserter<Object> {
/**
* Add an asynchronous part with {@link Publisher}-based content.
* @param name the name of the part to add
* @param publisher the part contents
* @param elementClreplaced the type of elements contained in the publisher
* @return this inserter for adding more parts
*/
<T, P extends Publisher<T>> MultipartInserter withPublisher(String name, P publisher, Clreplaced<T> elementClreplaced);
/**
* Variant of {@link #withPublisher(String, Publisher, Clreplaced)} that accepts a
* {@link ParameterizedTypeReference} for the element type, which allows
* specifying generic type information.
* @param name the key to be added
* @param publisher the publisher to be added as value
* @param typeReference the type of elements contained in {@code publisher}
* @return this inserter for adding more parts
*/
<T, P extends Publisher<T>> MultipartInserter withPublisher(String name, P publisher, ParameterizedTypeReference<T> typeReference);
}
private static clreplaced DefaultFormInserter implements FormInserter<String> {
private final MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
@Override
public FormInserter<String> with(String key, @Nullable String value) {
this.data.add(key, value);
return this;
}
@Override
public FormInserter<String> with(MultiValueMap<String, String> values) {
this.data.addAll(values);
return this;
}
@Override
public Mono<Void> insert(ClientHttpRequest outputMessage, Context context) {
HttpMessageWriter<MultiValueMap<String, String>> messageWriter = findWriter(context, FORM_DATA_TYPE, MediaType.APPLICATION_FORM_URLENCODED);
return messageWriter.write(Mono.just(this.data), FORM_DATA_TYPE, MediaType.APPLICATION_FORM_URLENCODED, outputMessage, context.hints());
}
}
private static clreplaced DefaultMultipartInserter implements MultipartInserter {
private final MultipartBodyBuilder builder = new MultipartBodyBuilder();
@Override
public MultipartInserter with(String key, Object value) {
this.builder.part(key, value);
return this;
}
@Override
public MultipartInserter with(MultiValueMap<String, Object> values) {
return withInternal(values);
}
@SuppressWarnings("unchecked")
private MultipartInserter withInternal(MultiValueMap<String, ?> values) {
values.forEach((key, valueList) -> {
for (Object value : valueList) {
this.builder.part(key, value);
}
});
return this;
}
@Override
public <T, P extends Publisher<T>> MultipartInserter withPublisher(String name, P publisher, Clreplaced<T> elementClreplaced) {
this.builder.asyncPart(name, publisher, elementClreplaced);
return this;
}
@Override
public <T, P extends Publisher<T>> MultipartInserter withPublisher(String name, P publisher, ParameterizedTypeReference<T> typeReference) {
this.builder.asyncPart(name, publisher, typeReference);
return this;
}
@Override
public Mono<Void> insert(ClientHttpRequest outputMessage, Context context) {
HttpMessageWriter<MultiValueMap<String, HttpEnreplacedy<?>>> messageWriter = findWriter(context, MULTIPART_DATA_TYPE, MediaType.MULTIPART_FORM_DATA);
MultiValueMap<String, HttpEnreplacedy<?>> body = this.builder.build();
return messageWriter.write(Mono.just(body), MULTIPART_DATA_TYPE, MediaType.MULTIPART_FORM_DATA, outputMessage, context.hints());
}
}
}
18
View Source File : WebFluxConfigurationSupport.java
License : Apache License 2.0
Project Creator : SourceHot
License : Apache License 2.0
Project Creator : SourceHot
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(@Qualifier("webFluxAdapterRegistry") ReactiveAdapterRegistry reactiveAdapterRegistry, ServerCodecConfigurer serverCodecConfigurer, @Qualifier("webFluxConversionService") FormattingConversionService conversionService, @Qualifier("webFluxValidator") Validator validator) {
RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter();
adapter.setMessageReaders(serverCodecConfigurer.getReaders());
adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer(conversionService, validator));
adapter.setReactiveAdapterRegistry(reactiveAdapterRegistry);
ArgumentResolverConfigurer configurer = new ArgumentResolverConfigurer();
configureArgumentResolvers(configurer);
adapter.setArgumentResolverConfigurer(configurer);
return adapter;
}
18
View Source File : RSocketMessageHandler.java
License : Apache License 2.0
Project Creator : SourceHot
License : Apache License 2.0
Project Creator : SourceHot
/**
* Configure the registry for adapting various reactive types.
* <p>When {@link #setRSocketStrategies(RSocketStrategies) rsocketStrategies}
* is set, this property is re-initialized with the registry in it, and
* likewise when this property is set the {@code RSocketStrategies} are
* mutated to change the registry in it.
* <p>By default this is set to the
* {@link org.springframework.messaging.rsocket.RSocketStrategies.Builder#reactiveAdapterStrategy(ReactiveAdapterRegistry) defaults}
* from {@code RSocketStrategies}.
*/
@Override
public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) {
super.setReactiveAdapterRegistry(registry);
this.strategies = this.strategies.mutate().reactiveAdapterStrategy(registry).build();
}
18
View Source File : HandlerMethodArgumentResolverSupport.java
License : MIT License
Project Creator : mindcarver
License : MIT License
Project Creator : mindcarver
/**
* Base clreplaced for {@link HandlerMethodArgumentResolver} implementations with access to a
* {@code ReactiveAdapterRegistry} and methods to check for method parameter support.
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 5.0
*/
public abstract clreplaced HandlerMethodArgumentResolverSupport implements HandlerMethodArgumentResolver {
protected final Log logger = LogFactory.getLog(getClreplaced());
private final ReactiveAdapterRegistry adapterRegistry;
protected HandlerMethodArgumentResolverSupport(ReactiveAdapterRegistry adapterRegistry) {
replacedert.notNull(adapterRegistry, "ReactiveAdapterRegistry is required");
this.adapterRegistry = adapterRegistry;
}
/**
* Return the configured {@link ReactiveAdapterRegistry}.
*/
public ReactiveAdapterRegistry getAdapterRegistry() {
return this.adapterRegistry;
}
/**
* Evaluate the {@code Predicate} on the method parameter type or on
* the generic type within a reactive type wrapper.
*/
protected boolean checkParameterType(MethodParameter parameter, Predicate<Clreplaced<?>> predicate) {
Clreplaced<?> type = parameter.getParameterType();
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type);
if (adapter != null) {
replacedertHasValues(adapter, parameter);
type = parameter.nested().getNestedParameterType();
}
return predicate.test(type);
}
private void replacedertHasValues(ReactiveAdapter adapter, MethodParameter param) {
if (adapter.isNoValue()) {
throw new IllegalArgumentException("No value reactive types not supported: " + param.getGenericParameterType());
}
}
/**
* Evaluate the {@code Predicate} on the method parameter type but raise an
* {@code IllegalStateException} if the same matches the generic type
* within a reactive type wrapper.
*/
protected boolean checkParameterTypeNoReactiveWrapper(MethodParameter parameter, Predicate<Clreplaced<?>> predicate) {
Clreplaced<?> type = parameter.getParameterType();
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type);
if (adapter != null) {
replacedertHasValues(adapter, parameter);
type = parameter.nested().getNestedParameterType();
}
if (predicate.test(type)) {
if (adapter == null) {
return true;
}
throw buildReactiveWrapperException(parameter);
}
return false;
}
private IllegalStateException buildReactiveWrapperException(MethodParameter parameter) {
return new IllegalStateException(getClreplaced().getSimpleName() + " doesn't support reactive type wrapper: " + parameter.getGenericParameterType());
}
/**
* Evaluate the {@code Predicate} on the method parameter type if it has the
* given annotation, nesting within {@link java.util.Optional} if necessary,
* but raise an {@code IllegalStateException} if the same matches the generic
* type within a reactive type wrapper.
*/
protected <A extends Annotation> boolean checkAnnotatedParamNoReactiveWrapper(MethodParameter parameter, Clreplaced<A> annotationType, BiPredicate<A, Clreplaced<?>> typePredicate) {
A annotation = parameter.getParameterAnnotation(annotationType);
if (annotation == null) {
return false;
}
parameter = parameter.nestedIfOptional();
Clreplaced<?> type = parameter.getNestedParameterType();
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type);
if (adapter != null) {
replacedertHasValues(adapter, parameter);
parameter = parameter.nested();
type = parameter.getNestedParameterType();
}
if (typePredicate.test(annotation, type)) {
if (adapter == null) {
return true;
}
throw buildReactiveWrapperException(parameter);
}
return false;
}
}
18
View Source File : ControllerMethodResolver.java
License : MIT License
Project Creator : mindcarver
License : MIT License
Project Creator : mindcarver
private static List<HandlerMethodArgumentResolver> requestMappingResolvers(ArgumentResolverConfigurer customResolvers, ReactiveAdapterRegistry reactiveRegistry, ConfigurableApplicationContext context, List<HttpMessageReader<?>> readers) {
return initResolvers(customResolvers, reactiveRegistry, context, true, readers);
}
17
View Source File : ModelInitializerTests.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
@Before
public void setup() {
ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
ArgumentResolverConfigurer resolverConfigurer = new ArgumentResolverConfigurer();
resolverConfigurer.addCustomResolver(new ModelMethodArgumentResolver(adapterRegistry));
ControllerMethodResolver methodResolver = new ControllerMethodResolver(resolverConfigurer, adapterRegistry, new StaticApplicationContext(), Collections.emptyList());
this.modelInitializer = new ModelInitializer(methodResolver, adapterRegistry);
}
17
View Source File : InvocableHandlerMethod.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Extension of {@link HandlerMethod} that invokes the underlying method with
* argument values resolved from the current HTTP request through a list of
* {@link HandlerMethodArgumentResolver}.
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller
* @author Sebastien Deleuze
* @since 5.0
*/
public clreplaced InvocableHandlerMethod extends HandlerMethod {
private static final Mono<Object[]> EMPTY_ARGS = Mono.just(new Object[0]);
private static final Object NO_ARG_VALUE = new Object();
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
/**
* Create an instance from a {@code HandlerMethod}.
*/
public InvocableHandlerMethod(HandlerMethod handlerMethod) {
super(handlerMethod);
}
/**
* Create an instance from a bean instance and a method.
*/
public InvocableHandlerMethod(Object bean, Method method) {
super(bean, method);
}
/**
* Configure the argument resolvers to use to use for resolving method
* argument values against a {@code ServerWebExchange}.
*/
public void setArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
this.resolvers.addResolvers(resolvers);
}
/**
* Return the configured argument resolvers.
*/
public List<HandlerMethodArgumentResolver> getResolvers() {
return this.resolvers.getResolvers();
}
/**
* Set the ParameterNameDiscoverer for resolving parameter names when needed
* (e.g. default request attribute name).
* <p>Default is a {@link DefaultParameterNameDiscoverer}.
*/
public void setParameterNameDiscoverer(ParameterNameDiscoverer nameDiscoverer) {
this.parameterNameDiscoverer = nameDiscoverer;
}
/**
* Return the configured parameter name discoverer.
*/
public ParameterNameDiscoverer getParameterNameDiscoverer() {
return this.parameterNameDiscoverer;
}
/**
* Configure a reactive adapter registry. This is needed for cases where the response is
* fully handled within the controller in combination with an async void return value.
* <p>By default this is a {@link ReactiveAdapterRegistry} with default settings.
*/
public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) {
this.reactiveAdapterRegistry = registry;
}
/**
* Invoke the method for the given exchange.
* @param exchange the current exchange
* @param bindingContext the binding context to use
* @param providedArgs optional list of argument values to match by type
* @return a Mono with a {@link HandlerResult}
*/
@SuppressWarnings("KotlinInternalInJava")
public Mono<HandlerResult> invoke(ServerWebExchange exchange, BindingContext bindingContext, Object... providedArgs) {
return getMethodArgumentValues(exchange, bindingContext, providedArgs).flatMap(args -> {
Object value;
try {
ReflectionUtils.makeAccessible(getBridgedMethod());
Method method = getBridgedMethod();
if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(method.getDeclaringClreplaced())) {
value = CoroutinesUtils.invokeHandlerMethod(method, getBean(), args);
} else {
value = method.invoke(getBean(), args);
}
} catch (IllegalArgumentException ex) {
replacedertTargetBean(getBridgedMethod(), getBean(), args);
String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
return Mono.error(new IllegalStateException(formatInvokeError(text, args), ex));
} catch (InvocationTargetException ex) {
return Mono.error(ex.getTargetException());
} catch (Throwable ex) {
// Unlikely to ever get here, but it must be handled...
return Mono.error(new IllegalStateException(formatInvokeError("Invocation failure", args), ex));
}
HttpStatus status = getResponseStatus();
if (status != null) {
exchange.getResponse().setStatusCode(status);
}
MethodParameter returnType = getReturnType();
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(returnType.getParameterType());
boolean asyncVoid = isAsyncVoidReturnType(returnType, adapter);
if ((value == null || asyncVoid) && isResponseHandled(args, exchange)) {
return (asyncVoid ? Mono.from(adapter.toPublisher(value)) : Mono.empty());
}
HandlerResult result = new HandlerResult(this, value, returnType, bindingContext);
return Mono.just(result);
});
}
private Mono<Object[]> getMethodArgumentValues(ServerWebExchange exchange, BindingContext bindingContext, Object... providedArgs) {
MethodParameter[] parameters = getMethodParameters();
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
}
List<Mono<Object>> argMonos = new ArrayList<>(parameters.length);
for (MethodParameter parameter : parameters) {
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
Object providedArg = findProvidedArgument(parameter, providedArgs);
if (providedArg != null) {
argMonos.add(Mono.just(providedArg));
continue;
}
if (!this.resolvers.supportsParameter(parameter)) {
return Mono.error(new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")));
}
try {
argMonos.add(this.resolvers.resolveArgument(parameter, bindingContext, exchange).defaultIfEmpty(NO_ARG_VALUE).doOnError(ex -> logArgumentErrorIfNecessary(exchange, parameter, ex)));
} catch (Exception ex) {
logArgumentErrorIfNecessary(exchange, parameter, ex);
argMonos.add(Mono.error(ex));
}
}
return Mono.zip(argMonos, values -> Stream.of(values).map(value -> value != NO_ARG_VALUE ? value : null).toArray());
}
private void logArgumentErrorIfNecessary(ServerWebExchange exchange, MethodParameter parameter, Throwable ex) {
// Leave stack trace for later, if error is not handled...
String exMsg = ex.getMessage();
if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
if (logger.isDebugEnabled()) {
logger.debug(exchange.getLogPrefix() + formatArgumentError(parameter, exMsg));
}
}
}
private static boolean isAsyncVoidReturnType(MethodParameter returnType, @Nullable ReactiveAdapter adapter) {
if (adapter != null && adapter.supportsEmpty()) {
if (adapter.isNoValue()) {
return true;
}
Type parameterType = returnType.getGenericParameterType();
if (parameterType instanceof ParameterizedType) {
ParameterizedType type = (ParameterizedType) parameterType;
if (type.getActualTypeArguments().length == 1) {
return Void.clreplaced.equals(type.getActualTypeArguments()[0]);
}
}
}
return false;
}
private boolean isResponseHandled(Object[] args, ServerWebExchange exchange) {
if (getResponseStatus() != null || exchange.isNotModified()) {
return true;
}
for (Object arg : args) {
if (arg instanceof ServerHttpResponse || arg instanceof ServerWebExchange) {
return true;
}
}
return false;
}
}
17
View Source File : ControllerMethodResolver.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
private static List<HandlerMethodArgumentResolver> modelMethodResolvers(ArgumentResolverConfigurer customResolvers, ReactiveAdapterRegistry adapterRegistry, ConfigurableApplicationContext context) {
return initResolvers(customResolvers, adapterRegistry, context, true, Collections.emptyList());
}
17
View Source File : ControllerMethodResolver.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
private List<SyncHandlerMethodArgumentResolver> initBinderResolvers(ArgumentResolverConfigurer customResolvers, ReactiveAdapterRegistry adapterRegistry, ConfigurableApplicationContext context) {
return initResolvers(customResolvers, adapterRegistry, context, false, Collections.emptyList()).stream().filter(resolver -> resolver instanceof SyncHandlerMethodArgumentResolver).map(resolver -> (SyncHandlerMethodArgumentResolver) resolver).collect(Collectors.toList());
}
17
View Source File : ControllerMethodResolver.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
private static List<HandlerMethodArgumentResolver> exceptionHandlerResolvers(ArgumentResolverConfigurer customResolvers, ReactiveAdapterRegistry adapterRegistry, ConfigurableApplicationContext context) {
return initResolvers(customResolvers, adapterRegistry, context, false, Collections.emptyList());
}
17
View Source File : DefaultRSocketStrategies.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Default, package-private {@link RSocketStrategies} implementation.
*
* @author Rossen Stoyanchev
* @since 5.2
*/
final clreplaced DefaultRSocketStrategies implements RSocketStrategies {
private final List<Encoder<?>> encoders;
private final List<Decoder<?>> decoders;
private final ReactiveAdapterRegistry adapterRegistry;
private final DataBufferFactory bufferFactory;
private DefaultRSocketStrategies(List<Encoder<?>> encoders, List<Decoder<?>> decoders, ReactiveAdapterRegistry adapterRegistry, DataBufferFactory bufferFactory) {
this.encoders = Collections.unmodifiableList(encoders);
this.decoders = Collections.unmodifiableList(decoders);
this.adapterRegistry = adapterRegistry;
this.bufferFactory = bufferFactory;
}
@Override
public List<Encoder<?>> encoders() {
return this.encoders;
}
@Override
public List<Decoder<?>> decoders() {
return this.decoders;
}
@Override
public ReactiveAdapterRegistry reactiveAdapterRegistry() {
return this.adapterRegistry;
}
@Override
public DataBufferFactory dataBufferFactory() {
return this.bufferFactory;
}
/**
* Default RSocketStrategies.Builder implementation.
*/
static clreplaced DefaultRSocketStrategiesBuilder implements RSocketStrategies.Builder {
private final List<Encoder<?>> encoders = new ArrayList<>();
private final List<Decoder<?>> decoders = new ArrayList<>();
private ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
@Nullable
private DataBufferFactory dataBufferFactory;
public DefaultRSocketStrategiesBuilder() {
}
public DefaultRSocketStrategiesBuilder(RSocketStrategies other) {
this.encoders.addAll(other.encoders());
this.decoders.addAll(other.decoders());
this.adapterRegistry = other.reactiveAdapterRegistry();
this.dataBufferFactory = other.dataBufferFactory();
}
@Override
public Builder encoder(Encoder<?>... encoders) {
this.encoders.addAll(Arrays.asList(encoders));
return this;
}
@Override
public Builder decoder(Decoder<?>... decoder) {
this.decoders.addAll(Arrays.asList(decoder));
return this;
}
@Override
public Builder encoders(Consumer<List<Encoder<?>>> consumer) {
consumer.accept(this.encoders);
return this;
}
@Override
public Builder decoders(Consumer<List<Decoder<?>>> consumer) {
consumer.accept(this.decoders);
return this;
}
@Override
public Builder reactiveAdapterStrategy(ReactiveAdapterRegistry registry) {
replacedert.notNull(registry, "ReactiveAdapterRegistry is required");
this.adapterRegistry = registry;
return this;
}
@Override
public Builder dataBufferFactory(DataBufferFactory bufferFactory) {
this.dataBufferFactory = bufferFactory;
return this;
}
@Override
public RSocketStrategies build() {
return new DefaultRSocketStrategies(this.encoders, this.decoders, this.adapterRegistry, this.dataBufferFactory != null ? this.dataBufferFactory : new DefaultDataBufferFactory());
}
}
}
17
View Source File : InvocableHandlerMethod.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Extension of {@link HandlerMethod} that invokes the underlying method with
* argument values resolved from the current HTTP request through a list of
* {@link HandlerMethodArgumentResolver}.
*
* @author Rossen Stoyanchev
* @since 5.2
*/
public clreplaced InvocableHandlerMethod extends HandlerMethod {
private static final Mono<Object[]> EMPTY_ARGS = Mono.just(new Object[0]);
private static final Object NO_ARG_VALUE = new Object();
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
/**
* Create an instance from a {@code HandlerMethod}.
*/
public InvocableHandlerMethod(HandlerMethod handlerMethod) {
super(handlerMethod);
}
/**
* Create an instance from a bean instance and a method.
*/
public InvocableHandlerMethod(Object bean, Method method) {
super(bean, method);
}
/**
* Configure the argument resolvers to use to use for resolving method
* argument values against a {@code ServerWebExchange}.
*/
public void setArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
this.resolvers.addResolvers(resolvers);
}
/**
* Return the configured argument resolvers.
*/
public List<HandlerMethodArgumentResolver> getResolvers() {
return this.resolvers.getResolvers();
}
/**
* Set the ParameterNameDiscoverer for resolving parameter names when needed
* (e.g. default request attribute name).
* <p>Default is a {@link DefaultParameterNameDiscoverer}.
*/
public void setParameterNameDiscoverer(ParameterNameDiscoverer nameDiscoverer) {
this.parameterNameDiscoverer = nameDiscoverer;
}
/**
* Return the configured parameter name discoverer.
*/
public ParameterNameDiscoverer getParameterNameDiscoverer() {
return this.parameterNameDiscoverer;
}
/**
* Configure a reactive adapter registry. This is needed for async return values.
* <p>By default this is a {@link ReactiveAdapterRegistry} with default settings.
*/
public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) {
this.reactiveAdapterRegistry = registry;
}
/**
* Invoke the method for the given exchange.
* @param message the current message
* @param providedArgs optional list of argument values to match by type
* @return a Mono with the result from the invocation
*/
@SuppressWarnings("KotlinInternalInJava")
public Mono<Object> invoke(Message<?> message, Object... providedArgs) {
return getMethodArgumentValues(message, providedArgs).flatMap(args -> {
Object value;
try {
Method method = getBridgedMethod();
ReflectionUtils.makeAccessible(method);
if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(method.getDeclaringClreplaced())) {
value = CoroutinesUtils.invokeHandlerMethod(method, getBean(), args);
} else {
value = method.invoke(getBean(), args);
}
} catch (IllegalArgumentException ex) {
replacedertTargetBean(getBridgedMethod(), getBean(), args);
String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
return Mono.error(new IllegalStateException(formatInvokeError(text, args), ex));
} catch (InvocationTargetException ex) {
return Mono.error(ex.getTargetException());
} catch (Throwable ex) {
// Unlikely to ever get here, but it must be handled...
return Mono.error(new IllegalStateException(formatInvokeError("Invocation failure", args), ex));
}
MethodParameter returnType = getReturnType();
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(returnType.getParameterType());
return (isAsyncVoidReturnType(returnType, adapter) ? Mono.from(adapter.toPublisher(value)) : Mono.justOrEmpty(value));
});
}
private Mono<Object[]> getMethodArgumentValues(Message<?> message, Object... providedArgs) {
MethodParameter[] parameters = getMethodParameters();
if (ObjectUtils.isEmpty(getMethodParameters())) {
return EMPTY_ARGS;
}
List<Mono<Object>> argMonos = new ArrayList<>(parameters.length);
for (MethodParameter parameter : parameters) {
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
Object providedArg = findProvidedArgument(parameter, providedArgs);
if (providedArg != null) {
argMonos.add(Mono.just(providedArg));
continue;
}
if (!this.resolvers.supportsParameter(parameter)) {
return Mono.error(new MethodArgumentResolutionException(message, parameter, formatArgumentError(parameter, "No suitable resolver")));
}
try {
argMonos.add(this.resolvers.resolveArgument(parameter, message).defaultIfEmpty(NO_ARG_VALUE).doOnError(ex -> logArgumentErrorIfNecessary(parameter, ex)));
} catch (Exception ex) {
logArgumentErrorIfNecessary(parameter, ex);
argMonos.add(Mono.error(ex));
}
}
return Mono.zip(argMonos, values -> Stream.of(values).map(value -> value != NO_ARG_VALUE ? value : null).toArray());
}
private void logArgumentErrorIfNecessary(MethodParameter parameter, Throwable ex) {
// Leave stack trace for later, if error is not handled...
String exMsg = ex.getMessage();
if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
if (logger.isDebugEnabled()) {
logger.debug(formatArgumentError(parameter, exMsg));
}
}
}
private boolean isAsyncVoidReturnType(MethodParameter returnType, @Nullable ReactiveAdapter reactiveAdapter) {
if (reactiveAdapter != null && reactiveAdapter.supportsEmpty()) {
if (reactiveAdapter.isNoValue()) {
return true;
}
Type parameterType = returnType.getGenericParameterType();
if (parameterType instanceof ParameterizedType) {
ParameterizedType type = (ParameterizedType) parameterType;
if (type.getActualTypeArguments().length == 1) {
return Void.clreplaced.equals(type.getActualTypeArguments()[0]);
}
}
}
return false;
}
}
17
View Source File : ModelInitializerTests.java
License : Apache License 2.0
Project Creator : SourceHot
License : Apache License 2.0
Project Creator : SourceHot
@BeforeEach
public void setup() {
ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
ArgumentResolverConfigurer resolverConfigurer = new ArgumentResolverConfigurer();
resolverConfigurer.addCustomResolver(new ModelMethodArgumentResolver(adapterRegistry));
ControllerMethodResolver methodResolver = new ControllerMethodResolver(resolverConfigurer, adapterRegistry, new StaticApplicationContext(), Collections.emptyList());
this.modelInitializer = new ModelInitializer(methodResolver, adapterRegistry);
}
17
View Source File : InvocableHandlerMethod.java
License : Apache License 2.0
Project Creator : SourceHot
License : Apache License 2.0
Project Creator : SourceHot
/**
* Extension of {@link HandlerMethod} that invokes the underlying method with
* argument values resolved from the current HTTP request through a list of
* {@link HandlerMethodArgumentResolver}.
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller
* @author Sebastien Deleuze
* @since 5.0
*/
public clreplaced InvocableHandlerMethod extends HandlerMethod {
private static final Mono<Object[]> EMPTY_ARGS = Mono.just(new Object[0]);
private static final Object NO_ARG_VALUE = new Object();
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
/**
* Create an instance from a {@code HandlerMethod}.
*/
public InvocableHandlerMethod(HandlerMethod handlerMethod) {
super(handlerMethod);
}
/**
* Create an instance from a bean instance and a method.
*/
public InvocableHandlerMethod(Object bean, Method method) {
super(bean, method);
}
/**
* Configure the argument resolvers to use to use for resolving method
* argument values against a {@code ServerWebExchange}.
*/
public void setArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
this.resolvers.addResolvers(resolvers);
}
/**
* Return the configured argument resolvers.
*/
public List<HandlerMethodArgumentResolver> getResolvers() {
return this.resolvers.getResolvers();
}
/**
* Set the ParameterNameDiscoverer for resolving parameter names when needed
* (e.g. default request attribute name).
* <p>Default is a {@link DefaultParameterNameDiscoverer}.
*/
public void setParameterNameDiscoverer(ParameterNameDiscoverer nameDiscoverer) {
this.parameterNameDiscoverer = nameDiscoverer;
}
/**
* Return the configured parameter name discoverer.
*/
public ParameterNameDiscoverer getParameterNameDiscoverer() {
return this.parameterNameDiscoverer;
}
/**
* Configure a reactive adapter registry. This is needed for cases where the response is
* fully handled within the controller in combination with an async void return value.
* <p>By default this is a {@link ReactiveAdapterRegistry} with default settings.
*/
public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) {
this.reactiveAdapterRegistry = registry;
}
/**
* Invoke the method for the given exchange.
* @param exchange the current exchange
* @param bindingContext the binding context to use
* @param providedArgs optional list of argument values to match by type
* @return a Mono with a {@link HandlerResult}
*/
@SuppressWarnings("KotlinInternalInJava")
public Mono<HandlerResult> invoke(ServerWebExchange exchange, BindingContext bindingContext, Object... providedArgs) {
return getMethodArgumentValues(exchange, bindingContext, providedArgs).flatMap(args -> {
Object value;
try {
ReflectionUtils.makeAccessible(getBridgedMethod());
Method method = getBridgedMethod();
if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(method.getDeclaringClreplaced()) && CoroutinesUtils.isSuspendingFunction(method)) {
value = CoroutinesUtils.invokeSuspendingFunction(method, getBean(), args);
} else {
value = method.invoke(getBean(), args);
}
} catch (IllegalArgumentException ex) {
replacedertTargetBean(getBridgedMethod(), getBean(), args);
String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
return Mono.error(new IllegalStateException(formatInvokeError(text, args), ex));
} catch (InvocationTargetException ex) {
return Mono.error(ex.getTargetException());
} catch (Throwable ex) {
// Unlikely to ever get here, but it must be handled...
return Mono.error(new IllegalStateException(formatInvokeError("Invocation failure", args), ex));
}
HttpStatus status = getResponseStatus();
if (status != null) {
exchange.getResponse().setStatusCode(status);
}
MethodParameter returnType = getReturnType();
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(returnType.getParameterType());
boolean asyncVoid = isAsyncVoidReturnType(returnType, adapter);
if ((value == null || asyncVoid) && isResponseHandled(args, exchange)) {
return (asyncVoid ? Mono.from(adapter.toPublisher(value)) : Mono.empty());
}
HandlerResult result = new HandlerResult(this, value, returnType, bindingContext);
return Mono.just(result);
});
}
private Mono<Object[]> getMethodArgumentValues(ServerWebExchange exchange, BindingContext bindingContext, Object... providedArgs) {
MethodParameter[] parameters = getMethodParameters();
if (ObjectUtils.isEmpty(parameters)) {
return EMPTY_ARGS;
}
List<Mono<Object>> argMonos = new ArrayList<>(parameters.length);
for (MethodParameter parameter : parameters) {
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
Object providedArg = findProvidedArgument(parameter, providedArgs);
if (providedArg != null) {
argMonos.add(Mono.just(providedArg));
continue;
}
if (!this.resolvers.supportsParameter(parameter)) {
return Mono.error(new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")));
}
try {
argMonos.add(this.resolvers.resolveArgument(parameter, bindingContext, exchange).defaultIfEmpty(NO_ARG_VALUE).doOnError(ex -> logArgumentErrorIfNecessary(exchange, parameter, ex)));
} catch (Exception ex) {
logArgumentErrorIfNecessary(exchange, parameter, ex);
argMonos.add(Mono.error(ex));
}
}
return Mono.zip(argMonos, values -> Stream.of(values).map(value -> value != NO_ARG_VALUE ? value : null).toArray());
}
private void logArgumentErrorIfNecessary(ServerWebExchange exchange, MethodParameter parameter, Throwable ex) {
// Leave stack trace for later, if error is not handled...
String exMsg = ex.getMessage();
if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
if (logger.isDebugEnabled()) {
logger.debug(exchange.getLogPrefix() + formatArgumentError(parameter, exMsg));
}
}
}
private static boolean isAsyncVoidReturnType(MethodParameter returnType, @Nullable ReactiveAdapter adapter) {
if (adapter != null && adapter.supportsEmpty()) {
if (adapter.isNoValue()) {
return true;
}
Type parameterType = returnType.getGenericParameterType();
if (parameterType instanceof ParameterizedType) {
ParameterizedType type = (ParameterizedType) parameterType;
if (type.getActualTypeArguments().length == 1) {
return Void.clreplaced.equals(type.getActualTypeArguments()[0]);
}
}
}
return false;
}
private boolean isResponseHandled(Object[] args, ServerWebExchange exchange) {
if (getResponseStatus() != null || exchange.isNotModified()) {
return true;
}
for (Object arg : args) {
if (arg instanceof ServerHttpResponse || arg instanceof ServerWebExchange) {
return true;
}
}
return false;
}
}
17
View Source File : DefaultRSocketStrategiesTests.java
License : Apache License 2.0
Project Creator : SourceHot
License : Apache License 2.0
Project Creator : SourceHot
@Test
void explicitValues() {
SimpleRouteMatcher matcher = new SimpleRouteMatcher(new AntPathMatcher());
DefaultMetadataExtractor extractor = new DefaultMetadataExtractor();
ReactiveAdapterRegistry registry = new ReactiveAdapterRegistry();
RSocketStrategies strategies = RSocketStrategies.builder().encoders(encoders -> {
encoders.clear();
encoders.add(new ByteArrayEncoder());
}).decoders(decoders -> {
decoders.clear();
decoders.add(new ByteArrayDecoder());
}).routeMatcher(matcher).metadataExtractor(extractor).reactiveAdapterStrategy(registry).build();
replacedertThat(strategies.encoders()).hreplacedize(1);
replacedertThat(strategies.decoders()).hreplacedize(1);
replacedertThat(strategies.routeMatcher()).isSameAs(matcher);
replacedertThat(strategies.metadataExtractor()).isSameAs(extractor);
replacedertThat(strategies.reactiveAdapterRegistry()).isSameAs(registry);
}
17
View Source File : InvocableHandlerMethod.java
License : Apache License 2.0
Project Creator : SourceHot
License : Apache License 2.0
Project Creator : SourceHot
/**
* Extension of {@link HandlerMethod} that invokes the underlying method with
* argument values resolved from the current HTTP request through a list of
* {@link HandlerMethodArgumentResolver}.
*
* @author Rossen Stoyanchev
* @since 5.2
*/
public clreplaced InvocableHandlerMethod extends HandlerMethod {
private static final Mono<Object[]> EMPTY_ARGS = Mono.just(new Object[0]);
private static final Object NO_ARG_VALUE = new Object();
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
/**
* Create an instance from a {@code HandlerMethod}.
*/
public InvocableHandlerMethod(HandlerMethod handlerMethod) {
super(handlerMethod);
}
/**
* Create an instance from a bean instance and a method.
*/
public InvocableHandlerMethod(Object bean, Method method) {
super(bean, method);
}
/**
* Configure the argument resolvers to use to use for resolving method
* argument values against a {@code ServerWebExchange}.
*/
public void setArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
this.resolvers.addResolvers(resolvers);
}
/**
* Return the configured argument resolvers.
*/
public List<HandlerMethodArgumentResolver> getResolvers() {
return this.resolvers.getResolvers();
}
/**
* Set the ParameterNameDiscoverer for resolving parameter names when needed
* (e.g. default request attribute name).
* <p>Default is a {@link DefaultParameterNameDiscoverer}.
*/
public void setParameterNameDiscoverer(ParameterNameDiscoverer nameDiscoverer) {
this.parameterNameDiscoverer = nameDiscoverer;
}
/**
* Return the configured parameter name discoverer.
*/
public ParameterNameDiscoverer getParameterNameDiscoverer() {
return this.parameterNameDiscoverer;
}
/**
* Configure a reactive adapter registry. This is needed for async return values.
* <p>By default this is a {@link ReactiveAdapterRegistry} with default settings.
*/
public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) {
this.reactiveAdapterRegistry = registry;
}
/**
* Invoke the method for the given exchange.
* @param message the current message
* @param providedArgs optional list of argument values to match by type
* @return a Mono with the result from the invocation
*/
@SuppressWarnings("KotlinInternalInJava")
public Mono<Object> invoke(Message<?> message, Object... providedArgs) {
return getMethodArgumentValues(message, providedArgs).flatMap(args -> {
Object value;
boolean isSuspendingFunction = false;
try {
Method method = getBridgedMethod();
ReflectionUtils.makeAccessible(method);
if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(method.getDeclaringClreplaced()) && CoroutinesUtils.isSuspendingFunction(method)) {
isSuspendingFunction = true;
value = CoroutinesUtils.invokeSuspendingFunction(method, getBean(), args);
} else {
value = method.invoke(getBean(), args);
}
} catch (IllegalArgumentException ex) {
replacedertTargetBean(getBridgedMethod(), getBean(), args);
String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
return Mono.error(new IllegalStateException(formatInvokeError(text, args), ex));
} catch (InvocationTargetException ex) {
return Mono.error(ex.getTargetException());
} catch (Throwable ex) {
// Unlikely to ever get here, but it must be handled...
return Mono.error(new IllegalStateException(formatInvokeError("Invocation failure", args), ex));
}
MethodParameter returnType = getReturnType();
Clreplaced<?> reactiveType = (isSuspendingFunction ? value.getClreplaced() : returnType.getParameterType());
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(reactiveType);
return (isAsyncVoidReturnType(returnType, adapter) ? Mono.from(adapter.toPublisher(value)) : Mono.justOrEmpty(value));
});
}
private Mono<Object[]> getMethodArgumentValues(Message<?> message, Object... providedArgs) {
MethodParameter[] parameters = getMethodParameters();
if (ObjectUtils.isEmpty(getMethodParameters())) {
return EMPTY_ARGS;
}
List<Mono<Object>> argMonos = new ArrayList<>(parameters.length);
for (MethodParameter parameter : parameters) {
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
Object providedArg = findProvidedArgument(parameter, providedArgs);
if (providedArg != null) {
argMonos.add(Mono.just(providedArg));
continue;
}
if (!this.resolvers.supportsParameter(parameter)) {
return Mono.error(new MethodArgumentResolutionException(message, parameter, formatArgumentError(parameter, "No suitable resolver")));
}
try {
argMonos.add(this.resolvers.resolveArgument(parameter, message).defaultIfEmpty(NO_ARG_VALUE).doOnError(ex -> logArgumentErrorIfNecessary(parameter, ex)));
} catch (Exception ex) {
logArgumentErrorIfNecessary(parameter, ex);
argMonos.add(Mono.error(ex));
}
}
return Mono.zip(argMonos, values -> Stream.of(values).map(value -> value != NO_ARG_VALUE ? value : null).toArray());
}
private void logArgumentErrorIfNecessary(MethodParameter parameter, Throwable ex) {
// Leave stack trace for later, if error is not handled...
String exMsg = ex.getMessage();
if (exMsg != null && !exMsg.contains(parameter.getExecutable().toGenericString())) {
if (logger.isDebugEnabled()) {
logger.debug(formatArgumentError(parameter, exMsg));
}
}
}
private boolean isAsyncVoidReturnType(MethodParameter returnType, @Nullable ReactiveAdapter reactiveAdapter) {
if (reactiveAdapter != null && reactiveAdapter.supportsEmpty()) {
if (reactiveAdapter.isNoValue()) {
return true;
}
Type parameterType = returnType.getGenericParameterType();
if (parameterType instanceof ParameterizedType) {
ParameterizedType type = (ParameterizedType) parameterType;
if (type.getActualTypeArguments().length == 1) {
return Void.clreplaced.equals(type.getActualTypeArguments()[0]);
}
}
}
return false;
}
}
17
View Source File : ModelInitializerTests.java
License : MIT License
Project Creator : mindcarver
License : MIT License
Project Creator : mindcarver
@Before
public void setUp() throws Exception {
ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
ArgumentResolverConfigurer resolverConfigurer = new ArgumentResolverConfigurer();
resolverConfigurer.addCustomResolver(new ModelArgumentResolver(adapterRegistry));
ControllerMethodResolver methodResolver = new ControllerMethodResolver(resolverConfigurer, adapterRegistry, new StaticApplicationContext(), Collections.emptyList());
this.modelInitializer = new ModelInitializer(methodResolver, adapterRegistry);
}
17
View Source File : InvocableHandlerMethod.java
License : MIT License
Project Creator : mindcarver
License : MIT License
Project Creator : mindcarver
/**
* Extension of {@link HandlerMethod} that invokes the underlying method with
* argument values resolved from the current HTTP request through a list of
* {@link HandlerMethodArgumentResolver}.
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 5.0
*/
public clreplaced InvocableHandlerMethod extends HandlerMethod {
private static final Mono<Object[]> EMPTY_ARGS = Mono.just(new Object[0]);
private static final Object NO_ARG_VALUE = new Object();
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
/**
* Create an instance from a {@code HandlerMethod}.
*/
public InvocableHandlerMethod(HandlerMethod handlerMethod) {
super(handlerMethod);
}
/**
* Create an instance from a bean instance and a method.
*/
public InvocableHandlerMethod(Object bean, Method method) {
super(bean, method);
}
/**
* Configure the argument resolvers to use to use for resolving method
* argument values against a {@code ServerWebExchange}.
*/
public void setArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
this.resolvers.addResolvers(resolvers);
}
/**
* Return the configured argument resolvers.
*/
public List<HandlerMethodArgumentResolver> getResolvers() {
return this.resolvers.getResolvers();
}
/**
* Set the ParameterNameDiscoverer for resolving parameter names when needed
* (e.g. default request attribute name).
* <p>Default is a {@link DefaultParameterNameDiscoverer}.
*/
public void setParameterNameDiscoverer(ParameterNameDiscoverer nameDiscoverer) {
this.parameterNameDiscoverer = nameDiscoverer;
}
/**
* Return the configured parameter name discoverer.
*/
public ParameterNameDiscoverer getParameterNameDiscoverer() {
return this.parameterNameDiscoverer;
}
/**
* Configure a reactive registry. This is needed for cases where the response
* is fully handled within the controller in combination with an async void
* return value.
* <p>By default this is an instance of {@link ReactiveAdapterRegistry} with
* default settings.
* @param registry the registry to use
*/
public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) {
this.reactiveAdapterRegistry = registry;
}
/**
* Invoke the method for the given exchange.
* @param exchange the current exchange
* @param bindingContext the binding context to use
* @param providedArgs optional list of argument values to match by type
* @return a Mono with a {@link HandlerResult}.
*/
public Mono<HandlerResult> invoke(ServerWebExchange exchange, BindingContext bindingContext, Object... providedArgs) {
return getMethodArgumentValues(exchange, bindingContext, providedArgs).flatMap(args -> {
Object value;
try {
ReflectionUtils.makeAccessible(getBridgedMethod());
value = getBridgedMethod().invoke(getBean(), args);
} catch (IllegalArgumentException ex) {
replacedertTargetBean(getBridgedMethod(), getBean(), args);
String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
return Mono.error(new IllegalStateException(formatInvokeError(text, args), ex));
} catch (InvocationTargetException ex) {
return Mono.error(ex.getTargetException());
} catch (Throwable ex) {
// Unlikely to ever get here, but it must be handled...
return Mono.error(new IllegalStateException(formatInvokeError("Invocation failure", args), ex));
}
HttpStatus status = getResponseStatus();
if (status != null) {
exchange.getResponse().setStatusCode(status);
}
MethodParameter returnType = getReturnType();
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(returnType.getParameterType());
boolean asyncVoid = isAsyncVoidReturnType(returnType, adapter);
if ((value == null || asyncVoid) && isResponseHandled(args, exchange)) {
return (asyncVoid ? Mono.from(adapter.toPublisher(value)) : Mono.empty());
}
HandlerResult result = new HandlerResult(this, value, returnType, bindingContext);
return Mono.just(result);
});
}
private Mono<Object[]> getMethodArgumentValues(ServerWebExchange exchange, BindingContext bindingContext, Object... providedArgs) {
if (ObjectUtils.isEmpty(getMethodParameters())) {
return EMPTY_ARGS;
}
MethodParameter[] parameters = getMethodParameters();
List<Mono<Object>> argMonos = new ArrayList<>(parameters.length);
for (MethodParameter parameter : parameters) {
parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
Object providedArg = findProvidedArgument(parameter, providedArgs);
if (providedArg != null) {
argMonos.add(Mono.just(providedArg));
continue;
}
if (!this.resolvers.supportsParameter(parameter)) {
return Mono.error(new IllegalStateException(formatArgumentError(parameter, "No suitable resolver")));
}
try {
argMonos.add(this.resolvers.resolveArgument(parameter, bindingContext, exchange).defaultIfEmpty(NO_ARG_VALUE).doOnError(cause -> logArgumentErrorIfNecessary(exchange, parameter, cause)));
} catch (Exception ex) {
logArgumentErrorIfNecessary(exchange, parameter, ex);
argMonos.add(Mono.error(ex));
}
}
return Mono.zip(argMonos, values -> Stream.of(values).map(o -> o != NO_ARG_VALUE ? o : null).toArray());
}
private void logArgumentErrorIfNecessary(ServerWebExchange exchange, MethodParameter parameter, Throwable cause) {
// Leave stack trace for later, if error is not handled..
String message = cause.getMessage();
if (!message.contains(parameter.getExecutable().toGenericString())) {
if (logger.isDebugEnabled()) {
logger.debug(exchange.getLogPrefix() + formatArgumentError(parameter, message));
}
}
}
private static boolean isAsyncVoidReturnType(MethodParameter returnType, @Nullable ReactiveAdapter adapter) {
if (adapter != null && adapter.supportsEmpty()) {
if (adapter.isNoValue()) {
return true;
}
Type parameterType = returnType.getGenericParameterType();
if (parameterType instanceof ParameterizedType) {
ParameterizedType type = (ParameterizedType) parameterType;
if (type.getActualTypeArguments().length == 1) {
return Void.clreplaced.equals(type.getActualTypeArguments()[0]);
}
}
}
return false;
}
private boolean isResponseHandled(Object[] args, ServerWebExchange exchange) {
if (getResponseStatus() != null || exchange.isNotModified()) {
return true;
}
for (Object arg : args) {
if (arg instanceof ServerHttpResponse || arg instanceof ServerWebExchange) {
return true;
}
}
return false;
}
}
17
View Source File : ControllerMethodResolver.java
License : MIT License
Project Creator : mindcarver
License : MIT License
Project Creator : mindcarver
private static List<HandlerMethodArgumentResolver> exceptionHandlerResolvers(ArgumentResolverConfigurer customResolvers, ReactiveAdapterRegistry reactiveRegistry, ConfigurableApplicationContext context) {
return initResolvers(customResolvers, reactiveRegistry, context, false, Collections.emptyList());
}
17
View Source File : ControllerMethodResolver.java
License : MIT License
Project Creator : mindcarver
License : MIT License
Project Creator : mindcarver
private List<SyncHandlerMethodArgumentResolver> initBinderResolvers(ArgumentResolverConfigurer customResolvers, ReactiveAdapterRegistry reactiveRegistry, ConfigurableApplicationContext context) {
return initResolvers(customResolvers, reactiveRegistry, context, false, Collections.emptyList()).stream().filter(resolver -> resolver instanceof SyncHandlerMethodArgumentResolver).map(resolver -> (SyncHandlerMethodArgumentResolver) resolver).collect(Collectors.toList());
}
17
View Source File : ControllerMethodResolver.java
License : MIT License
Project Creator : mindcarver
License : MIT License
Project Creator : mindcarver
private static List<HandlerMethodArgumentResolver> modelMethodResolvers(ArgumentResolverConfigurer customResolvers, ReactiveAdapterRegistry reactiveRegistry, ConfigurableApplicationContext context) {
return initResolvers(customResolvers, reactiveRegistry, context, true, Collections.emptyList());
}
17
View Source File : ServiceConsumeConfiguration.java
License : Apache License 2.0
Project Creator : alibaba
License : Apache License 2.0
Project Creator : alibaba
/**
* Service consumer configuration
*
* @author leijuan
*/
@Configuration
public clreplaced ServiceConsumeConfiguration {
@Autowired
private ReactiveAdapterRegistry reactiveAdapterRegistry;
@PostConstruct
public void init() {
new RxJava3Registrar().registerAdapters(reactiveAdapterRegistry);
}
@Bean
public UserService userService(UpstreamManager upstreamManager) {
return RSocketRemoteServiceBuilder.client(UserService.clreplaced).upstreamManager(upstreamManager).build();
}
@Bean
public UserServiceExtra userServiceExtra(UpstreamManager upstreamManager) {
return RSocketRemoteServiceBuilder.client(UserServiceExtra.clreplaced).service(UserService.clreplaced.getCanonicalName()).upstreamManager(upstreamManager).acceptEncodingType(RSocketMimeType.Json).build();
}
@Bean
public RxUserService rxUserService(UpstreamManager upstreamManager) {
return RSocketRemoteServiceBuilder.client(RxUserService.clreplaced).encodingType(RSocketMimeType.CBOR).upstreamManager(upstreamManager).build();
}
@Bean
public Rx3UserService rx3UserService(UpstreamManager upstreamManager) {
return RSocketRemoteServiceBuilder.client(Rx3UserService.clreplaced).upstreamManager(upstreamManager).build();
}
@Bean
public AccountService accountService(UpstreamManager upstreamManager) {
return RSocketRemoteServiceBuilder.client(AccountService.clreplaced).encodingType(RSocketMimeType.Protobuf).upstreamManager(upstreamManager).build();
}
@Bean
public RSocketRequester rsocketRequester(UpstreamManager upstreamManager) {
LoadBalancedRSocket loadBalancedRSocket = upstreamManager.findBroker().getLoadBalancedRSocket();
RSocketStrategies rSocketStrategies = RSocketStrategies.builder().encoder(new HessianEncoder()).decoder(new HessianDecoder()).build();
return RSocketRequester.wrap(loadBalancedRSocket, MimeType.valueOf("application/x-hessian"), MimeType.valueOf("message/x.rsocket.composite-metadata.v0"), rSocketStrategies);
}
}
16
View Source File : ResultErrorAutoConfig.java
License : Apache License 2.0
Project Creator : yl-yue
License : Apache License 2.0
Project Creator : yl-yue
/**
* 默认优先级高于 ResponseBodyResultHandler
*/
@Bean
public ResultResponseBodyHandler resultResponseBodyHandler(ServerCodecConfigurer serverCodecConfigurer, @Qualifier("webFluxContentTypeResolver") RequestedContentTypeResolver contentTypeResolver, @Qualifier("webFluxAdapterRegistry") ReactiveAdapterRegistry reactiveAdapterRegistry) {
return new ResultResponseBodyHandler(serverCodecConfigurer.getWriters(), contentTypeResolver, reactiveAdapterRegistry);
}
16
View Source File : ReactiveTypeHandlerTests.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
@Before
public void setup() throws Exception {
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
factoryBean.afterPropertiesSet();
ContentNegotiationManager manager = factoryBean.getObject();
ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
this.handler = new ReactiveTypeHandler(adapterRegistry, new SyncTaskExecutor(), manager);
resetRequest();
}
16
View Source File : ReactiveTypeHandler.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Private helper clreplaced to replacedist with handling "reactive" return values types
* that can be adapted to a Reactive Streams {@link Publisher} through the
* {@link ReactiveAdapterRegistry}.
*
* <p>Such return values may be bridged to a {@link ResponseBodyEmitter} for
* streaming purposes at the presence of a streaming media type or based on the
* generic type.
*
* <p>For all other cases {@code Publisher} output is collected and bridged to
* {@link DeferredResult} for standard async request processing.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
clreplaced ReactiveTypeHandler {
private static final long STREAMING_TIMEOUT_VALUE = -1;
private static Log logger = LogFactory.getLog(ReactiveTypeHandler.clreplaced);
private final ReactiveAdapterRegistry adapterRegistry;
private final TaskExecutor taskExecutor;
private final ContentNegotiationManager contentNegotiationManager;
private boolean taskExecutorWarning;
public ReactiveTypeHandler() {
this(ReactiveAdapterRegistry.getSharedInstance(), new SyncTaskExecutor(), new ContentNegotiationManager());
}
ReactiveTypeHandler(ReactiveAdapterRegistry registry, TaskExecutor executor, ContentNegotiationManager manager) {
replacedert.notNull(registry, "ReactiveAdapterRegistry is required");
replacedert.notNull(executor, "TaskExecutor is required");
replacedert.notNull(manager, "ContentNegotiationManager is required");
this.adapterRegistry = registry;
this.taskExecutor = executor;
this.contentNegotiationManager = manager;
this.taskExecutorWarning = (executor instanceof SimpleAsyncTaskExecutor || executor instanceof SyncTaskExecutor);
}
/**
* Whether the type can be adapted to a Reactive Streams {@link Publisher}.
*/
public boolean isReactiveType(Clreplaced<?> type) {
return (this.adapterRegistry.getAdapter(type) != null);
}
/**
* Process the given reactive return value and decide whether to adapt it
* to a {@link ResponseBodyEmitter} or a {@link DeferredResult}.
* @return an emitter for streaming, or {@code null} if handled internally
* with a {@link DeferredResult}
*/
@Nullable
public ResponseBodyEmitter handleValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mav, NativeWebRequest request) throws Exception {
replacedert.notNull(returnValue, "Expected return value");
ReactiveAdapter adapter = this.adapterRegistry.getAdapter(returnValue.getClreplaced());
replacedert.state(adapter != null, () -> "Unexpected return value: " + returnValue);
ResolvableType elementType = ResolvableType.forMethodParameter(returnType).getGeneric();
Clreplaced<?> elementClreplaced = elementType.toClreplaced();
Collection<MediaType> mediaTypes = getMediaTypes(request);
Optional<MediaType> mediaType = mediaTypes.stream().filter(MimeType::isConcrete).findFirst();
if (adapter.isMultiValue()) {
if (mediaTypes.stream().anyMatch(MediaType.TEXT_EVENT_STREAM::includes) || ServerSentEvent.clreplaced.isreplacedignableFrom(elementClreplaced)) {
logExecutorWarning(returnType);
SseEmitter emitter = new SseEmitter(STREAMING_TIMEOUT_VALUE);
new SseEmitterSubscriber(emitter, this.taskExecutor).connect(adapter, returnValue);
return emitter;
}
if (CharSequence.clreplaced.isreplacedignableFrom(elementClreplaced)) {
logExecutorWarning(returnType);
ResponseBodyEmitter emitter = getEmitter(mediaType.orElse(MediaType.TEXT_PLAIN));
new TextEmitterSubscriber(emitter, this.taskExecutor).connect(adapter, returnValue);
return emitter;
}
if (mediaTypes.stream().anyMatch(MediaType.APPLICATION_STREAM_JSON::includes)) {
logExecutorWarning(returnType);
ResponseBodyEmitter emitter = getEmitter(MediaType.APPLICATION_STREAM_JSON);
new JsonEmitterSubscriber(emitter, this.taskExecutor).connect(adapter, returnValue);
return emitter;
}
}
// Not streaming...
DeferredResult<Object> result = new DeferredResult<>();
new DeferredResultSubscriber(result, adapter, elementType).connect(adapter, returnValue);
WebAsyncUtils.getAsyncManager(request).startDeferredResultProcessing(result, mav);
return null;
}
@SuppressWarnings("unchecked")
private Collection<MediaType> getMediaTypes(NativeWebRequest request) throws HttpMediaTypeNotAcceptableException {
Collection<MediaType> mediaTypes = (Collection<MediaType>) request.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST);
return CollectionUtils.isEmpty(mediaTypes) ? this.contentNegotiationManager.resolveMediaTypes(request) : mediaTypes;
}
private ResponseBodyEmitter getEmitter(MediaType mediaType) {
return new ResponseBodyEmitter(STREAMING_TIMEOUT_VALUE) {
@Override
protected void extendResponse(ServerHttpResponse outputMessage) {
outputMessage.getHeaders().setContentType(mediaType);
}
};
}
@SuppressWarnings("ConstantConditions")
private void logExecutorWarning(MethodParameter returnType) {
if (this.taskExecutorWarning && logger.isWarnEnabled()) {
synchronized (this) {
if (this.taskExecutorWarning) {
String executorTypeName = this.taskExecutor.getClreplaced().getSimpleName();
logger.warn("\n!!!\n" + "Streaming through a reactive type requires an Executor to write to the response.\n" + "Please, configure a TaskExecutor in the MVC config under \"async support\".\n" + "The " + executorTypeName + " currently in use is not suitable under load.\n" + "-------------------------------\n" + "Controller:\t" + returnType.getContainingClreplaced().getName() + "\n" + "Method:\t\t" + returnType.getMethod().getName() + "\n" + "Returning:\t" + ResolvableType.forMethodParameter(returnType).toString() + "\n" + "!!!");
this.taskExecutorWarning = false;
}
}
}
}
private abstract static clreplaced AbstractEmitterSubscriber implements Subscriber<Object>, Runnable {
private final ResponseBodyEmitter emitter;
private final TaskExecutor taskExecutor;
@Nullable
private Subscription subscription;
private final AtomicReference<Object> elementRef = new AtomicReference<>();
@Nullable
private Throwable error;
private volatile boolean terminated;
private final AtomicLong executing = new AtomicLong();
private volatile boolean done;
protected AbstractEmitterSubscriber(ResponseBodyEmitter emitter, TaskExecutor executor) {
this.emitter = emitter;
this.taskExecutor = executor;
}
public void connect(ReactiveAdapter adapter, Object returnValue) {
Publisher<Object> publisher = adapter.toPublisher(returnValue);
publisher.subscribe(this);
}
protected ResponseBodyEmitter getEmitter() {
return this.emitter;
}
@Override
public final void onSubscribe(Subscription subscription) {
this.subscription = subscription;
this.emitter.onTimeout(() -> {
if (logger.isTraceEnabled()) {
logger.trace("Connection timeout for " + this.emitter);
}
terminate();
this.emitter.complete();
});
this.emitter.onError(this.emitter::completeWithError);
subscription.request(1);
}
@Override
public final void onNext(Object element) {
this.elementRef.lazySet(element);
trySchedule();
}
@Override
public final void onError(Throwable ex) {
this.error = ex;
this.terminated = true;
trySchedule();
}
@Override
public final void onComplete() {
this.terminated = true;
trySchedule();
}
private void trySchedule() {
if (this.executing.getAndIncrement() == 0) {
schedule();
}
}
private void schedule() {
try {
this.taskExecutor.execute(this);
} catch (Throwable ex) {
try {
terminate();
} finally {
this.executing.decrementAndGet();
this.elementRef.lazySet(null);
}
}
}
@Override
public void run() {
if (this.done) {
this.elementRef.lazySet(null);
return;
}
// Check terminal signal before processing element..
boolean isTerminated = this.terminated;
Object element = this.elementRef.get();
if (element != null) {
this.elementRef.lazySet(null);
replacedert.state(this.subscription != null, "No subscription");
try {
send(element);
this.subscription.request(1);
} catch (final Throwable ex) {
if (logger.isTraceEnabled()) {
logger.trace("Send for " + this.emitter + " failed: " + ex);
}
terminate();
return;
}
}
if (isTerminated) {
this.done = true;
Throwable ex = this.error;
this.error = null;
if (ex != null) {
if (logger.isTraceEnabled()) {
logger.trace("Publisher for " + this.emitter + " failed: " + ex);
}
this.emitter.completeWithError(ex);
} else {
if (logger.isTraceEnabled()) {
logger.trace("Publisher for " + this.emitter + " completed");
}
this.emitter.complete();
}
return;
}
if (this.executing.decrementAndGet() != 0) {
schedule();
}
}
protected abstract void send(Object element) throws IOException;
private void terminate() {
this.done = true;
if (this.subscription != null) {
this.subscription.cancel();
}
}
}
private static clreplaced SseEmitterSubscriber extends AbstractEmitterSubscriber {
SseEmitterSubscriber(SseEmitter sseEmitter, TaskExecutor executor) {
super(sseEmitter, executor);
}
@Override
protected void send(Object element) throws IOException {
if (element instanceof ServerSentEvent) {
ServerSentEvent<?> event = (ServerSentEvent<?>) element;
((SseEmitter) getEmitter()).send(adapt(event));
} else {
getEmitter().send(element, MediaType.APPLICATION_JSON);
}
}
private SseEmitter.SseEventBuilder adapt(ServerSentEvent<?> sse) {
SseEmitter.SseEventBuilder builder = SseEmitter.event();
String id = sse.id();
String event = sse.event();
Duration retry = sse.retry();
String comment = sse.comment();
Object data = sse.data();
if (id != null) {
builder.id(id);
}
if (event != null) {
builder.name(event);
}
if (data != null) {
builder.data(data);
}
if (retry != null) {
builder.reconnectTime(retry.toMillis());
}
if (comment != null) {
builder.comment(comment);
}
return builder;
}
}
private static clreplaced JsonEmitterSubscriber extends AbstractEmitterSubscriber {
JsonEmitterSubscriber(ResponseBodyEmitter emitter, TaskExecutor executor) {
super(emitter, executor);
}
@Override
protected void send(Object element) throws IOException {
getEmitter().send(element, MediaType.APPLICATION_JSON);
getEmitter().send("\n", MediaType.TEXT_PLAIN);
}
}
private static clreplaced TextEmitterSubscriber extends AbstractEmitterSubscriber {
TextEmitterSubscriber(ResponseBodyEmitter emitter, TaskExecutor executor) {
super(emitter, executor);
}
@Override
protected void send(Object element) throws IOException {
getEmitter().send(element, MediaType.TEXT_PLAIN);
}
}
private static clreplaced DeferredResultSubscriber implements Subscriber<Object> {
private final DeferredResult<Object> result;
private final boolean multiValueSource;
private final CollectedValuesList values;
DeferredResultSubscriber(DeferredResult<Object> result, ReactiveAdapter adapter, ResolvableType elementType) {
this.result = result;
this.multiValueSource = adapter.isMultiValue();
this.values = new CollectedValuesList(elementType);
}
public void connect(ReactiveAdapter adapter, Object returnValue) {
Publisher<Object> publisher = adapter.toPublisher(returnValue);
publisher.subscribe(this);
}
@Override
public void onSubscribe(Subscription subscription) {
this.result.onTimeout(subscription::cancel);
subscription.request(Long.MAX_VALUE);
}
@Override
public void onNext(Object element) {
this.values.add(element);
}
@Override
public void onError(Throwable ex) {
this.result.setErrorResult(ex);
}
@Override
public void onComplete() {
if (this.values.size() > 1 || this.multiValueSource) {
this.result.setResult(this.values);
} else if (this.values.size() == 1) {
this.result.setResult(this.values.get(0));
} else {
this.result.setResult(null);
}
}
}
/**
* List of collect values where all elements are a specified type.
*/
@SuppressWarnings("serial")
static clreplaced CollectedValuesList extends ArrayList<Object> {
private final ResolvableType elementType;
CollectedValuesList(ResolvableType elementType) {
this.elementType = elementType;
}
public ResolvableType getReturnType() {
return ResolvableType.forClreplacedWithGenerics(List.clreplaced, this.elementType);
}
}
}
16
View Source File : RequestPartMethodArgumentResolverTests.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
@Before
public void setup() throws Exception {
List<HttpMessageReader<?>> readers = ServerCodecConfigurer.create().getReaders();
ReactiveAdapterRegistry registry = ReactiveAdapterRegistry.getSharedInstance();
this.resolver = new RequestPartMethodArgumentResolver(readers, registry);
List<HttpMessageWriter<?>> writers = ClientCodecConfigurer.create().getWriters();
this.writer = new MultipartHttpMessageWriter(writers);
}
16
View Source File : RequestParamMethodArgumentResolverTests.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
@Test
public void doesNotSupportParameterWithDefaultResolutionTurnedOff() {
ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
this.resolver = new RequestParamMethodArgumentResolver(null, adapterRegistry, false);
MethodParameter param = this.testMethod.annotNotPresent(RequestParam.clreplaced).arg(String.clreplaced);
replacedertFalse(this.resolver.supportsParameter(param));
}
16
View Source File : HandlerResultHandlerSupport.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Base clreplaced for {@link org.springframework.web.reactive.HandlerResultHandler
* HandlerResultHandler} with support for content negotiation and access to a
* {@code ReactiveAdapter} registry.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
public abstract clreplaced HandlerResultHandlerSupport implements Ordered {
private static final List<MediaType> ALL_APPLICATION_MEDIA_TYPES = Arrays.asList(MediaType.ALL, new MediaType("application"));
protected final Log logger = LogFactory.getLog(getClreplaced());
private final RequestedContentTypeResolver contentTypeResolver;
private final ReactiveAdapterRegistry adapterRegistry;
private int order = LOWEST_PRECEDENCE;
protected HandlerResultHandlerSupport(RequestedContentTypeResolver contentTypeResolver, ReactiveAdapterRegistry adapterRegistry) {
replacedert.notNull(contentTypeResolver, "RequestedContentTypeResolver is required");
replacedert.notNull(adapterRegistry, "ReactiveAdapterRegistry is required");
this.contentTypeResolver = contentTypeResolver;
this.adapterRegistry = adapterRegistry;
}
/**
* Return the configured {@link ReactiveAdapterRegistry}.
*/
public ReactiveAdapterRegistry getAdapterRegistry() {
return this.adapterRegistry;
}
/**
* Return the configured {@link RequestedContentTypeResolver}.
*/
public RequestedContentTypeResolver getContentTypeResolver() {
return this.contentTypeResolver;
}
/**
* Set the order for this result handler relative to others.
* <p>By default set to {@link Ordered#LOWEST_PRECEDENCE}, however see
* Javadoc of sub-clreplacedes which may change this default.
* @param order the order
*/
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
return this.order;
}
/**
* Get a {@code ReactiveAdapter} for the top-level return value type.
* @return the matching adapter, or {@code null} if none
*/
@Nullable
protected ReactiveAdapter getAdapter(HandlerResult result) {
return getAdapterRegistry().getAdapter(result.getReturnType().resolve(), result.getReturnValue());
}
/**
* Select the best media type for the current request through a content negotiation algorithm.
* @param exchange the current request
* @param producibleTypesSupplier the media types that can be produced for the current request
* @return the selected media type, or {@code null} if none
*/
@Nullable
protected MediaType selectMediaType(ServerWebExchange exchange, Supplier<List<MediaType>> producibleTypesSupplier) {
MediaType contentType = exchange.getResponse().getHeaders().getContentType();
if (contentType != null && contentType.isConcrete()) {
if (logger.isDebugEnabled()) {
logger.debug(exchange.getLogPrefix() + "Found 'Content-Type:" + contentType + "' in response");
}
return contentType;
}
List<MediaType> acceptableTypes = getAcceptableTypes(exchange);
List<MediaType> producibleTypes = getProducibleTypes(exchange, producibleTypesSupplier);
Set<MediaType> compatibleMediaTypes = new LinkedHashSet<>();
for (MediaType acceptable : acceptableTypes) {
for (MediaType producible : producibleTypes) {
if (acceptable.isCompatibleWith(producible)) {
compatibleMediaTypes.add(selectMoreSpecificMediaType(acceptable, producible));
}
}
}
List<MediaType> result = new ArrayList<>(compatibleMediaTypes);
MediaType.sortBySpecificityAndQuality(result);
MediaType selected = null;
for (MediaType mediaType : result) {
if (mediaType.isConcrete()) {
selected = mediaType;
break;
} else if (mediaType.isPresentIn(ALL_APPLICATION_MEDIA_TYPES)) {
selected = MediaType.APPLICATION_OCTET_STREAM;
break;
}
}
if (selected != null) {
if (logger.isDebugEnabled()) {
logger.debug("Using '" + selected + "' given " + acceptableTypes + " and supported " + producibleTypes);
}
} else if (logger.isDebugEnabled()) {
logger.debug(exchange.getLogPrefix() + "No match for " + acceptableTypes + ", supported: " + producibleTypes);
}
return selected;
}
private List<MediaType> getAcceptableTypes(ServerWebExchange exchange) {
return getContentTypeResolver().resolveMediaTypes(exchange);
}
private List<MediaType> getProducibleTypes(ServerWebExchange exchange, Supplier<List<MediaType>> producibleTypesSupplier) {
Set<MediaType> mediaTypes = exchange.getAttribute(HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE);
return (mediaTypes != null ? new ArrayList<>(mediaTypes) : producibleTypesSupplier.get());
}
private MediaType selectMoreSpecificMediaType(MediaType acceptable, MediaType producible) {
producible = producible.copyQualityValue(acceptable);
Comparator<MediaType> comparator = MediaType.SPECIFICITY_COMPARATOR;
return (comparator.compare(acceptable, producible) <= 0 ? acceptable : producible);
}
}
16
View Source File : InvocableHelper.java
License : MIT License
Project Creator : Vip-Augus
License : MIT License
Project Creator : Vip-Augus
/**
* Help to initialize and invoke an {@link InvocableHandlerMethod}, and to then
* apply return value handling and exception handling. Holds all necessary
* configuration necessary to do so.
*
* @author Rossen Stoyanchev
* @since 5.2
*/
clreplaced InvocableHelper {
private static Log logger = LogFactory.getLog(InvocableHelper.clreplaced);
private final HandlerMethodArgumentResolverComposite argumentResolvers = new HandlerMethodArgumentResolverComposite();
private final HandlerMethodReturnValueHandlerComposite returnValueHandlers = new HandlerMethodReturnValueHandlerComposite();
private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
private final Function<Clreplaced<?>, AbstractExceptionHandlerMethodResolver> exceptionMethodResolverFactory;
private final Map<Clreplaced<?>, AbstractExceptionHandlerMethodResolver> exceptionHandlerCache = new ConcurrentHashMap<>(64);
private final Map<MessagingAdviceBean, AbstractExceptionHandlerMethodResolver> exceptionHandlerAdviceCache = new LinkedHashMap<>(64);
public InvocableHelper(Function<Clreplaced<?>, AbstractExceptionHandlerMethodResolver> exceptionMethodResolverFactory) {
this.exceptionMethodResolverFactory = exceptionMethodResolverFactory;
}
/**
* Add the arguments resolvers to use for message handling and exception
* handling methods.
*/
public void addArgumentResolvers(List<? extends HandlerMethodArgumentResolver> resolvers) {
this.argumentResolvers.addResolvers(resolvers);
}
/**
* Add the return value handlers to use for message handling and exception
* handling methods.
*/
public void addReturnValueHandlers(List<? extends HandlerMethodReturnValueHandler> handlers) {
this.returnValueHandlers.addHandlers(handlers);
}
/**
* Configure the registry for adapting various reactive types.
* <p>By default this is an instance of {@link ReactiveAdapterRegistry} with
* default settings.
*/
public void setReactiveAdapterRegistry(ReactiveAdapterRegistry registry) {
replacedert.notNull(registry, "ReactiveAdapterRegistry is required");
this.reactiveAdapterRegistry = registry;
}
/**
* Return the configured registry for adapting reactive types.
*/
public ReactiveAdapterRegistry getReactiveAdapterRegistry() {
return this.reactiveAdapterRegistry;
}
/**
* Method to populate the MessagingAdviceBean cache (e.g. to support "global"
* {@code @MessageExceptionHandler}).
*/
public void registerExceptionHandlerAdvice(MessagingAdviceBean bean, AbstractExceptionHandlerMethodResolver resolver) {
this.exceptionHandlerAdviceCache.put(bean, resolver);
}
/**
* Create {@link InvocableHandlerMethod} with the configured arg resolvers.
* @param handlerMethod the target handler method to invoke
* @return the created instance
*/
public InvocableHandlerMethod initMessageMappingMethod(HandlerMethod handlerMethod) {
InvocableHandlerMethod invocable = new InvocableHandlerMethod(handlerMethod);
invocable.setArgumentResolvers(this.argumentResolvers.getResolvers());
return invocable;
}
/**
* Find an exception handling method for the given exception.
* <p>The default implementation searches methods in the clreplaced hierarchy of
* the HandlerMethod first and if not found, it continues searching for
* additional handling methods registered via
* {@link #registerExceptionHandlerAdvice}.
* @param handlerMethod the method where the exception was raised
* @param ex the exception raised or signaled
* @return a method to handle the exception, or {@code null}
*/
@Nullable
public InvocableHandlerMethod initExceptionHandlerMethod(HandlerMethod handlerMethod, Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Searching for methods to handle " + ex.getClreplaced().getSimpleName());
}
Clreplaced<?> beanType = handlerMethod.getBeanType();
AbstractExceptionHandlerMethodResolver resolver = this.exceptionHandlerCache.get(beanType);
if (resolver == null) {
resolver = this.exceptionMethodResolverFactory.apply(beanType);
this.exceptionHandlerCache.put(beanType, resolver);
}
InvocableHandlerMethod exceptionHandlerMethod = null;
Method method = resolver.resolveMethod(ex);
if (method != null) {
exceptionHandlerMethod = new InvocableHandlerMethod(handlerMethod.getBean(), method);
} else {
for (MessagingAdviceBean advice : this.exceptionHandlerAdviceCache.keySet()) {
if (advice.isApplicableToBeanType(beanType)) {
resolver = this.exceptionHandlerAdviceCache.get(advice);
method = resolver.resolveMethod(ex);
if (method != null) {
exceptionHandlerMethod = new InvocableHandlerMethod(advice.resolveBean(), method);
break;
}
}
}
}
if (exceptionHandlerMethod != null) {
logger.debug("Found exception handler " + exceptionHandlerMethod.getShortLogMessage());
exceptionHandlerMethod.setArgumentResolvers(this.argumentResolvers.getResolvers());
} else {
logger.error("No exception handling method", ex);
}
return exceptionHandlerMethod;
}
public Mono<Void> handleMessage(HandlerMethod handlerMethod, Message<?> message) {
InvocableHandlerMethod invocable = initMessageMappingMethod(handlerMethod);
if (logger.isDebugEnabled()) {
logger.debug("Invoking " + invocable.getShortLogMessage());
}
return invocable.invoke(message).switchIfEmpty(Mono.defer(() -> handleReturnValue(null, invocable, message))).flatMap(returnValue -> handleReturnValue(returnValue, invocable, message)).onErrorResume(ex -> {
InvocableHandlerMethod exHandler = initExceptionHandlerMethod(handlerMethod, ex);
if (exHandler == null) {
return Mono.error(ex);
}
if (logger.isDebugEnabled()) {
logger.debug("Invoking " + exHandler.getShortLogMessage());
}
return exHandler.invoke(message, ex).switchIfEmpty(Mono.defer(() -> handleReturnValue(null, exHandler, message))).flatMap(returnValue -> handleReturnValue(returnValue, exHandler, message));
});
}
private Mono<Void> handleReturnValue(@Nullable Object returnValue, HandlerMethod handlerMethod, Message<?> message) {
MethodParameter returnType = handlerMethod.getReturnType();
return this.returnValueHandlers.handleReturnValue(returnValue, returnType, message);
}
}
16
View Source File : ReactiveTypeHandlerTests.java
License : Apache License 2.0
Project Creator : SourceHot
License : Apache License 2.0
Project Creator : SourceHot
@BeforeEach
public void setup() throws Exception {
ContentNegotiationManagerFactoryBean factoryBean = new ContentNegotiationManagerFactoryBean();
factoryBean.afterPropertiesSet();
ContentNegotiationManager manager = factoryBean.getObject();
ReactiveAdapterRegistry adapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
this.handler = new ReactiveTypeHandler(adapterRegistry, new SyncTaskExecutor(), manager);
resetRequest();
}
See More Examples