Browse Source

DATACMNS-416 - Added means to enforce eager instantiation of CDI repositories.

The CDI extension now eagerly instantiates repository beans that are annotated with the newly introduced @Eager annotation. This is necessary to prevent the initialization procedure from interfering with potentially already executed business logic.

To achieve this CdiRepositoryExtensionSupport provides a new method registerBean(…) that has to be called by store implementations. The extension will then keep track of beans that require eager initialization and trigger it when the container has finished validation.
pull/61/head
Oliver Gierke 12 years ago
parent
commit
df1373aa81
  1. 23
      src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java
  2. 36
      src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java
  3. 37
      src/main/java/org/springframework/data/repository/cdi/Eager.java
  4. 4
      src/test/java/org/springframework/data/repository/cdi/DummyCdiExtension.java

23
src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java

@ -53,6 +53,8 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl @@ -53,6 +53,8 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl
private final BeanManager beanManager;
private final String passivationId;
private transient T repoInstance;
/**
* Creates a new {@link CdiRepositoryBean}.
*
@ -107,11 +109,6 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl @@ -107,11 +109,6 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl
interfaces.add(repositoryType);
interfaces.addAll(Arrays.asList(repositoryType.getInterfaces()));
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Declaring types '%s' for repository '%s'.", interfaces.toString(),
repositoryType.getName()));
}
return new HashSet<Type>(interfaces);
}
@ -128,17 +125,27 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl @@ -128,17 +125,27 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl
return (S) beanManager.getReference(bean, type, creationalContext);
}
/**
* Forces the initialization of bean target.
*/
public final void initialize() {
create(beanManager.createCreationalContext(this));
}
/*
* (non-Javadoc)
* @see javax.enterprise.context.spi.Contextual#create(javax.enterprise.context.spi.CreationalContext)
*/
public final T create(CreationalContext<T> creationalContext) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(String.format("Creating bean instance for repository type '%s'.", repositoryType.getName()));
if (this.repoInstance != null) {
LOGGER.debug("Returning eagerly created CDI repository instance for {}.", repositoryType.getName());
return this.repoInstance;
}
return create(creationalContext, repositoryType);
LOGGER.debug("Creating CDI repository bean instance for {}.", repositoryType.getName());
this.repoInstance = create(creationalContext, repositoryType);
return repoInstance;
}
/*

36
src/main/java/org/springframework/data/repository/cdi/CdiRepositoryExtensionSupport.java

@ -25,7 +25,9 @@ import java.util.Set; @@ -25,7 +25,9 @@ import java.util.Set;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import javax.enterprise.util.AnnotationLiteral;
@ -33,6 +35,7 @@ import javax.inject.Qualifier; @@ -33,6 +35,7 @@ import javax.inject.Qualifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.RepositoryDefinition;
@ -48,6 +51,7 @@ public abstract class CdiRepositoryExtensionSupport implements Extension { @@ -48,6 +51,7 @@ public abstract class CdiRepositoryExtensionSupport implements Extension {
private static final Logger LOGGER = LoggerFactory.getLogger(CdiRepositoryExtensionSupport.class);
private final Map<Class<?>, Set<Annotation>> repositoryTypes = new HashMap<Class<?>, Set<Annotation>>();
private final Set<CdiRepositoryBean<?>> eagerRepositories = new HashSet<CdiRepositoryBean<?>>();
/**
* Implementation of a an observer which checks for Spring Data repository types and stores them in
@ -115,6 +119,22 @@ public abstract class CdiRepositoryExtensionSupport implements Extension { @@ -115,6 +119,22 @@ public abstract class CdiRepositoryExtensionSupport implements Extension {
return qualifiers;
}
/**
* Triggers the eager initialization of beans registered for that behavior.
*
* @param event must not be {@literal null}.
* @param manager must not be {@literal null}.
* @see #registerBean(CdiRepositoryBean)
*/
void afterDeploymentValidation(@Observes AfterDeploymentValidation event, BeanManager manager) {
for (CdiRepositoryBean<?> bean : eagerRepositories) {
LOGGER.debug("Eagerly instantiating CDI repository bean for {}.", bean.getBeanClass());
bean.initialize();
}
}
/**
* Provides access to all repository types as well as their qualifiers.
*
@ -124,6 +144,22 @@ public abstract class CdiRepositoryExtensionSupport implements Extension { @@ -124,6 +144,22 @@ public abstract class CdiRepositoryExtensionSupport implements Extension {
return repositoryTypes.entrySet();
}
/**
* Registers the given {@link CdiRepositoryBean} for further general treatment by the infrastructure. In particular,
* this will cause repositories to be instantiated eagerly if marked as such.
*
* @param bean must not be {@literal null}.
* @see #afterDeploymentValidation(AfterDeploymentValidation, BeanManager)
*/
protected void registerBean(CdiRepositoryBean<?> bean) {
Class<?> repositoryInterface = bean.getBeanClass();
if (AnnotationUtils.findAnnotation(repositoryInterface, Eager.class) != null) {
this.eagerRepositories.add(bean);
}
}
@SuppressWarnings("all")
static class DefaultAnnotationLiteral extends AnnotationLiteral<Default> implements Default {

37
src/main/java/org/springframework/data/repository/cdi/Eager.java

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
/*
* 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.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to mark repository interfaces to be instantiated eagerly in a CDI context.
*
* @author Oliver Gierke
* @since 1.7
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Inherited
public @interface Eager {
}

4
src/test/java/org/springframework/data/repository/cdi/DummyCdiExtension.java

@ -40,7 +40,9 @@ public class DummyCdiExtension extends CdiRepositoryExtensionSupport { @@ -40,7 +40,9 @@ public class DummyCdiExtension extends CdiRepositoryExtensionSupport {
@SuppressWarnings({ "rawtypes", "unchecked" })
void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) {
for (Entry<Class<?>, Set<Annotation>> type : getRepositoryTypes()) {
afterBeanDiscovery.addBean(new DummyCdiRepositoryBean(type.getValue(), type.getKey(), beanManager));
DummyCdiRepositoryBean bean = new DummyCdiRepositoryBean(type.getValue(), type.getKey(), beanManager);
registerBean(bean);
afterBeanDiscovery.addBean(bean);
}
}

Loading…
Cancel
Save