diff --git a/pom.xml b/pom.xml
index 19255544a..e3fdc5362 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,6 +17,7 @@
DATACMNS
+ 2.0.4
2.11.7
1.4.8
@@ -143,6 +144,13 @@
true
+
+ io.javaslang
+ javaslang
+ ${javaslang}
+ true
+
+
javax.el
el-api
diff --git a/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java b/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java
index e8f57d04d..9acc89cfe 100644
--- a/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java
+++ b/src/main/java/org/springframework/data/repository/util/QueryExecutionConverters.java
@@ -19,11 +19,13 @@ import scala.Function0;
import scala.Option;
import scala.runtime.AbstractFunction0;
+import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
+import java.util.function.Supplier;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
@@ -33,6 +35,7 @@ import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
+import org.springframework.util.ReflectionUtils;
import org.springframework.util.concurrent.ListenableFuture;
import com.google.common.base.Optional;
@@ -43,10 +46,11 @@ import com.google.common.base.Optional;
*
* - {@code java.util.Optional}
* - {@code com.google.common.base.Optional}
- * - {@code scala.Option}
+ * - {@code scala.Option} - as of 1.12
* - {@code java.util.concurrent.Future}
* - {@code java.util.concurrent.CompletableFuture}
* - {@code org.springframework.util.concurrent.ListenableFuture<}
+ * - {@code javaslang.control.Option} - as of 1.13
*
*
* @author Oliver Gierke
@@ -65,6 +69,8 @@ public abstract class QueryExecutionConverters {
QueryExecutionConverters.class.getClassLoader());
private static final boolean SCALA_PRESENT = ClassUtils.isPresent("scala.Option",
QueryExecutionConverters.class.getClassLoader());
+ private static final boolean JAVASLANG_PRESENT = ClassUtils.isPresent("javaslang.control.Option",
+ QueryExecutionConverters.class.getClassLoader());
private static final Set> WRAPPER_TYPES = new HashSet>();
private static final Set> UNWRAPPERS = new HashSet>();
@@ -92,6 +98,11 @@ public abstract class QueryExecutionConverters {
WRAPPER_TYPES.add(NullableWrapperToScalaOptionConverter.getWrapperType());
UNWRAPPERS.add(ScalOptionUnwrapper.INSTANCE);
}
+
+ if (JAVASLANG_PRESENT) {
+ WRAPPER_TYPES.add(NullableWrapperToJavaSlangOptionConverter.getWrapperType());
+ UNWRAPPERS.add(JavaSlangOptionUnwrapper.INSTANCE);
+ }
}
private QueryExecutionConverters() {}
@@ -137,6 +148,10 @@ public abstract class QueryExecutionConverters {
conversionService.addConverter(new NullableWrapperToScalaOptionConverter(conversionService));
}
+ if (JAVASLANG_PRESENT) {
+ conversionService.addConverter(new NullableWrapperToJavaSlangOptionConverter(conversionService));
+ }
+
conversionService.addConverter(new NullableWrapperToFutureConverter(conversionService));
}
@@ -375,6 +390,51 @@ public abstract class QueryExecutionConverters {
}
}
+ /**
+ * Converter to convert from {@link NullableWrapper} into JavaSlang's {@link javaslang.control.Option}.
+ *
+ * @author Oliver Gierke
+ * @since 1.13
+ */
+ private static class NullableWrapperToJavaSlangOptionConverter extends AbstractWrapperTypeConverter {
+
+ private static final Method OF_METHOD;
+ private static final Method NONE_METHOD;
+
+ static {
+ OF_METHOD = ReflectionUtils.findMethod(getWrapperType(), "of", Object.class);
+ NONE_METHOD = ReflectionUtils.findMethod(getWrapperType(), "none");
+ }
+
+ /**
+ * Creates a new {@link NullableWrapperToJavaSlangOptionConverter} using the given {@link ConversionService}.
+ *
+ * @param conversionService must not be {@literal null}.
+ */
+ public NullableWrapperToJavaSlangOptionConverter(ConversionService conversionService) {
+ super(conversionService, createEmptyOption(), getWrapperType());
+ }
+
+ public static Class> getWrapperType() {
+ return javaslang.control.Option.class;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.util.QueryExecutionConverters.AbstractWrapperTypeConverter#wrap(java.lang.Object)
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ protected Object wrap(Object source) {
+ return (javaslang.control.Option