diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java
index df7daa65b..7daeb33bf 100644
--- a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProvider.java
@@ -36,8 +36,6 @@ public class PersistentEntityParameterValueProvider
provider;
private final Object parent;
- private SpELExpressionEvaluator spELEvaluator;
-
/**
* Creates a new {@link PersistentEntityParameterValueProvider} for the given {@link PersistentEntity} and
* {@link PropertyValueProvider}.
@@ -57,16 +55,6 @@ public class PersistentEntityParameterValueProvider
T getParameterValue(Parameter parameter) {
- if (spELEvaluator != null && parameter.hasSpelExpression()) {
- return spELEvaluator.evaluate(parameter.getSpelExpression());
- }
-
PreferredConstructor, P> constructor = entity.getPersistenceConstructor();
if (constructor.isEnclosingClassParameter(parameter)) {
diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/SpELExpressionParameterValueProvider.java b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/SpELExpressionParameterValueProvider.java
new file mode 100644
index 000000000..a20a11366
--- /dev/null
+++ b/spring-data-commons-core/src/main/java/org/springframework/data/mapping/model/SpELExpressionParameterValueProvider.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.mapping.model;
+
+import org.springframework.core.convert.ConversionService;
+import org.springframework.data.mapping.PersistentProperty;
+import org.springframework.data.mapping.PreferredConstructor.Parameter;
+import org.springframework.util.Assert;
+
+/**
+ * {@link ParameterValueProvider} that can be used to front a {@link ParameterValueProvider} delegate to prefer a Spel
+ * expression evaluation over directly resolving the parameter value with the delegate.
+ *
+ * @author Oliver Gierke
+ */
+public class SpELExpressionParameterValueProvider
> implements ParameterValueProvider
{
+
+ private final SpELExpressionEvaluator evaluator;
+ private final ParameterValueProvider
delegate;
+ private final ConversionService conversionService;
+
+ /**
+ * Creates a new {@link SpELExpressionParameterValueProvider} using the given {@link SpELExpressionEvaluator},
+ * {@link ConversionService} and {@link ParameterValueProvider} delegate to forward calls to, that resolve parameters
+ * that do not have a Spel expression configured with them.
+ *
+ * @param evaluator must not be {@literal null}.
+ * @param conversionService must not be {@literal null}.
+ * @param delegate must not be {@literal null}.
+ */
+ public SpELExpressionParameterValueProvider(SpELExpressionEvaluator evaluator, ConversionService conversionService,
+ ParameterValueProvider
delegate) {
+
+ Assert.notNull(evaluator, "SpELExpressionEvaluator must not be null!");
+ Assert.notNull(conversionService, "ConversionService must not be null!");
+ Assert.notNull(delegate, "ParameterValueProvider delegate must not be null!");
+
+ this.evaluator = evaluator;
+ this.conversionService = conversionService;
+ this.delegate = delegate;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.mapping.model.ParameterValueProvider#getParameterValue(org.springframework.data.mapping.PreferredConstructor.Parameter)
+ */
+ public T getParameterValue(Parameter parameter) {
+
+ if (!parameter.hasSpelExpression()) {
+ return delegate == null ? null : delegate.getParameterValue(parameter);
+ }
+
+ Object object = evaluator.evaluate(parameter.getSpelExpression());
+ return object == null ? null : potentiallyConvertSpelValue(object, parameter);
+ }
+
+ /**
+ * Hook to allow to massage the value resulting from the Spel expression evaluation. Default implementation will
+ * leverage the configured {@link ConversionService} to massage the value into the parameter type.
+ *
+ * @param object the value to massage, will never be {@literal null}.
+ * @param parameter the {@link Parameter} we create the value for
+ * @return
+ */
+ protected T potentiallyConvertSpelValue(Object object, Parameter parameter) {
+ return conversionService.convert(object, parameter.getRawType());
+ }
+}
diff --git a/spring-data-commons-core/src/test/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProviderUnitTests.java b/spring-data-commons-core/src/test/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProviderUnitTests.java
index ee238f327..c6a720950 100644
--- a/spring-data-commons-core/src/test/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProviderUnitTests.java
+++ b/spring-data-commons-core/src/test/java/org/springframework/data/mapping/model/PersistentEntityParameterValueProviderUnitTests.java
@@ -20,7 +20,9 @@ import static org.junit.Assert.*;
import java.util.Iterator;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
@@ -39,6 +41,9 @@ import org.springframework.data.util.ClassTypeInformation;
@RunWith(MockitoJUnitRunner.class)
public class PersistentEntityParameterValueProviderUnitTests
propertyValueProvider;
@Mock
@@ -53,6 +58,7 @@ public class PersistentEntityParameterValueProviderUnitTests
entity = new BasicPersistentEntity(ClassTypeInformation.from(Inner.class)) {
+ @Override
public P getPersistentProperty(String name) {
return property;
}
@@ -67,6 +73,22 @@ public class PersistentEntityParameterValueProviderUnitTests
entity = new BasicPersistentEntity(ClassTypeInformation.from(Entity.class));
+ ParameterValueProvider
provider = new PersistentEntityParameterValueProvider
(entity, propertyValueProvider,
+ property);
+
+ PreferredConstructor constructor = entity.getPersistenceConstructor();
+
+ exception.expect(MappingException.class);
+ exception.expectMessage("bar");
+ exception.expectMessage(Entity.class.getName());
+
+ provider.getParameterValue(constructor.getParameters().iterator().next());
+ }
+
static class Outer {
class Inner {
@@ -78,4 +100,13 @@ public class PersistentEntityParameterValueProviderUnitTests