DataBinder unwraps Optional objects and allows for proper handling of Optional.empty()

Issue: SPR-12241
This commit is contained in:
Juergen Hoeller
2014-09-25 17:00:36 +02:00
parent 070642c148
commit cfc821d179
4 changed files with 151 additions and 37 deletions

View File

@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -41,7 +42,9 @@ import org.springframework.beans.TypeConverter;
import org.springframework.beans.TypeMismatchException;
import org.springframework.core.MethodParameter;
import org.springframework.core.convert.ConversionService;
import org.springframework.lang.UsesJava8;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.PatternMatchUtils;
import org.springframework.util.StringUtils;
@@ -119,6 +122,19 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
*/
protected static final Log logger = LogFactory.getLog(DataBinder.class);
private static Class<?> javaUtilOptionalClass = null;
static {
try {
javaUtilOptionalClass =
ClassUtils.forName("java.util.Optional", DataBinder.class.getClassLoader());
}
catch (ClassNotFoundException ex) {
// Java 8 not available - Optional references simply not supported then.
}
}
private final Object target;
private final String objectName;
@@ -165,7 +181,12 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
* @param objectName the name of the target object
*/
public DataBinder(Object target, String objectName) {
this.target = target;
if (target != null && target.getClass().equals(javaUtilOptionalClass)) {
this.target = OptionalUnwrapper.unwrap(target);
}
else {
this.target = target;
}
this.objectName = objectName;
}
@@ -779,4 +800,22 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
return getBindingResult().getModel();
}
/**
* Inner class to avoid a hard dependency on Java 8.
*/
@UsesJava8
private static class OptionalUnwrapper {
public static Object unwrap(Object optionalObject) {
Optional<?> optional = (Optional<?>) optionalObject;
if (!optional.isPresent()) {
return null;
}
Object result = optional.get();
Assert.isTrue(!(result instanceof Optional), "Multi-level Optional usage not supported");
return result;
}
}
}