private Object getErrors(MethodParameter parameter, BindingContext context) { Assert.isTrue(parameter.getParameterIndex() > 0, "Errors argument must be declared immediately after a model attribute argument"); int index = parameter.getParameterIndex() - 1; MethodParameter attributeParam = MethodParameter.forExecutable(parameter.getExecutable(), index); ReactiveAdapter adapter = getAdapterRegistry().getAdapter(attributeParam.getParameterType()); Assert.state(adapter == null, "An @ModelAttribute and an Errors/BindingResult argument " + "cannot both be declared with an async type wrapper. " + "Either declare the @ModelAttribute without an async wrapper type or " + "handle a WebExchangeBindException error signal through the async type."); ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.class); String name = (ann != null && StringUtils.hasText(ann.value()) ? ann.value() : Conventions.getVariableNameForParameter(attributeParam)); Object errors = context.getModel().asMap().get(BindingResult.MODEL_KEY_PREFIX + name); Assert.state(errors != null, () -> "An Errors/BindingResult argument is expected " + "immediately after the @ModelAttribute argument to which it applies. " + "For @RequestBody and @RequestPart arguments, please declare them with a reactive " + "type wrapper and use its onError operators to handle WebExchangeBindException: " + parameter.getMethod()); return errors; }
private String getModelAttributeName(MethodParameter parameter) { Assert.isTrue(parameter.getParameterIndex() > 0, "Errors argument must be immediately after a model attribute argument."); int index = parameter.getParameterIndex() - 1; MethodParameter attributeParam = new MethodParameter(parameter.getMethod(), index); Class<?> attributeType = attributeParam.getParameterType(); ResolvableType type = ResolvableType.forMethodParameter(attributeParam); ReactiveAdapter adapter = getAdapterRegistry().getAdapter(type.resolve()); Assert.isNull(adapter, "Errors/BindingResult cannot be used with an async model attribute. " + "Either declare the model attribute without the async wrapper type " + "or handle WebExchangeBindException through the async type."); ModelAttribute annot = parameter.getParameterAnnotation(ModelAttribute.class); if (annot != null && StringUtils.hasText(annot.value())) { return annot.value(); } // TODO: Conventions does not deal with async wrappers return ClassUtils.getShortNameAsProperty(attributeType); }