DATACMNS-557 - Added support for custom implementations to CDI infrastructure.

The CDI extension now discovers a custom implementation class similarly to the detection when using Spring Data in a Spring container. Extracted the custom implementation detection for re-use. The CDI extension discovers the potentially available bean and hands it to the CdiRepositoryBean for further usage.

Implementations should implement the extended variant of the create(…) method we introduce with this commit to be able to forward the resolved custom implementation bean.

Original pull request: #92.
This commit is contained in:
Mark Paluch
2014-08-07 10:26:10 +02:00
committed by Oliver Gierke
parent 62e66ab305
commit 1f0260e48d
12 changed files with 427 additions and 86 deletions

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2014 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;
public interface AnotherRepository extends Repository<Object, Serializable>, AnotherRepositoryCustom {
}

View File

@@ -0,0 +1,21 @@
/*
* Copyright 2014 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;
public interface AnotherRepositoryCustom {
int returnZero();
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright 2014 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;
public class AnotherRepositoryImpl implements AnotherRepositoryCustom {
@Override
public int returnZero() {
return 0;
}
}

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.data.repository.cdi;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.Test;
@@ -36,5 +36,20 @@ public abstract class CdiRepositoryExtensionSupportIntegrationTests {
assertThat(client.repository, is(notNullValue()));
}
/**
* @see DATACMNS-557
*/
@Test
public void createsSpringDataRepositoryWithCustimImplBean() {
assertThat(getBean(AnotherRepository.class), is(notNullValue()));
RepositoryClient client = getBean(RepositoryClient.class);
assertThat(client.anotherRepository, is(notNullValue()));
// this will always return 0 since it's a mock
assertThat(client.anotherRepository.returnZero(), is(0));
}
protected abstract <T> T getBean(Class<T> type);
}

View File

@@ -15,18 +15,21 @@
*/
package org.springframework.data.repository.cdi;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Map.Entry;
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 java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.webbeans.context.AbstractContext;
import org.apache.webbeans.context.creational.BeanInstanceBag;
import org.mockito.Mockito;
/**
@@ -37,10 +40,15 @@ import org.mockito.Mockito;
*/
public class DummyCdiExtension extends CdiRepositoryExtensionSupport {
@SuppressWarnings({ "rawtypes", "unchecked" })
@SuppressWarnings({"rawtypes", "unchecked"})
void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) {
afterBeanDiscovery.addContext(new MyCustomScope());
for (Entry<Class<?>, Set<Annotation>> type : getRepositoryTypes()) {
DummyCdiRepositoryBean bean = new DummyCdiRepositoryBean(type.getValue(), type.getKey(), beanManager);
CdiRepositoryConfigurationSource configurationSource = lookupConfiguration(beanManager, type.getValue());
Object customImplementation = findCustomImplementation(type.getKey(), beanManager, type.getValue());
DummyCdiRepositoryBean bean = new DummyCdiRepositoryBean(type.getValue(), type.getKey(), beanManager, customImplementation);
registerBean(bean);
afterBeanDiscovery.addBean(bean);
}
@@ -52,6 +60,10 @@ public class DummyCdiExtension extends CdiRepositoryExtensionSupport {
super(qualifiers, repositoryType, beanManager);
}
DummyCdiRepositoryBean(Set<Annotation> qualifiers, Class<T> repositoryType, BeanManager beanManager, Object customImplementation) {
super(qualifiers, repositoryType, beanManager, customImplementation);
}
public Class<? extends Annotation> getScope() {
return MyScope.class;
}
@@ -67,4 +79,22 @@ public class DummyCdiExtension extends CdiRepositoryExtensionSupport {
@interface MyScope {
}
static class MyCustomScope extends AbstractContext {
MyCustomScope() {
super(MyScope.class);
setActive(true);
}
@Override
protected void setComponentInstanceMap() {
componentInstanceMap = new HashMap<Contextual<?>, BeanInstanceBag<?>>();
}
@Override
public boolean isActive() {
return true;
}
}
}

View File

@@ -25,4 +25,7 @@ class RepositoryClient {
@Inject
SampleRepository repository;
@Inject
AnotherRepository anotherRepository;
}