001/* 002 * Copyright 2002-2014 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.method.annotation; 018 019import java.util.ArrayList; 020 021import org.springframework.core.MethodParameter; 022import org.springframework.ui.ModelMap; 023import org.springframework.validation.BindingResult; 024import org.springframework.validation.Errors; 025import org.springframework.web.bind.support.WebDataBinderFactory; 026import org.springframework.web.context.request.NativeWebRequest; 027import org.springframework.web.method.support.HandlerMethodArgumentResolver; 028import org.springframework.web.method.support.ModelAndViewContainer; 029 030/** 031 * Resolves {@link Errors} method arguments. 032 * 033 * <p>An {@code Errors} method argument is expected to appear immediately after 034 * the model attribute in the method signature. It is resolved by expecting the 035 * last two attributes added to the model to be the model attribute and its 036 * {@link BindingResult}. 037 * 038 * @author Rossen Stoyanchev 039 * @since 3.1 040 */ 041public class ErrorsMethodArgumentResolver implements HandlerMethodArgumentResolver { 042 043 @Override 044 public boolean supportsParameter(MethodParameter parameter) { 045 Class<?> paramType = parameter.getParameterType(); 046 return Errors.class.isAssignableFrom(paramType); 047 } 048 049 @Override 050 public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, 051 NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { 052 053 ModelMap model = mavContainer.getModel(); 054 if (model.size() > 0) { 055 int lastIndex = model.size()-1; 056 String lastKey = new ArrayList<String>(model.keySet()).get(lastIndex); 057 if (lastKey.startsWith(BindingResult.MODEL_KEY_PREFIX)) { 058 return model.get(lastKey); 059 } 060 } 061 062 throw new IllegalStateException( 063 "An Errors/BindingResult argument is expected to be declared immediately after the model attribute, " + 064 "the @RequestBody or the @RequestPart arguments to which they apply: " + parameter.getMethod()); 065 } 066 067}