diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/init/AbstractRepositoryPopulatorFactoryBean.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/init/AbstractRepositoryPopulatorFactoryBean.java index 8dee29d61..06b4f0f99 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/init/AbstractRepositoryPopulatorFactoryBean.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/init/AbstractRepositoryPopulatorFactoryBean.java @@ -17,10 +17,13 @@ package org.springframework.data.repository.init; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.core.io.Resource; import org.springframework.data.repository.support.Repositories; +import org.springframework.util.Assert; /** * Base class for {@link FactoryBean}s creating {@link ResourceReaderRepositoryPopulator}s. Sub-classes have to provide @@ -29,20 +32,31 @@ import org.springframework.data.repository.support.Repositories; * @author Oliver Gierke */ public abstract class AbstractRepositoryPopulatorFactoryBean extends - AbstractFactoryBean implements ApplicationListener { + AbstractFactoryBean implements ApplicationListener, + ApplicationEventPublisherAware { private Resource[] resources; private RepositoryPopulator populator; + private ApplicationEventPublisher publisher; /** * Configures the {@link Resource}s to be used to load objects from and initialize the repositories eventually. * - * @param resources the resources to set + * @param resources must not be {@literal null}. */ public void setResources(Resource[] resources) { + Assert.notNull(resources, "Resources must not be null!"); this.resources = resources.clone(); } + /* + * (non-Javadoc) + * @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher(org.springframework.context.ApplicationEventPublisher) + */ + public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { + this.publisher = publisher; + } + /* * (non-Javadoc) * @see org.springframework.beans.factory.config.AbstractFactoryBean#getObjectType() @@ -61,6 +75,7 @@ public abstract class AbstractRepositoryPopulatorFactoryBean extends ResourceReaderRepositoryPopulator initializer = new ResourceReaderRepositoryPopulator(getResourceReader()); initializer.setResources(resources); + initializer.setApplicationEventPublisher(publisher); this.populator = initializer; diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/init/RepositoriesPopulatedEvent.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/init/RepositoriesPopulatedEvent.java new file mode 100644 index 000000000..d819932f7 --- /dev/null +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/init/RepositoriesPopulatedEvent.java @@ -0,0 +1,102 @@ +/* + * Copyright 2012 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.init; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationEvent; +import org.springframework.data.repository.support.Repositories; +import org.springframework.util.Assert; + +/** + * {@link ApplicationEvent} being thrown after a {@link RepositoryPopulator} has finished populating the + * {@link Repositories} available in the {@link ApplicationContext}. + * + * @author Oliver Gierke + */ +public class RepositoriesPopulatedEvent extends ApplicationEvent { + + private static final long serialVersionUID = 7449982118828889097L; + + private final Repositories repositories; + + /** + * Creates a new {@link RepositoriesPopulatedEvent} using the given {@link RepositoryPopulator} and + * {@link Repositories}. + * + * @param populator the {@link RepositoryPopulator} that threw the event, must not be {@literal null}. + * @param repositories the {@link Repositories} that were populated, must not be {@literal null}. + */ + public RepositoriesPopulatedEvent(RepositoryPopulator populator, Repositories repositories) { + + super(populator); + + Assert.notNull(populator); + Assert.notNull(repositories); + + this.repositories = repositories; + } + + /* + * (non-Javadoc) + * @see java.util.EventObject#getSource() + */ + @Override + public RepositoryPopulator getSource() { + return (RepositoryPopulator) super.getSource(); + } + + /** + * Returns the {@link Repositories} that were populated. + * + * @return the repositories will never be {@literal null}. + */ + public Repositories getRepositories() { + return repositories; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + + if (this == obj) { + return true; + } + + if (obj == null || !getClass().equals(obj.getClass())) { + return false; + } + + RepositoriesPopulatedEvent that = (RepositoriesPopulatedEvent) obj; + return this.source.equals(that.source) && this.repositories.equals(that.repositories); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + + int result = 17; + result += 31 * source.hashCode(); + result += 31 * repositories.hashCode(); + + return result; + } +} diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/init/ResourceReaderRepositoryPopulator.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/init/ResourceReaderRepositoryPopulator.java index 4ccdc019e..d36f802c0 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/init/ResourceReaderRepositoryPopulator.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/init/ResourceReaderRepositoryPopulator.java @@ -22,6 +22,8 @@ import java.util.Collection; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; @@ -35,7 +37,7 @@ import org.springframework.util.Assert; * @author Oliver Gierke * @since 1.4 */ -public class ResourceReaderRepositoryPopulator implements RepositoryPopulator { +public class ResourceReaderRepositoryPopulator implements RepositoryPopulator, ApplicationEventPublisherAware { private static final Log LOG = LogFactory.getLog(ResourceReaderRepositoryPopulator.class); @@ -43,6 +45,7 @@ public class ResourceReaderRepositoryPopulator implements RepositoryPopulator { private final ResourceReader reader; private final ClassLoader classLoader; + private ApplicationEventPublisher publisher; private Collection resources; /** @@ -91,6 +94,14 @@ public class ResourceReaderRepositoryPopulator implements RepositoryPopulator { this.resources = Arrays.asList(resources); } + /* + * (non-Javadoc) + * @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher(org.springframework.context.ApplicationEventPublisher) + */ + public void setApplicationEventPublisher(ApplicationEventPublisher publisher) { + this.publisher = publisher; + } + /* * (non-Javadoc) * @see org.springframework.data.repository.init.RepositoryPopulator#initialize() @@ -115,6 +126,10 @@ public class ResourceReaderRepositoryPopulator implements RepositoryPopulator { persist(result, repositories); } } + + if (publisher != null) { + publisher.publishEvent(new RepositoriesPopulatedEvent(this, repositories)); + } } /** diff --git a/spring-data-commons-core/src/test/java/org/springframework/data/repository/init/ResourceReaderRepositoryInitializerUnitTests.java b/spring-data-commons-core/src/test/java/org/springframework/data/repository/init/ResourceReaderRepositoryInitializerUnitTests.java index 0bea8b790..bce48d569 100644 --- a/spring-data-commons-core/src/test/java/org/springframework/data/repository/init/ResourceReaderRepositoryInitializerUnitTests.java +++ b/spring-data-commons-core/src/test/java/org/springframework/data/repository/init/ResourceReaderRepositoryInitializerUnitTests.java @@ -26,6 +26,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.core.io.Resource; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.support.Repositories; @@ -47,6 +49,9 @@ public class ResourceReaderRepositoryInitializerUnitTests { @Mock CrudRepository repo; + @Mock + ApplicationEventPublisher publisher; + @Test public void storesSingleObjectCorrectly() throws Exception { @@ -68,13 +73,33 @@ public class ResourceReaderRepositoryInitializerUnitTests { verify(repo, times(1)).save(object); } - private void setUpReferenceAndInititalize(Object reference) throws Exception { + /** + * @see DATACMNS-224 + */ + @Test + public void emitsRepositoriesPopulatedEventIfPublisherConfigured() throws Exception { + + RepositoryPopulator populator = setUpReferenceAndInititalize(new Object(), publisher); + + ApplicationEvent event = new RepositoriesPopulatedEvent(populator, repositories); + verify(publisher, times(1)).publishEvent(event); + } + + private RepositoryPopulator setUpReferenceAndInititalize(Object reference, ApplicationEventPublisher publish) + throws Exception { when(reader.readFrom(any(Resource.class), any(ClassLoader.class))).thenReturn(reference); when(repositories.getRepositoryFor(Object.class)).thenReturn(repo); - ResourceReaderRepositoryPopulator initializer = new ResourceReaderRepositoryPopulator(reader); - initializer.setResources(resource); - initializer.populate(repositories); + ResourceReaderRepositoryPopulator populator = new ResourceReaderRepositoryPopulator(reader); + populator.setResources(resource); + populator.setApplicationEventPublisher(publisher); + populator.populate(repositories); + + return populator; + } + + private RepositoryPopulator setUpReferenceAndInititalize(Object reference) throws Exception { + return setUpReferenceAndInititalize(reference, null); } }