DATACMNS-1260 - Extract EvaluationContextProvider and corresponding SPIs into dedicated package.

We now have a refined replica of the EvaluationContextProvider API and SPIs in the org.springframework.data.spel package. It has seen a bit of a Java 8 overhaul by removing the SPI support class in favor of turning most methods in EvaluationContextExtension into default ones.

The already existing API has been renamed to QueryMethodEvaluationContextProvider to indicate it's working with additional semantics specific to query methods (i.e. the Parameters metadata). The internals have been refactored to use the new API but still detect implementations of the old EvaluationContextExtension interface. The implementations get wrapped into an adapting proxy to satisfy the new API so that the actual inspection and usage of the extension is now already done using the new APIs.

The repository configuration has slightly change so that the creation of the EvaluationContextProvider is now taking place within RepositoryFactoryBeanSupport's implementation of BeanFactoryAware.

AbstractMappingContext is now ApplicationContextAware and holds an ExtensionAwareEvaluationContextProvider using the configured ApplicationContext. That EvaluationContextProvider is forwarded to all MutablePersistentEntity instances. BasicPersistentEntity now exposes getEvaluationContext(…) to subclasses to easily create an EvaluationContext using the extension aware infrastructure.

Removed DefaultEvaluationContextProvider in favor of a simple constant in QueryMethodEvaluationContextProvider.

Related tickets: DATACMNS-1258, DATACMNS-1108.
This commit is contained in:
Oliver Gierke
2018-02-14 19:05:59 +01:00
parent 90337535d1
commit a6215fbe0f
25 changed files with 707 additions and 171 deletions

View File

@@ -16,6 +16,7 @@
package org.springframework.data.repository.cdi;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import java.io.Serializable;
@@ -42,9 +43,8 @@ import org.springframework.data.repository.config.CustomRepositoryImplementation
import org.springframework.data.repository.core.NamedQueries;
import org.springframework.data.repository.core.support.PropertiesBasedNamedQueries;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.data.repository.query.DefaultEvaluationContextProvider;
import org.springframework.data.repository.query.EvaluationContextProvider;
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
/**
* Unit tests for {@link CdiRepositoryBean}.
@@ -175,7 +175,7 @@ public class CdiRepositoryBeanUnitTests {
bean.applyConfiguration(repositoryFactory);
verify(repositoryFactory).setEvaluationContextProvider(DefaultEvaluationContextProvider.INSTANCE);
verify(repositoryFactory).setEvaluationContextProvider(QueryMethodEvaluationContextProvider.DEFAULT);
verify(repositoryFactory).setNamedQueries(PropertiesBasedNamedQueries.EMPTY);
verify(repositoryFactory).setRepositoryBaseClass(String.class);
verify(repositoryFactory).setQueryLookupStrategyKey(Key.CREATE);
@@ -209,8 +209,8 @@ public class CdiRepositoryBeanUnitTests {
INSTANCE;
@Override
public Optional<EvaluationContextProvider> getEvaluationContextProvider() {
return Optional.of(DefaultEvaluationContextProvider.INSTANCE);
public Optional<QueryMethodEvaluationContextProvider> getEvaluationContextProvider() {
return Optional.of(QueryMethodEvaluationContextProvider.DEFAULT);
}
@Override

View File

@@ -29,7 +29,7 @@ import org.springframework.data.repository.core.RepositoryInformation;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments;
import org.springframework.data.repository.core.support.RepositoryFactorySupportUnitTests.MyRepositoryQuery;
import org.springframework.data.repository.query.EvaluationContextProvider;
import org.springframework.data.repository.query.QueryMethodEvaluationContextProvider;
import org.springframework.data.repository.query.QueryLookupStrategy;
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
import org.springframework.data.repository.query.RepositoryQuery;
@@ -92,7 +92,7 @@ public class DummyRepositoryFactory extends RepositoryFactorySupport {
*/
@Override
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(Key key,
EvaluationContextProvider evaluationContextProvider) {
QueryMethodEvaluationContextProvider evaluationContextProvider) {
return Optional.of(strategy);
}

View File

