@Nullable private Object findAndRemoveReactiveAttribute(Model model, String attributeName) { return model.asMap().entrySet().stream() .filter(entry -> { if (!entry.getKey().startsWith(attributeName)) { return false; } ReactiveAdapter adapter = getAdapterRegistry().getAdapter(null, entry.getValue()); if (adapter == null) { return false; } String name = attributeName + ClassUtils.getShortName(adapter.getReactiveType()); return entry.getKey().equals(name); }) .findFirst() .map(entry -> { // Remove since we will be re-inserting the resolved attribute value model.asMap().remove(entry.getKey()); return entry.getValue(); }) .orElse(null); }
private Mono<?> prepareAttributeMono(String attributeName, ResolvableType attributeType, BindingContext context, ServerWebExchange exchange) { Object attribute = context.getModel().asMap().get(attributeName); if (attribute == null) { attribute = findAndRemoveReactiveAttribute(context.getModel(), attributeName); } if (attribute == null) { return createAttribute(attributeName, attributeType.toClass(), context, exchange); } ReactiveAdapter adapterFrom = getAdapterRegistry().getAdapter(null, attribute); if (adapterFrom != null) { Assert.isTrue(!adapterFrom.isMultiValue(), "Data binding only supports single-value async types"); return Mono.from(adapterFrom.toPublisher(attribute)); } else { return Mono.justOrEmpty(attribute); } }
ReactiveAdapter adapter = (resolvedType != null ? getAdapterRegistry().getAdapter(resolvedType) : null); ResolvableType valueType = (adapter != null ? type.getGeneric() : type);
private Mono<?> getAttributeMono(String attributeName, Class<?> attributeType, MethodParameter param, BindingContext context, ServerWebExchange exchange) { Object attribute = context.getModel().asMap().get(attributeName); if (attribute == null) { attribute = createAttribute(attributeName, attributeType, param, context, exchange); } if (attribute != null) { ReactiveAdapter adapterFrom = getAdapterRegistry().getAdapter(null, attribute); if (adapterFrom != null) { Assert.isTrue(!adapterFrom.isMultiValue(), "Data binding supports single-value async types."); return Mono.from(adapterFrom.toPublisher(attribute)); } } return Mono.justOrEmpty(attribute); }
@Override public boolean supportsParameter(MethodParameter parameter) { if (parameter.hasParameterAnnotation(ModelAttribute.class)) { return true; } if (this.useDefaultResolution) { Class<?> clazz = parameter.getParameterType(); ReactiveAdapter adapter = getAdapterRegistry().getAdapter(clazz); if (adapter != null) { if (adapter.isNoValue() || adapter.isMultiValue()) { return false; } clazz = ResolvableType.forMethodParameter(parameter).getGeneric(0).getRawClass(); } return !BeanUtils.isSimpleProperty(clazz); } return false; }
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type.resolve()); Class<?> valueType = (adapter != null ? type.resolveGeneric(0) : parameter.getParameterType()); String name = getAttributeName(valueType, parameter);