001/* 002 * Copyright 2002-2020 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.bind.support; 018 019import java.beans.PropertyEditor; 020import java.util.List; 021import java.util.Map; 022 023import org.springframework.beans.PropertyEditorRegistry; 024import org.springframework.core.MethodParameter; 025import org.springframework.lang.Nullable; 026import org.springframework.util.Assert; 027import org.springframework.validation.BeanPropertyBindingResult; 028import org.springframework.validation.BindingResult; 029import org.springframework.validation.Errors; 030import org.springframework.validation.FieldError; 031import org.springframework.validation.ObjectError; 032import org.springframework.web.server.ServerWebInputException; 033 034/** 035 * A specialization of {@link ServerWebInputException} thrown when after data 036 * binding and validation failure. Implements {@link BindingResult} (and its 037 * super-interface {@link Errors}) to allow for direct analysis of binding and 038 * validation errors. 039 * 040 * @author Rossen Stoyanchev 041 * @since 5.0 042 */ 043@SuppressWarnings("serial") 044public class WebExchangeBindException extends ServerWebInputException implements BindingResult { 045 046 private final BindingResult bindingResult; 047 048 049 public WebExchangeBindException(MethodParameter parameter, BindingResult bindingResult) { 050 super("Validation failure", parameter); 051 this.bindingResult = bindingResult; 052 } 053 054 055 /** 056 * Return the BindingResult that this BindException wraps. 057 * Will typically be a BeanPropertyBindingResult. 058 * @see BeanPropertyBindingResult 059 */ 060 public final BindingResult getBindingResult() { 061 return this.bindingResult; 062 } 063 064 065 @Override 066 public String getObjectName() { 067 return this.bindingResult.getObjectName(); 068 } 069 070 @Override 071 public void setNestedPath(String nestedPath) { 072 this.bindingResult.setNestedPath(nestedPath); 073 } 074 075 @Override 076 public String getNestedPath() { 077 return this.bindingResult.getNestedPath(); 078 } 079 080 @Override 081 public void pushNestedPath(String subPath) { 082 this.bindingResult.pushNestedPath(subPath); 083 } 084 085 @Override 086 public void popNestedPath() throws IllegalStateException { 087 this.bindingResult.popNestedPath(); 088 } 089 090 091 @Override 092 public void reject(String errorCode) { 093 this.bindingResult.reject(errorCode); 094 } 095 096 @Override 097 public void reject(String errorCode, String defaultMessage) { 098 this.bindingResult.reject(errorCode, defaultMessage); 099 } 100 101 @Override 102 public void reject(String errorCode, @Nullable Object[] errorArgs, @Nullable String defaultMessage) { 103 this.bindingResult.reject(errorCode, errorArgs, defaultMessage); 104 } 105 106 @Override 107 public void rejectValue(@Nullable String field, String errorCode) { 108 this.bindingResult.rejectValue(field, errorCode); 109 } 110 111 @Override 112 public void rejectValue(@Nullable String field, String errorCode, String defaultMessage) { 113 this.bindingResult.rejectValue(field, errorCode, defaultMessage); 114 } 115 116 @Override 117 public void rejectValue( 118 @Nullable String field, String errorCode, @Nullable Object[] errorArgs, @Nullable String defaultMessage) { 119 120 this.bindingResult.rejectValue(field, errorCode, errorArgs, defaultMessage); 121 } 122 123 @Override 124 public void addAllErrors(Errors errors) { 125 this.bindingResult.addAllErrors(errors); 126 } 127 128 129 @Override 130 public boolean hasErrors() { 131 return this.bindingResult.hasErrors(); 132 } 133 134 @Override 135 public int getErrorCount() { 136 return this.bindingResult.getErrorCount(); 137 } 138 139 @Override 140 public List<ObjectError> getAllErrors() { 141 return this.bindingResult.getAllErrors(); 142 } 143 144 @Override 145 public boolean hasGlobalErrors() { 146 return this.bindingResult.hasGlobalErrors(); 147 } 148 149 @Override 150 public int getGlobalErrorCount() { 151 return this.bindingResult.getGlobalErrorCount(); 152 } 153 154 @Override 155 public List<ObjectError> getGlobalErrors() { 156 return this.bindingResult.getGlobalErrors(); 157 } 158 159 @Override 160 @Nullable 161 public ObjectError getGlobalError() { 162 return this.bindingResult.getGlobalError(); 163 } 164 165 @Override 166 public boolean hasFieldErrors() { 167 return this.bindingResult.hasFieldErrors(); 168 } 169 170 @Override 171 public int getFieldErrorCount() { 172 return this.bindingResult.getFieldErrorCount(); 173 } 174 175 @Override 176 public List<FieldError> getFieldErrors() { 177 return this.bindingResult.getFieldErrors(); 178 } 179 180 @Override 181 @Nullable 182 public FieldError getFieldError() { 183 return this.bindingResult.getFieldError(); 184 } 185 186 @Override 187 public boolean hasFieldErrors(String field) { 188 return this.bindingResult.hasFieldErrors(field); 189 } 190 191 @Override 192 public int getFieldErrorCount(String field) { 193 return this.bindingResult.getFieldErrorCount(field); 194 } 195 196 @Override 197 public List<FieldError> getFieldErrors(String field) { 198 return this.bindingResult.getFieldErrors(field); 199 } 200 201 @Override 202 @Nullable 203 public FieldError getFieldError(String field) { 204 return this.bindingResult.getFieldError(field); 205 } 206 207 @Override 208 @Nullable 209 public Object getFieldValue(String field) { 210 return this.bindingResult.getFieldValue(field); 211 } 212 213 @Override 214 @Nullable 215 public Class<?> getFieldType(String field) { 216 return this.bindingResult.getFieldType(field); 217 } 218 219 @Override 220 @Nullable 221 public Object getTarget() { 222 return this.bindingResult.getTarget(); 223 } 224 225 @Override 226 public Map<String, Object> getModel() { 227 return this.bindingResult.getModel(); 228 } 229 230 @Override 231 @Nullable 232 public Object getRawFieldValue(String field) { 233 return this.bindingResult.getRawFieldValue(field); 234 } 235 236 @Override 237 @SuppressWarnings("rawtypes") 238 @Nullable 239 public PropertyEditor findEditor(@Nullable String field, @Nullable Class valueType) { 240 return this.bindingResult.findEditor(field, valueType); 241 } 242 243 @Override 244 @Nullable 245 public PropertyEditorRegistry getPropertyEditorRegistry() { 246 return this.bindingResult.getPropertyEditorRegistry(); 247 } 248 249 @Override 250 public String[] resolveMessageCodes(String errorCode) { 251 return this.bindingResult.resolveMessageCodes(errorCode); 252 } 253 254 @Override 255 public String[] resolveMessageCodes(String errorCode, String field) { 256 return this.bindingResult.resolveMessageCodes(errorCode, field); 257 } 258 259 @Override 260 public void addError(ObjectError error) { 261 this.bindingResult.addError(error); 262 } 263 264 @Override 265 public void recordFieldValue(String field, Class<?> type, @Nullable Object value) { 266 this.bindingResult.recordFieldValue(field, type, value); 267 } 268 269 @Override 270 public void recordSuppressedField(String field) { 271 this.bindingResult.recordSuppressedField(field); 272 } 273 274 @Override 275 public String[] getSuppressedFields() { 276 return this.bindingResult.getSuppressedFields(); 277 } 278 279 280 /** 281 * Returns diagnostic information about the errors held in this object. 282 */ 283 @Override 284 public String getMessage() { 285 MethodParameter parameter = getMethodParameter(); 286 Assert.state(parameter != null, "No MethodParameter"); 287 StringBuilder sb = new StringBuilder("Validation failed for argument at index ") 288 .append(parameter.getParameterIndex()).append(" in method: ") 289 .append(parameter.getExecutable().toGenericString()) 290 .append(", with ").append(this.bindingResult.getErrorCount()).append(" error(s): "); 291 for (ObjectError error : this.bindingResult.getAllErrors()) { 292 sb.append("[").append(error).append("] "); 293 } 294 return sb.toString(); 295 } 296 297 @Override 298 public boolean equals(@Nullable Object other) { 299 return (this == other || this.bindingResult.equals(other)); 300 } 301 302 @Override 303 public int hashCode() { 304 return this.bindingResult.hashCode(); 305 } 306 307}