From cd3400534951b68f4f8809c43a67a9b85b881f06 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 6 Aug 2014 14:26:37 +0200 Subject: [PATCH] DATAJPA-584 - Add support for custom implementations in CDI. Adapted to API changes in Spring Data Commons. Added test cases to make sure the lookup of custom repository implementations works. Original pull request: #105. --- .../jpa/repository/cdi/JpaRepositoryBean.java | 15 ++++---- .../cdi/JpaRepositoryExtension.java | 8 +++-- .../cdi/CdiExtensionIntegrationTests.java | 23 ++++++++++++- .../QualifiedCustomizedCdiConfiguration.java | 32 +++++++++++++++++ .../QualifiedCustomizedUserRepository.java | 30 ++++++++++++++++ ...QualifiedCustomizedUserRepositoryBean.java | 28 +++++++++++++++ ...alifiedCustomizedUserRepositoryCustom.java | 26 ++++++++++++++ .../cdi/QualifiedEntityManagerProducer.java | 20 +++++++++-- .../repository/cdi/RepositoryConsumer.java | 24 +++++++++---- .../cdi/SamplePersonRepository.java | 25 ++++++++++++++ .../cdi/SamplePersonRepositoryCustom.java | 26 ++++++++++++++ .../cdi/SamplePersonRepositoryImpl.java | 29 ++++++++++++++++ .../data/jpa/repository/cdi/UserDB.java | 34 +++++++++++++++++++ 13 files changed, 301 insertions(+), 19 deletions(-) create mode 100644 src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedCdiConfiguration.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedUserRepository.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedUserRepositoryBean.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedUserRepositoryCustom.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/cdi/SamplePersonRepository.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/cdi/SamplePersonRepositoryCustom.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/cdi/SamplePersonRepositoryImpl.java create mode 100644 src/test/java/org/springframework/data/jpa/repository/cdi/UserDB.java diff --git a/src/main/java/org/springframework/data/jpa/repository/cdi/JpaRepositoryBean.java b/src/main/java/org/springframework/data/jpa/repository/cdi/JpaRepositoryBean.java index abe7f22da..12342531e 100644 --- a/src/main/java/org/springframework/data/jpa/repository/cdi/JpaRepositoryBean.java +++ b/src/main/java/org/springframework/data/jpa/repository/cdi/JpaRepositoryBean.java @@ -32,6 +32,7 @@ import org.springframework.util.Assert; * * @author Dirk Mahler * @author Oliver Gierke + * @author Mark Paluch * @param The type of the repository. */ class JpaRepositoryBean extends CdiRepositoryBean { @@ -45,27 +46,29 @@ class JpaRepositoryBean extends CdiRepositoryBean { * @param entityManagerBean must not be {@literal null}. * @param qualifiers must not be {@literal null}. * @param repositoryType must not be {@literal null}. + * @param customImplementationBean can be {@literal null}. */ JpaRepositoryBean(BeanManager beanManager, Bean entityManagerBean, Set qualifiers, - Class repositoryType) { + Class repositoryType, Bean customImplementationBean) { - super(qualifiers, repositoryType, beanManager); + super(qualifiers, repositoryType, beanManager, customImplementationBean); Assert.notNull(entityManagerBean); this.entityManagerBean = entityManagerBean; } - /* + /* * (non-Javadoc) - * @see javax.enterprise.context.spi.Contextual#create(javax.enterprise .context.spi.CreationalContext) + * @see org.springframework.data.repository.cdi.CdiRepositoryBean#create(javax.enterprise.context.spi.CreationalContext, java.lang.Class, java.lang.Object) */ @Override - public T create(CreationalContext creationalContext, Class repositoryType) { + public T create(CreationalContext creationalContext, Class repositoryType, Object customImplementation) { // Get an instance from the associated entity manager bean. EntityManager entityManager = getDependencyInstance(entityManagerBean, EntityManager.class); + // Create the JPA repository instance and return it. JpaRepositoryFactory factory = new JpaRepositoryFactory(entityManager); - return factory.getRepository(repositoryType); + return factory.getRepository(repositoryType, customImplementation); } } diff --git a/src/main/java/org/springframework/data/jpa/repository/cdi/JpaRepositoryExtension.java b/src/main/java/org/springframework/data/jpa/repository/cdi/JpaRepositoryExtension.java index faa1b1997..9360fbe13 100644 --- a/src/main/java/org/springframework/data/jpa/repository/cdi/JpaRepositoryExtension.java +++ b/src/main/java/org/springframework/data/jpa/repository/cdi/JpaRepositoryExtension.java @@ -41,6 +41,7 @@ import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport; * * @author Dirk Mahler * @author Oliver Gierke + * @author Mark Paluch */ public class JpaRepositoryExtension extends CdiRepositoryExtensionSupport { @@ -57,7 +58,7 @@ public class JpaRepositoryExtension extends CdiRepositoryExtensionSupport { * later association with corresponding repository beans. * * @param The type. - * @param processAnnotatedType The annotated type as defined by CDI. + * @param processBean The annotated type as defined by CDI. */ @SuppressWarnings("unchecked") void processBean(@Observes ProcessBean processBean) { @@ -118,7 +119,10 @@ public class JpaRepositoryExtension extends CdiRepositoryExtensionSupport { EntityManager.class.getName(), qualifiers)); } + Bean customImplementationBean = getCustomImplementationBean(repositoryType, beanManager, qualifiers); + // Construct and return the repository bean. - return new JpaRepositoryBean(beanManager, entityManagerBean, qualifiers, repositoryType); + return new JpaRepositoryBean(beanManager, entityManagerBean, qualifiers, repositoryType, + customImplementationBean); } } diff --git a/src/test/java/org/springframework/data/jpa/repository/cdi/CdiExtensionIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/cdi/CdiExtensionIntegrationTests.java index 1a2f123f3..57c2afccd 100644 --- a/src/test/java/org/springframework/data/jpa/repository/cdi/CdiExtensionIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/cdi/CdiExtensionIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2013 the original author or authors. + * Copyright 2011-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. @@ -35,6 +35,7 @@ import org.slf4j.LoggerFactory; * * @author Dirk Mahler * @author Oliver Gierke + * @author Mark Paluch */ public class CdiExtensionIntegrationTests { @@ -73,4 +74,24 @@ public class CdiExtensionIntegrationTests { repositoryConsumer.save(person); repositoryConsumer.findAll(); } + + /** + * @see DATAJPA-584 + */ + @Test + public void returnOneFromCustomImpl() { + + RepositoryConsumer repositoryConsumer = container.getInstance(RepositoryConsumer.class); + assertThat(repositoryConsumer.returnOne(), is(1)); + } + + /** + * @see DATAJPA-584 + */ + @Test + public void useQualifiedCustomizedUserRepo() { + + RepositoryConsumer repositoryConsumer = container.getInstance(RepositoryConsumer.class); + repositoryConsumer.doSomethonOnUserDB(); + } } diff --git a/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedCdiConfiguration.java b/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedCdiConfiguration.java new file mode 100644 index 000000000..7caa1ba23 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedCdiConfiguration.java @@ -0,0 +1,32 @@ +/* + * 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.jpa.repository.cdi; + +import org.springframework.data.repository.cdi.CdiRepositoryConfiguration; + +/** + * @see DATAJPA-584 + * @author Mark Paluch + */ +@UserDB +public class QualifiedCustomizedCdiConfiguration implements CdiRepositoryConfiguration { + + @Override + public String getRepositoryImplementationPostfix() { + return "Bean"; + } +} diff --git a/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedUserRepository.java b/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedUserRepository.java new file mode 100644 index 000000000..42e4bb3a3 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedUserRepository.java @@ -0,0 +1,30 @@ +/* + * 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.jpa.repository.cdi; + +import org.springframework.data.jpa.domain.sample.User; +import org.springframework.data.repository.Repository; + +/** + * @see DATAJPA-584 + * @author Mark Paluch + */ +@UserDB +public interface QualifiedCustomizedUserRepository extends Repository, + QualifiedCustomizedUserRepositoryCustom { + +} diff --git a/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedUserRepositoryBean.java b/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedUserRepositoryBean.java new file mode 100644 index 000000000..b5d144cf0 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedUserRepositoryBean.java @@ -0,0 +1,28 @@ +/* + * 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.jpa.repository.cdi; + +/** + * @see DATAJPA-584 + * @author Mark Paluch + */ +@UserDB +public class QualifiedCustomizedUserRepositoryBean implements QualifiedCustomizedUserRepositoryCustom { + + @Override + public void doSomething() {} +} diff --git a/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedUserRepositoryCustom.java b/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedUserRepositoryCustom.java new file mode 100644 index 000000000..6262cc3e7 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedCustomizedUserRepositoryCustom.java @@ -0,0 +1,26 @@ +/* + * 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.jpa.repository.cdi; + +/** + * @see DATAJPA-584 + * @author Mark Paluch + */ +public interface QualifiedCustomizedUserRepositoryCustom { + + void doSomething(); +} diff --git a/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedEntityManagerProducer.java b/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedEntityManagerProducer.java index 68001fc7d..ddbfe25c8 100644 --- a/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedEntityManagerProducer.java +++ b/src/test/java/org/springframework/data/jpa/repository/cdi/QualifiedEntityManagerProducer.java @@ -1,5 +1,5 @@ /* - * Copyright 2011 the original author or authors. + * Copyright 2011-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. @@ -20,15 +20,29 @@ import javax.enterprise.inject.Produces; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; +/** + * @author Oliver Gierke + * @author Mark Paluch + */ class QualifiedEntityManagerProducer { @Produces @PersonDB - public EntityManager createEntityManager(EntityManagerFactory entityManagerFactory) { + public EntityManager createPersonDBEntityManager(EntityManagerFactory entityManagerFactory) { return entityManagerFactory.createEntityManager(); } - public void close(@Disposes @PersonDB EntityManager entityManager) { + public void closePersonDB(@Disposes @PersonDB EntityManager entityManager) { + entityManager.close(); + } + + @Produces + @UserDB + public EntityManager createUserDBEntityManager(EntityManagerFactory entityManagerFactory) { + return entityManagerFactory.createEntityManager(); + } + + public void closeUserDB(@Disposes @UserDB EntityManager entityManager) { entityManager.close(); } } diff --git a/src/test/java/org/springframework/data/jpa/repository/cdi/RepositoryConsumer.java b/src/test/java/org/springframework/data/jpa/repository/cdi/RepositoryConsumer.java index 40ad8313c..05fd2b65e 100644 --- a/src/test/java/org/springframework/data/jpa/repository/cdi/RepositoryConsumer.java +++ b/src/test/java/org/springframework/data/jpa/repository/cdi/RepositoryConsumer.java @@ -1,5 +1,5 @@ /* - * Copyright 2011 the original author or authors. + * Copyright 2011-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. @@ -17,15 +17,17 @@ package org.springframework.data.jpa.repository.cdi; import javax.inject.Inject; +/** + * @author Oliver Gierke + * @author Mark Paluch + */ @Transactional class RepositoryConsumer { - @Inject - private PersonRepository unqualifiedRepo; - - @Inject - @PersonDB - private PersonRepository qualifiedRepo; + @Inject PersonRepository unqualifiedRepo; + @Inject @PersonDB PersonRepository qualifiedRepo; + @Inject SamplePersonRepository samplePersonRepository; + @Inject @UserDB QualifiedCustomizedUserRepository qualifiedCustomizedUserRepository; public void findAll() { unqualifiedRepo.findAll(); @@ -36,4 +38,12 @@ class RepositoryConsumer { unqualifiedRepo.save(person); qualifiedRepo.save(person); } + + public int returnOne() { + return samplePersonRepository.returnOne(); + } + + public void doSomethonOnUserDB() { + qualifiedCustomizedUserRepository.doSomething(); + } } diff --git a/src/test/java/org/springframework/data/jpa/repository/cdi/SamplePersonRepository.java b/src/test/java/org/springframework/data/jpa/repository/cdi/SamplePersonRepository.java new file mode 100644 index 000000000..6c3042319 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/cdi/SamplePersonRepository.java @@ -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.jpa.repository.cdi; + +import org.springframework.data.repository.Repository; + +/** + * @see DATAJPA-584 + * @author Mark Paluch + */ +public interface SamplePersonRepository extends Repository, SamplePersonRepositoryCustom {} diff --git a/src/test/java/org/springframework/data/jpa/repository/cdi/SamplePersonRepositoryCustom.java b/src/test/java/org/springframework/data/jpa/repository/cdi/SamplePersonRepositoryCustom.java new file mode 100644 index 000000000..4d2354c4c --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/cdi/SamplePersonRepositoryCustom.java @@ -0,0 +1,26 @@ +/* + * 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.jpa.repository.cdi; + +/** + * @see DATAJPA-584 + * @author Mark Paluch + */ +interface SamplePersonRepositoryCustom { + + int returnOne(); +} diff --git a/src/test/java/org/springframework/data/jpa/repository/cdi/SamplePersonRepositoryImpl.java b/src/test/java/org/springframework/data/jpa/repository/cdi/SamplePersonRepositoryImpl.java new file mode 100644 index 000000000..81ef8a64a --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/cdi/SamplePersonRepositoryImpl.java @@ -0,0 +1,29 @@ +/* + * 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.jpa.repository.cdi; + +/** + * @see DATAJPA-584 + * @author Mark Paluch + */ +class SamplePersonRepositoryImpl implements SamplePersonRepositoryCustom { + + @Override + public int returnOne() { + return 1; + } +} diff --git a/src/test/java/org/springframework/data/jpa/repository/cdi/UserDB.java b/src/test/java/org/springframework/data/jpa/repository/cdi/UserDB.java new file mode 100644 index 000000000..1251ffdd0 --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/cdi/UserDB.java @@ -0,0 +1,34 @@ +/* + * 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.jpa.repository.cdi; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.inject.Qualifier; + +/** + * @see DATAJPA-584 + * @author Mark Paluch + */ +@Qualifier +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER }) +@interface UserDB { + +}