List of usage examples for org.springframework.web.bind WebDataBinder getFieldMarkerPrefix
@Nullable
public String getFieldMarkerPrefix()
From source file:org.springframework.web.method.annotation.ModelAttributeMethodProcessor.java
/** * Construct a new attribute instance with the given constructor. * <p>Called from/*from w ww .j a v a 2 s . c o m*/ * {@link #createAttribute(String, MethodParameter, WebDataBinderFactory, NativeWebRequest)} * after constructor resolution. * @param ctor the constructor to use * @param attributeName the name of the attribute (never {@code null}) * @param binderFactory for creating WebDataBinder instance * @param webRequest the current request * @return the created model attribute (never {@code null}) * @throws BindException in case of constructor argument binding failure * @throws Exception in case of constructor invocation failure * @since 5.0 */ protected Object constructAttribute(Constructor<?> ctor, String attributeName, WebDataBinderFactory binderFactory, NativeWebRequest webRequest) throws Exception { if (ctor.getParameterCount() == 0) { // A single default constructor -> clearly a standard JavaBeans arrangement. return BeanUtils.instantiateClass(ctor); } // A single data class constructor -> resolve constructor arguments from request parameters. ConstructorProperties cp = ctor.getAnnotation(ConstructorProperties.class); String[] paramNames = (cp != null ? cp.value() : parameterNameDiscoverer.getParameterNames(ctor)); Assert.state(paramNames != null, () -> "Cannot resolve parameter names for constructor " + ctor); Class<?>[] paramTypes = ctor.getParameterTypes(); Assert.state(paramNames.length == paramTypes.length, () -> "Invalid number of parameter names: " + paramNames.length + " for constructor " + ctor); Object[] args = new Object[paramTypes.length]; WebDataBinder binder = binderFactory.createBinder(webRequest, null, attributeName); String fieldDefaultPrefix = binder.getFieldDefaultPrefix(); String fieldMarkerPrefix = binder.getFieldMarkerPrefix(); boolean bindingFailure = false; for (int i = 0; i < paramNames.length; i++) { String paramName = paramNames[i]; Class<?> paramType = paramTypes[i]; Object value = webRequest.getParameterValues(paramName); if (value == null) { if (fieldDefaultPrefix != null) { value = webRequest.getParameter(fieldDefaultPrefix + paramName); } if (value == null && fieldMarkerPrefix != null) { if (webRequest.getParameter(fieldMarkerPrefix + paramName) != null) { value = binder.getEmptyValue(paramType); } } } try { MethodParameter methodParam = new MethodParameter(ctor, i); if (value == null && methodParam.isOptional()) { args[i] = (methodParam.getParameterType() == Optional.class ? Optional.empty() : null); } else { args[i] = binder.convertIfNecessary(value, paramType, methodParam); } } catch (TypeMismatchException ex) { ex.initPropertyName(paramName); binder.getBindingErrorProcessor().processPropertyAccessException(ex, binder.getBindingResult()); bindingFailure = true; args[i] = value; } } if (bindingFailure) { if (binder.getBindingResult() instanceof AbstractBindingResult) { AbstractBindingResult result = (AbstractBindingResult) binder.getBindingResult(); for (int i = 0; i < paramNames.length; i++) { result.recordFieldValue(paramNames[i], paramTypes[i], args[i]); } } throw new BindException(binder.getBindingResult()); } return BeanUtils.instantiateClass(ctor, args); }