Search in sources :

Example 56 with ModelAttribute

use of org.springframework.web.bind.annotation.ModelAttribute in project spring-framework by spring-projects.

the class ModelAttributeMethodProcessor method resolveArgument.

/**
 * Resolve the argument from the model or if not found instantiate it with
 * its default if it is available. The model attribute is then populated
 * with request values via data binding and optionally validated
 * if {@code @java.validation.Valid} is present on the argument.
 * @throws BindException if data binding and validation result in an error
 * and the next method parameter is not of type {@link Errors}
 * @throws Exception if WebDataBinder initialization fails
 */
@Override
@Nullable
public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
    Assert.state(mavContainer != null, "ModelAttributeMethodProcessor requires ModelAndViewContainer");
    Assert.state(binderFactory != null, "ModelAttributeMethodProcessor requires WebDataBinderFactory");
    String name = ModelFactory.getNameForParameter(parameter);
    ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.class);
    if (ann != null) {
        mavContainer.setBinding(name, ann.binding());
    }
    Object attribute = null;
    BindingResult bindingResult = null;
    if (mavContainer.containsAttribute(name)) {
        attribute = mavContainer.getModel().get(name);
    } else {
        // Create attribute instance
        try {
            attribute = createAttribute(name, parameter, binderFactory, webRequest);
        } catch (BindException ex) {
            if (isBindExceptionRequired(parameter)) {
                // No BindingResult parameter -> fail with BindException
                throw ex;
            }
            // Otherwise, expose null/empty value and associated BindingResult
            if (parameter.getParameterType() == Optional.class) {
                attribute = Optional.empty();
            } else {
                attribute = ex.getTarget();
            }
            bindingResult = ex.getBindingResult();
        }
    }
    if (bindingResult == null) {
        // Bean property binding and validation;
        // skipped in case of binding failure on construction.
        WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
        if (binder.getTarget() != null) {
            if (!mavContainer.isBindingDisabled(name)) {
                bindRequestParameters(binder, webRequest);
            }
            validateIfApplicable(binder, parameter);
            if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
                throw new BindException(binder.getBindingResult());
            }
        }
        // Value type adaptation, also covering java.util.Optional
        if (!parameter.getParameterType().isInstance(attribute)) {
            attribute = binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter);
        }
        bindingResult = binder.getBindingResult();
    }
    // Add resolved attribute and BindingResult at the end of the model
    Map<String, Object> bindingResultModel = bindingResult.getModel();
    mavContainer.removeAttributes(bindingResultModel);
    mavContainer.addAllAttributes(bindingResultModel);
    return attribute;
}
Also used : WebDataBinder(org.springframework.web.bind.WebDataBinder) BindingResult(org.springframework.validation.BindingResult) Optional(java.util.Optional) ModelAttribute(org.springframework.web.bind.annotation.ModelAttribute) BindException(org.springframework.validation.BindException) Nullable(org.springframework.lang.Nullable)

Example 57 with ModelAttribute

use of org.springframework.web.bind.annotation.ModelAttribute in project spring-framework by spring-projects.

the class ModelFactory method getNameForParameter.

/**
 * 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.class);
    String name = (ann != null ? ann.value() : null);
    return (StringUtils.hasText(name) ? name : Conventions.getVariableNameForParameter(parameter));
}
Also used : ModelAttribute(org.springframework.web.bind.annotation.ModelAttribute)

Example 58 with ModelAttribute

use of org.springframework.web.bind.annotation.ModelAttribute in project spring-framework by spring-projects.

the class ModelFactory method invokeModelAttributeMethods.

/**
 * Invoke model attribute methods to populate the model.
 * Attributes are added only if not already present in the model.
 */
private void invokeModelAttributeMethods(NativeWebRequest request, ModelAndViewContainer container) throws Exception {
    while (!this.modelMethods.isEmpty()) {
        InvocableHandlerMethod modelMethod = getNextModelMethod(container).getHandlerMethod();
        ModelAttribute ann = modelMethod.getMethodAnnotation(ModelAttribute.class);
        Assert.state(ann != null, "No ModelAttribute annotation");
        if (container.containsAttribute(ann.name())) {
            if (!ann.binding()) {
                container.setBindingDisabled(ann.name());
            }
            continue;
        }
        Object returnValue = modelMethod.invokeForRequest(request, container);
        if (modelMethod.isVoid()) {
            if (StringUtils.hasText(ann.value())) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Name in @ModelAttribute is ignored because method returns void: " + modelMethod.getShortLogMessage());
                }
            }
            continue;
        }
        String returnValueName = getNameForReturnValue(returnValue, modelMethod.getReturnType());
        if (!ann.binding()) {
            container.setBindingDisabled(returnValueName);
        }
        if (!container.containsAttribute(returnValueName)) {
            container.addAttribute(returnValueName, returnValue);
        }
    }
}
Also used : InvocableHandlerMethod(org.springframework.web.method.support.InvocableHandlerMethod) ModelAttribute(org.springframework.web.bind.annotation.ModelAttribute)

Example 59 with ModelAttribute

use of org.springframework.web.bind.annotation.ModelAttribute in project spring-framework by spring-projects.

the class ModelFactory method getNameForReturnValue.

/**
 * Derive the model attribute name for the given return value. Results will be
 * based on:
 * <ol>
 * <li>the method {@code ModelAttribute} annotation value
 * <li>the declared return type if it is more specific than {@code Object}
 * <li>the actual return value type
 * </ol>
 * @param returnValue the value returned from a method invocation
 * @param returnType a descriptor for the return type of the method
 * @return the derived name (never {@code null} or empty String)
 */
public static String getNameForReturnValue(@Nullable Object returnValue, MethodParameter returnType) {
    ModelAttribute ann = returnType.getMethodAnnotation(ModelAttribute.class);
    if (ann != null && StringUtils.hasText(ann.value())) {
        return ann.value();
    } else {
        Method method = returnType.getMethod();
        Assert.state(method != null, "No handler method");
        Class<?> containingClass = returnType.getContainingClass();
        Class<?> resolvedType = GenericTypeResolver.resolveReturnType(method, containingClass);
        return Conventions.getVariableNameForReturnType(method, resolvedType, returnValue);
    }
}
Also used : ModelAttribute(org.springframework.web.bind.annotation.ModelAttribute) InvocableHandlerMethod(org.springframework.web.method.support.InvocableHandlerMethod) HandlerMethod(org.springframework.web.method.HandlerMethod) Method(java.lang.reflect.Method)

Aggregations

ModelAttribute (org.springframework.web.bind.annotation.ModelAttribute)59 RequestMapping (org.springframework.web.bind.annotation.RequestMapping)19 IOException (java.io.IOException)7 Valid (javax.validation.Valid)6 RequestMethod (org.springframework.web.bind.annotation.RequestMethod)6 SimpleDateFormat (java.text.SimpleDateFormat)5 LinkedHashMap (java.util.LinkedHashMap)5 HttpSession (javax.servlet.http.HttpSession)5 Autowired (org.springframework.beans.factory.annotation.Autowired)5 Sort (org.springframework.data.domain.Sort)5 FileNotFoundException (java.io.FileNotFoundException)4 DateFormat (java.text.DateFormat)4 java.util (java.util)4 Callable (java.util.concurrent.Callable)4 ExecutionException (java.util.concurrent.ExecutionException)4 ExecutorService (java.util.concurrent.ExecutorService)4 Executors (java.util.concurrent.Executors)4 Future (java.util.concurrent.Future)4 TimeUnit (java.util.concurrent.TimeUnit)4 PreDestroy (javax.annotation.PreDestroy)4