DATACMNS-1233 - Allow CDI Repositories to be composed of an arbitrary number of implementation classes.
We now support repository fragments for repositories exported through CDI. Original pull request: #272.
This commit is contained in:
committed by
Oliver Gierke
parent
919090bf20
commit
0a3b71f0a1
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2018 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.repository.cdi;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface AnotherFragmentInterface {
|
||||
|
||||
int getPriority();
|
||||
|
||||
int getShadowed();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2018 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.repository.cdi;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class AnotherFragmentInterfaceImpl implements AnotherFragmentInterface {
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getShadowed() {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
* Copyright 2018 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.
|
||||
@@ -13,10 +13,12 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.repository.cdi;
|
||||
|
||||
public class AnotherRepositoryImpl implements AnotherRepositoryCustom {
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class AnotherRepositoryImpl implements AnotherRepositoryCustom {
|
||||
|
||||
@Override
|
||||
public int returnZero() {
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2018 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.repository.cdi;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import javax.enterprise.inject.se.SeContainer;
|
||||
import javax.enterprise.inject.se.SeContainerInitializer;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.repository.cdi.isolated.IsolatedComposedRepository;
|
||||
|
||||
/**
|
||||
* CDI integration tests for {@link CdiRepositoryConfiguration}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class CdiConfigurationIntegrationTests {
|
||||
|
||||
private static SeContainer container;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() {
|
||||
|
||||
container = SeContainerInitializer.newInstance() //
|
||||
.disableDiscovery() //
|
||||
.addPackages(IsolatedComposedRepository.class) //
|
||||
.initialize();
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1233
|
||||
public void shouldApplyImplementationPostfix() {
|
||||
|
||||
IsolatedComposedRepository repository = container.select(IsolatedComposedRepository.class).get();
|
||||
|
||||
assertThat(repository.getPriority()).isEqualTo(42);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
container.close();
|
||||
}
|
||||
}
|
||||
@@ -155,14 +155,14 @@ public class CdiRepositoryBeanUnitTests {
|
||||
|
||||
verify(detector).detectCustomImplementation( //
|
||||
eq("CdiRepositoryBeanUnitTests.SampleRepositoryImpl"), //
|
||||
eq("namedRepositoryImpl"), //
|
||||
eq("CdiRepositoryBeanUnitTests.SampleRepositoryImpl"), //
|
||||
anySet(), //
|
||||
anySet(), //
|
||||
Mockito.any(Function.class) //
|
||||
);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1255
|
||||
@Test // DATACMNS-1233
|
||||
public void appliesRepositoryConfiguration() {
|
||||
|
||||
DummyCdiRepositoryBean<SampleRepository> bean = new DummyCdiRepositoryBean<SampleRepository>(NO_ANNOTATIONS,
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2018 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.repository.cdi;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface ComposedRepository
|
||||
extends Repository<Object, Serializable>, FragmentInterface, AnotherFragmentInterface {
|
||||
|
||||
// duplicate method shadowed by AnotherFragmentInterfaceImpl. The legacy custom implementation comes last, after all
|
||||
// other fragments.
|
||||
int getShadowed();
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2018 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.repository.cdi;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface ComposedRepositoryCustom {
|
||||
|
||||
int returnFourtyTwo();
|
||||
|
||||
// duplicate method shadowed by AnotherFragmentInterfaceImpl. The legacy custom implementation comes last, after all
|
||||
// other
|
||||
// fragments.
|
||||
int getShadowed();
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2018 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.repository.cdi;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class ComposedRepositoryImpl implements ComposedRepositoryCustom {
|
||||
|
||||
@Override
|
||||
public int returnFourtyTwo() {
|
||||
return 42;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getShadowed() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -24,16 +24,15 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.enterprise.context.NormalScope;
|
||||
import javax.enterprise.context.spi.Contextual;
|
||||
import javax.enterprise.context.spi.CreationalContext;
|
||||
import javax.enterprise.event.Observes;
|
||||
import javax.enterprise.inject.spi.AfterBeanDiscovery;
|
||||
import javax.enterprise.inject.spi.BeanManager;
|
||||
|
||||
import org.apache.webbeans.context.AbstractContext;
|
||||
import org.apache.webbeans.context.creational.BeanInstanceBag;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.data.repository.config.CustomRepositoryImplementationDetector;
|
||||
import org.springframework.data.repository.core.support.DummyRepositoryFactory;
|
||||
|
||||
/**
|
||||
* Dummy extension of {@link CdiRepositoryExtensionSupport} to allow integration tests. Will create mocks for repository
|
||||
@@ -74,9 +73,12 @@ public class DummyCdiExtension extends CdiRepositoryExtensionSupport {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType,
|
||||
Optional<Object> customImplementation) {
|
||||
return Mockito.mock(repositoryType);
|
||||
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType) {
|
||||
|
||||
T mock = Mockito.mock(repositoryType);
|
||||
DummyRepositoryFactory repositoryFactory = new DummyRepositoryFactory(mock);
|
||||
|
||||
return create(repositoryFactory, repositoryType, getRepositoryFragments(repositoryType));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2018 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.repository.cdi;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface FragmentInterface {
|
||||
int getPriority();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2018 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.repository.cdi;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class FragmentInterfaceImpl implements FragmentInterface {
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2018 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.repository.cdi;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import javax.enterprise.inject.se.SeContainer;
|
||||
import javax.enterprise.inject.se.SeContainerInitializer;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* CDI integration tests for composed repositories.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class RepositoryFragmentsIntegrationTests {
|
||||
|
||||
private static SeContainer container;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUp() {
|
||||
|
||||
container = SeContainerInitializer.newInstance() //
|
||||
.disableDiscovery() //
|
||||
.addPackages(ComposedRepository.class) //
|
||||
.initialize();
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1233
|
||||
public void shouldInvokeCustomImplementationLast() {
|
||||
|
||||
ComposedRepository repository = getBean(ComposedRepository.class);
|
||||
ComposedRepositoryImpl customImplementation = getBean(ComposedRepositoryImpl.class);
|
||||
AnotherFragmentInterfaceImpl shadowed = getBean(AnotherFragmentInterfaceImpl.class);
|
||||
|
||||
assertThat(repository.getShadowed()).isEqualTo(2);
|
||||
assertThat(customImplementation.getShadowed()).isEqualTo(1);
|
||||
assertThat(shadowed.getShadowed()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-1233
|
||||
public void shouldRespectInterfaceOrder() {
|
||||
|
||||
ComposedRepository repository = getBean(ComposedRepository.class);
|
||||
FragmentInterfaceImpl fragment = getBean(FragmentInterfaceImpl.class);
|
||||
AnotherFragmentInterfaceImpl shadowed = getBean(AnotherFragmentInterfaceImpl.class);
|
||||
|
||||
assertThat(repository.getPriority()).isEqualTo(1);
|
||||
assertThat(fragment.getPriority()).isEqualTo(1);
|
||||
assertThat(shadowed.getPriority()).isEqualTo(2);
|
||||
}
|
||||
|
||||
protected <T> T getBean(Class<T> type) {
|
||||
return container.select(type).get();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
container.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2018 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.repository.cdi.isolated;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface FragmentInterface {
|
||||
|
||||
int getPriority();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2018 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.repository.cdi.isolated;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
class FragmentInterfaceFoo implements FragmentInterface {
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 42;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2018 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.repository.cdi.isolated;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public interface IsolatedComposedRepository extends Repository<Object, Serializable>, FragmentInterface {}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2018 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.repository.cdi.isolated;
|
||||
|
||||
import org.springframework.data.repository.cdi.CdiRepositoryConfiguration;
|
||||
|
||||
/**
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class MyCdiConfiguration implements CdiRepositoryConfiguration {
|
||||
|
||||
@Override
|
||||
public String getRepositoryImplementationPostfix() {
|
||||
return "Foo";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user