@@ -35,14 +35,13 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.repository.query.spi.EvaluationContextExtension;
import org.springframework.data.repository.query.spi.EvaluationContextExtensionSupport;
import org.springframework.data.repository.query.spi.Function;
import org.springframework.data.spel.spi.EvaluationContextExtension;
import org.springframework.data.spel.spi.Function;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
/**
* Unit tests {@link ExtensionAwareEvaluationContextProvider}.
* Unit tests {@link ExtensionAwareQueryMethodEvaluationContextProvider}.
*
* @author Oliver Gierke
* @author Thomas Darimont
@@ -51,19 +50,19 @@ import org.springframework.expression.spel.standard.SpelExpressionParser;
public class ExtensionAwareEvaluationContextProviderUnitTests {
Method method;
EvaluationContextProvider provider;
QueryMethodEvaluationContextProvider provider;
@Before
public void setUp() throws Exception {
this.method = SampleRepo.class.getMethod("findByFirstname", String.class);
this.provider = new ExtensionAwareEvaluationContextProvider(Collections.emptyList());
this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(Collections.emptyList());
}
@Test // DATACMNS-533
public void usesPropertyDefinedByExtension() {
this.provider = new ExtensionAwareEvaluationContextProvider(
this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(
Collections.singletonList(new DummyExtension("_first", "first")));
assertThat(evaluateExpression("key")).isEqualTo("first");
@@ -76,7 +75,7 @@ public class ExtensionAwareEvaluationContextProviderUnitTests {
extensions.add(new DummyExtension("_first", "first"));
extensions.add(new DummyExtension("_second", "second"));
this.provider = new ExtensionAwareEvaluationContextProvider(extensions);
this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(extensions);
assertThat(evaluateExpression("key")).isEqualTo("second");
}
@@ -88,7 +87,7 @@ public class ExtensionAwareEvaluationContextProviderUnitTests {
extensions.add(new DummyExtension("_first", "first"));
extensions.add(new DummyExtension("_second", "second"));
this.provider = new ExtensionAwareEvaluationContextProvider(extensions);
this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(extensions);
assertThat(evaluateExpression("_first.key")).isEqualTo("first");
}
@@ -100,7 +99,7 @@ public class ExtensionAwareEvaluationContextProviderUnitTests {
@Test // DATACMNS-533
public void exposesMethodDefinedByExtension() {
this.provider = new ExtensionAwareEvaluationContextProvider(
this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(
Collections.singletonList(new DummyExtension("_first", "first")));
assertThat(evaluateExpression("aliasedMethod()")).isEqualTo("methodResult");
@@ -112,7 +111,7 @@ public class ExtensionAwareEvaluationContextProviderUnitTests {
@Test // DATACMNS-533
public void exposesPropertiesDefinedByExtension() {
this.provider = new ExtensionAwareEvaluationContextProvider(
this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(
Collections.singletonList(new DummyExtension("_first", "first")));
assertThat(evaluateExpression("DUMMY_KEY")).isEqualTo("dummy");
@@ -151,7 +150,7 @@ public class ExtensionAwareEvaluationContextProviderUnitTests {
@Test // DATACMNS-533
public void shouldBeAbleToAccessCustomRootObjectPropertiesAndFunctions() {
this.provider = new ExtensionAwareEvaluationContextProvider(Collections.singletonList( //
this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(Collections.singletonList( //
new DummyExtension("_first", "first") {
@Override
public CustomExtensionRootObject1 getRootObject() {
@@ -173,7 +172,7 @@ public class ExtensionAwareEvaluationContextProviderUnitTests {
@Test // DATACMNS-533
public void shouldBeAbleToAccessCustomRootObjectPropertiesAndFunctionsInMultipleExtensions() {
this.provider = new ExtensionAwareEvaluationContextProvider(Arrays.asList( //
this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(Arrays.asList( //
new DummyExtension("_first", "first") {
@Override
public CustomExtensionRootObject1 getRootObject() {
@@ -201,7 +200,7 @@ public class ExtensionAwareEvaluationContextProviderUnitTests {
final AtomicInteger counter = new AtomicInteger();
this.provider = new ExtensionAwareEvaluationContextProvider(Collections.singletonList( //
this.provider = new ExtensionAwareQueryMethodEvaluationContextProvider(Collections.singletonList( //
new DummyExtension("_first", "first") {
@Override
@@ -272,9 +271,9 @@ public class ExtensionAwareEvaluationContextProviderUnitTests {
.withMessageContaining("(java.lang.Integer)");
}
private static ExtensionAwareEvaluationContextProvider createContextProviderWithOverloads() {
private static ExtensionAwareQueryMethodEvaluationContextProvider createContextProviderWithOverloads() {
return new ExtensionAwareEvaluationContextProvider(Collections.singletonList( //
return new ExtensionAwareQueryMethodEvaluationContextProvider(Collections.singletonList( //
new DummyExtension("_first", "first") {
@Override
public Object getRootObject() {
@@ -284,7 +283,7 @@ public class ExtensionAwareEvaluationContextProviderUnitTests {
}
@RequiredArgsConstructor
public static class DummyExtension extends EvaluationContextExtensionSupport {
public static class DummyExtension implements org.springframework.data.spel.spi.EvaluationContextExtension {
public static String DUMMY_KEY = "dummy";
@@ -306,7 +305,7 @@ public class ExtensionAwareEvaluationContextProviderUnitTests {
@Override
public Map<String, Object> getProperties() {
Map<String, Object> properties = new HashMap<>(super.getProperties());
Map<String, Object> properties = new HashMap<>();
properties.put("key", value);
@@ -320,7 +319,7 @@ public class ExtensionAwareEvaluationContextProviderUnitTests {
@Override
public Map<String, Function> getFunctions() {
Map<String, Function> functions = new HashMap<>(super.getFunctions());
Map<String, Function> functions = new HashMap<>();
try {
functions.put("aliasedMethod", new Function(getClass().getMethod("extensionMethod")));

View File

@@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.repository.query;
package org.springframework.data.spel;
import java.util.Optional;
import org.junit.Test;
import org.springframework.data.repository.query.spi.EvaluationContextExtension;
import org.springframework.data.spel.spi.EvaluationContextExtension;
/**
* Unit tests for {@link EvaluationContextExtensionInformation}.