DATAKV-115 - Make derived finder execution thread-safe.
We now make sure separate SpelExpression and EvaluationContext for each and every derived finder execution to assert the expression context cannot be accidentally overridden. Original pull request: #16.
This commit is contained in:
committed by
Oliver Gierke
parent
3c52aff26c
commit
e22ee22e58
@@ -16,7 +16,6 @@
|
||||
package org.springframework.data.keyvalue.core;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
@@ -33,14 +32,12 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.keyvalue.core.query.KeyValueQuery;
|
||||
import org.springframework.data.keyvalue.repository.query.SpelQueryCreator;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.expression.spel.standard.SpelExpression;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
|
||||
/**
|
||||
@@ -77,8 +74,8 @@ public class SpelQueryEngineUnitTests {
|
||||
|
||||
doReturn(people).when(adapter).getAllOf(anyString());
|
||||
|
||||
assertThat((Collection<Person>) engine.execute(createQueryForMethodWithArgs("findByFirstname", "bob"), null, -1, -1,
|
||||
anyString()), contains(BOB_WITH_FIRSTNAME));
|
||||
assertThat((Collection<Person>) engine.execute(createQueryForMethodWithArgs("findByFirstname", "bob"), null, -1,
|
||||
-1, anyString()), contains(BOB_WITH_FIRSTNAME));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,7 +89,7 @@ public class SpelQueryEngineUnitTests {
|
||||
assertThat(engine.count(createQueryForMethodWithArgs("findByFirstname", "bob"), anyString()), is(1L));
|
||||
}
|
||||
|
||||
private static SpelExpression createQueryForMethodWithArgs(String methodName, Object... args) throws Exception {
|
||||
private static SpelCriteria createQueryForMethodWithArgs(String methodName, Object... args) throws Exception {
|
||||
|
||||
List<Class<?>> types = new ArrayList<Class<?>>(args.length);
|
||||
|
||||
@@ -105,13 +102,10 @@ public class SpelQueryEngineUnitTests {
|
||||
doReturn(method.getReturnType()).when(metadata).getReturnedDomainClass(method);
|
||||
|
||||
PartTree partTree = new PartTree(method.getName(), method.getReturnType());
|
||||
SpelQueryCreator creator = new SpelQueryCreator(partTree, new ParametersParameterAccessor(
|
||||
new QueryMethod(method, metadata, new SpelAwareProxyProjectionFactory()).getParameters(), args));
|
||||
SpelQueryCreator creator = new SpelQueryCreator(partTree, new ParametersParameterAccessor(new QueryMethod(method,
|
||||
metadata, new SpelAwareProxyProjectionFactory()).getParameters(), args));
|
||||
|
||||
KeyValueQuery<SpelExpression> query = creator.createQuery();
|
||||
query.getCritieria().setEvaluationContext(new StandardEvaluationContext(args));
|
||||
|
||||
return query.getCritieria();
|
||||
return new SpelCriteria(creator.createQuery().getCritieria(), new StandardEvaluationContext(args));
|
||||
}
|
||||
|
||||
static interface PersonRepository {
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2015-2016 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.keyvalue.repository.query;
|
||||
|
||||
import static org.hamcrest.core.IsNot.*;
|
||||
import static org.hamcrest.core.IsSame.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.keyvalue.Person;
|
||||
import org.springframework.data.keyvalue.core.KeyValueOperations;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.DefaultEvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class KeyValuePartTreeQueryUnitTests {
|
||||
|
||||
@Mock KeyValueOperations kvOpsMock;
|
||||
@Mock RepositoryMetadata metadataMock;
|
||||
@Mock ProjectionFactory projectionFactoryMock;
|
||||
|
||||
/**
|
||||
* @see DATAKV-115
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void spelExpressionAndContextShouldNotBeReused() throws NoSuchMethodException, SecurityException {
|
||||
|
||||
when(metadataMock.getDomainType()).thenReturn((Class) Person.class);
|
||||
when(metadataMock.getReturnedDomainClass(any(Method.class))).thenReturn((Class) Person.class);
|
||||
|
||||
QueryMethod qm = new QueryMethod(Repo.class.getMethod("findByFirstname", String.class), metadataMock,
|
||||
projectionFactoryMock);
|
||||
|
||||
KeyValuePartTreeQuery query = new KeyValuePartTreeQuery(qm, DefaultEvaluationContextProvider.INSTANCE, kvOpsMock,
|
||||
SpelQueryCreator.class);
|
||||
|
||||
Object[] args = new Object[] { "foo" };
|
||||
|
||||
assertThat(query.prepareQuery(args).getCritieria(), not(sameInstance(query.prepareQuery(args).getCritieria())));
|
||||
}
|
||||
|
||||
static interface Repo {
|
||||
|
||||
List<Person> findByFirstname(String firstname);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user