From 02cacf59bca50eb19a55699ba41177530f34dad9 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Fri, 26 Apr 2013 18:46:15 +0200 Subject: [PATCH] DATACMNS-322 - CdiRepositoryBean implements PassivationCapable. To allow the CdiRepositoryBeans being used inside scoped CDI beans we need to implement PassivationCapable so that the CDI contain can serialize the bean instance and detect the contextual instance on deserialization. As the repositories are application scoped we simply consider a bean of a given type plus its qualifier annotations unique. --- .../repository/cdi/CdiRepositoryBean.java | 39 ++++++++++++++++++- .../cdi/CdiRepositoryExtensionSupport.java | 4 +- .../cdi/CdiRepositoryBeanUnitTests.java | 15 +++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java index bf7d430d6..b73477e11 100644 --- a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java +++ b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java @@ -17,9 +17,11 @@ package org.springframework.data.repository.cdi; import java.lang.annotation.Annotation; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.List; import java.util.Set; import javax.enterprise.context.ApplicationScoped; @@ -29,10 +31,12 @@ import javax.enterprise.inject.Stereotype; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.InjectionPoint; +import javax.enterprise.inject.spi.PassivationCapable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Base class for {@link Bean} wrappers. @@ -40,13 +44,14 @@ import org.springframework.util.Assert; * @author Dirk Mahler * @author Oliver Gierke */ -public abstract class CdiRepositoryBean implements Bean { +public abstract class CdiRepositoryBean implements Bean, PassivationCapable { private static final Logger LOGGER = LoggerFactory.getLogger(CdiRepositoryBean.class); private final Set qualifiers; private final Class repositoryType; private final BeanManager beanManager; + private final String passivationId; /** * Creates a new {@link CdiRepositoryBean}. @@ -65,6 +70,30 @@ public abstract class CdiRepositoryBean implements Bean { this.qualifiers = qualifiers; this.repositoryType = repositoryType; this.beanManager = beanManager; + this.passivationId = createPassivationId(qualifiers, repositoryType); + } + + /** + * Creates a unique identifier for the given repository type and the given annotations. + * + * @param qualifiers must not be {@literal null} or contain {@literal null} values. + * @param repositoryType must not be {@literal null}. + * @return + */ + private final String createPassivationId(Set qualifiers, Class repositoryType) { + + List qualifierNames = new ArrayList(qualifiers.size()); + + for (Annotation qualifier : qualifiers) { + qualifierNames.add(qualifier.annotationType().getName()); + } + + Collections.sort(qualifierNames); + + StringBuilder builder = new StringBuilder(StringUtils.collectionToDelimitedString(qualifierNames, ":")); + builder.append(":").append(repositoryType.getName()); + + return builder.toString(); } /* @@ -200,6 +229,14 @@ public abstract class CdiRepositoryBean implements Bean { return ApplicationScoped.class; } + /* + * (non-Javadoc) + * @see javax.enterprise.inject.spi.PassivationCapable#getId() + */ + public String getId() { + return passivationId; + } + /** * Creates the actual component instance. * diff --git a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java index 5fd10c2bb..1c35c5d48 100644 --- a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java +++ b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java @@ -124,13 +124,13 @@ public abstract class CdiRepositoryExtensionSupport implements Extension { return repositoryTypes.entrySet(); } - private static class DefaultAnnotationLiteral extends AnnotationLiteral implements Default { + static class DefaultAnnotationLiteral extends AnnotationLiteral implements Default { private static final long serialVersionUID = 511359421048623933L; private static final DefaultAnnotationLiteral INSTANCE = new DefaultAnnotationLiteral(); } - private static class AnyAnnotationLiteral extends AnnotationLiteral implements Any { + static class AnyAnnotationLiteral extends AnnotationLiteral implements Any { private static final long serialVersionUID = 7261821376671361463L; private static final AnyAnnotationLiteral INSTANCE = new AnyAnnotationLiteral(); diff --git a/src/test/java/org/springframework/data/repository/cdi/CdiRepositoryBeanUnitTests.java b/src/test/java/org/springframework/data/repository/cdi/CdiRepositoryBeanUnitTests.java index c906bb8b8..24c2b70a7 100644 --- a/src/test/java/org/springframework/data/repository/cdi/CdiRepositoryBeanUnitTests.java +++ b/src/test/java/org/springframework/data/repository/cdi/CdiRepositoryBeanUnitTests.java @@ -44,7 +44,11 @@ import org.springframework.data.repository.Repository; @RunWith(MockitoJUnitRunner.class) public class CdiRepositoryBeanUnitTests { + static final String PASSIVATION_ID = "javax.enterprise.inject.Default:org.springframework.data.repository.cdi.CdiRepositoryBeanUnitTests$SampleRepository"; + static final Set NO_ANNOTATIONS = Collections.emptySet(); + static final Set SINGLE_ANNOTATION = Collections + .singleton((Annotation) new CdiRepositoryExtensionSupport.DefaultAnnotationLiteral()); @Mock BeanManager beanManager; @@ -110,6 +114,17 @@ public class CdiRepositoryBeanUnitTests { assertThat(bean.getScope(), equalTo((Class) ApplicationScoped.class)); } + /** + * @see DATACMNS-322 + */ + @Test + public void createsPassivationId() { + + CdiRepositoryBean bean = new DummyCdiRepositoryBean(SINGLE_ANNOTATION, + SampleRepository.class, beanManager); + assertThat(bean.getId(), is(PASSIVATION_ID)); + } + static class DummyCdiRepositoryBean extends CdiRepositoryBean { public DummyCdiRepositoryBean(Set qualifiers, Class repositoryType, BeanManager beanManager) {