diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfiguration.java index 531e9246b6..8b1c9e8e74 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastAutoConfiguration.java @@ -24,18 +24,14 @@ import com.hazelcast.core.HazelcastInstance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; -import org.springframework.boot.autoconfigure.data.jpa.EntityManagerFactoryDependsOnPostProcessor; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.Resource; -import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; /** * {@link EnableAutoConfiguration Auto-configuration} for Hazelcast. Creates a @@ -82,18 +78,6 @@ public class HazelcastAutoConfiguration { } - @Configuration - @ConditionalOnClass(LocalContainerEntityManagerFactoryBean.class) - @ConditionalOnBean(AbstractEntityManagerFactoryBean.class) - protected static class HazelcastInstanceJpaDependencyConfiguration - extends EntityManagerFactoryDependsOnPostProcessor { - - public HazelcastInstanceJpaDependencyConfiguration() { - super("hazelcastInstance"); - } - - } - /** * {@link HazelcastConfigResourceCondition} that checks if the * {@code spring.hazelcast.config} configuration key is defined. diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastJpaDependencyAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastJpaDependencyAutoConfiguration.java new file mode 100644 index 0000000000..29251db18d --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastJpaDependencyAutoConfiguration.java @@ -0,0 +1,79 @@ +/* + * Copyright 2012-2015 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.boot.autoconfigure.hazelcast; + +import javax.persistence.EntityManagerFactory; + +import com.hazelcast.core.HazelcastInstance; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.AllNestedConditions; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.data.jpa.EntityManagerFactoryDependsOnPostProcessor; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; +import org.springframework.orm.jpa.AbstractEntityManagerFactoryBean; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; + +/** + * Additional configuration to ensure that {@link EntityManagerFactory} beans + * depend-on the {@code hazelcastInstance} bean. + * + * @author Stephane Nicoll + * @since 1.3.0 + */ +@Configuration +@ConditionalOnClass({ HazelcastInstance.class, LocalContainerEntityManagerFactoryBean.class }) +@AutoConfigureAfter({ HazelcastAutoConfiguration.class, HibernateJpaAutoConfiguration.class }) +class HazelcastJpaDependencyAutoConfiguration { + + @Bean + @Conditional(OnHazelcastAndJpaCondition.class) + public static HazelcastInstanceJpaDependencyPostProcessor hazelcastInstanceJpaDependencyPostProcessor() { + return new HazelcastInstanceJpaDependencyPostProcessor(); + } + + private static class HazelcastInstanceJpaDependencyPostProcessor + extends EntityManagerFactoryDependsOnPostProcessor { + + HazelcastInstanceJpaDependencyPostProcessor() { + super("hazelcastInstance"); + } + } + + static class OnHazelcastAndJpaCondition extends AllNestedConditions { + + OnHazelcastAndJpaCondition() { + super(ConfigurationPhase.REGISTER_BEAN); + } + + @ConditionalOnBean(name = "hazelcastInstance") + static class HasHazelcastInstance { + + } + + @ConditionalOnBean(AbstractEntityManagerFactoryBean.class) + static class HasJpa { + + } + + } + +} diff --git a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories index c3cd466d3b..cdfe4cabbe 100644 --- a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories @@ -36,6 +36,7 @@ org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\ org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\ org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\ org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\ +org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\ org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\ org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastJpaDependencyAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastJpaDependencyAutoConfigurationTests.java new file mode 100644 index 0000000000..95c7837d5c --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/hazelcast/HazelcastJpaDependencyAutoConfigurationTests.java @@ -0,0 +1,128 @@ +/* + * Copyright 2012-2015 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.boot.autoconfigure.hazelcast; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import com.hazelcast.core.HazelcastInstance; +import org.junit.After; +import org.junit.Test; + +import org.springframework.boot.autoconfigure.data.jpa.EntityManagerFactoryDependsOnPostProcessor; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasKey; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link HazelcastJpaDependencyAutoConfiguration}. + * + * @author Stephane Nicoll + */ +public class HazelcastJpaDependencyAutoConfigurationTests { + + private AnnotationConfigApplicationContext context; + + @After + public void closeContext() { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void registrationIfHazelcastInstanceHasRegularBeanName() { + load(HazelcastConfiguration.class); + assertThat(this.context.getBeansOfType(EntityManagerFactoryDependsOnPostProcessor.class), + hasKey("hazelcastInstanceJpaDependencyPostProcessor")); + assertThat(getEntityManagerFactoryDependencies(), hasItem("hazelcastInstance")); + } + + @Test + public void noRegistrationIfHazelcastInstanceHasCustomBeanName() { + load(HazelcastCustomNameConfiguration.class); + assertThat(getEntityManagerFactoryDependencies(), not(hasItem("hazelcastInstance"))); + assertThat(this.context.getBeansOfType(EntityManagerFactoryDependsOnPostProcessor.class), + not(hasKey("hazelcastInstanceJpaDependencyPostProcessor"))); + } + + @Test + public void noRegistrationWithNoHazelcastInstance() { + load(null); + assertThat(getEntityManagerFactoryDependencies(), not(hasItem("hazelcastInstance"))); + assertThat(this.context.getBeansOfType(EntityManagerFactoryDependsOnPostProcessor.class), + not(hasKey("hazelcastInstanceJpaDependencyPostProcessor"))); + } + + @Test + public void noRegistrationWithNoEntityManagerFactory() { + this.context = new AnnotationConfigApplicationContext(); + this.context.register(HazelcastConfiguration.class, + HazelcastJpaDependencyAutoConfiguration.class); + this.context.refresh(); + assertThat(this.context.getBeansOfType(EntityManagerFactoryDependsOnPostProcessor.class), + not(hasKey("hazelcastInstanceJpaDependencyPostProcessor"))); + } + + private List getEntityManagerFactoryDependencies() { + String[] dependsOn = this.context.getBeanDefinition("entityManagerFactory").getDependsOn(); + return dependsOn != null ? Arrays.asList(dependsOn) : Collections.emptyList(); + } + + public void load(Class config) { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + if (config != null) { + ctx.register(config); + } + ctx.register(EmbeddedDataSourceConfiguration.class, + DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class); + ctx.register(HazelcastJpaDependencyAutoConfiguration.class); + ctx.refresh(); + this.context = ctx; + } + + @Configuration + static class HazelcastConfiguration { + + @Bean + public HazelcastInstance hazelcastInstance() { + return mock(HazelcastInstance.class); + } + + } + + @Configuration + static class HazelcastCustomNameConfiguration { + + @Bean + public HazelcastInstance myHazelcastInstance() { + return mock(HazelcastInstance.class); + } + + } + +}