From 6ed69709d7d34087a7a37c97840081619fe14571 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 28 Apr 2014 07:45:19 +0200 Subject: [PATCH 1/4] Add auto configuration support for Spring Data Solr Registers required components in application context if not available to set up environment for usage with Spring Data Solr. Will listen on SolrServer and SolrRepositories for configuration. By default an HttpSolrServer is registered unless a zkHost (zookeeper host) is defined. In that case an instance of CloudSolrServer will be created. By default multicore support is enabled, creating instances of SolrServer for each core defined via @SolrDocument. --- spring-boot-autoconfigure/pom.xml | 10 ++ .../SolrRepositoriesAutoConfiguration.java | 48 ++++++++ ...SolrRepositoriesAutoConfigureRegstrar.java | 73 +++++++++++++ .../solr/SolrAutoConfiguration.java | 68 ++++++++++++ .../autoconfigure/solr/SolrProperties.java | 49 +++++++++ .../main/resources/META-INF/spring.factories | 2 + ...JpaRepositoriesAutoConfigurationTests.java | 7 +- ...olrRepositoriesAutoConfigurationTests.java | 92 ++++++++++++++++ .../data/alt/CitySolrRepository.java | 26 +++++ .../boot/autoconfigure/data/solr/City.java | 47 ++++++++ .../data/solr/CityRepository.java | 28 +++++ spring-boot-dependencies/pom.xml | 6 + spring-boot-samples/pom.xml | 1 + .../spring-boot-sample-data-solr/pom.xml | 42 +++++++ .../main/java/sample/data/solr/Product.java | 103 ++++++++++++++++++ .../sample/data/solr/ProductRepository.java | 30 +++++ .../data/solr/SampleSolrApplication.java | 68 ++++++++++++ .../data/solr/SampleSolrApplicationTests.java | 62 +++++++++++ spring-boot-starters/pom.xml | 1 + .../spring-boot-starter-data-solr/pom.xml | 35 ++++++ .../main/resources/META-INF/spring.provides | 1 + 21 files changed, 797 insertions(+), 2 deletions(-) create mode 100644 spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfiguration.java create mode 100644 spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigureRegstrar.java create mode 100644 spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrAutoConfiguration.java create mode 100644 spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrProperties.java create mode 100644 spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigurationTests.java create mode 100644 spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/alt/CitySolrRepository.java create mode 100644 spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/City.java create mode 100644 spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/CityRepository.java create mode 100644 spring-boot-samples/spring-boot-sample-data-solr/pom.xml create mode 100644 spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/Product.java create mode 100644 spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/ProductRepository.java create mode 100644 spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/SampleSolrApplication.java create mode 100644 spring-boot-samples/spring-boot-sample-data-solr/src/test/java/sample/data/solr/SampleSolrApplicationTests.java create mode 100644 spring-boot-starters/spring-boot-starter-data-solr/pom.xml create mode 100644 spring-boot-starters/spring-boot-starter-data-solr/src/main/resources/META-INF/spring.provides diff --git a/spring-boot-autoconfigure/pom.xml b/spring-boot-autoconfigure/pom.xml index 3f07add763..b95bfb217c 100644 --- a/spring-boot-autoconfigure/pom.xml +++ b/spring-boot-autoconfigure/pom.xml @@ -56,6 +56,11 @@ activemq-pool true + + org.apache.solr + solr-solrj + true + org.apache.tomcat.embed tomcat-embed-core @@ -171,6 +176,11 @@ spring-data-redis true + + org.springframework.data + spring-data-solr + true + org.springframework.hateoas spring-hateoas diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfiguration.java new file mode 100644 index 0000000000..2fa95b9984 --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfiguration.java @@ -0,0 +1,48 @@ +/* + * 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.boot.autoconfigure.data; + +import org.apache.solr.client.solrj.SolrServer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.data.solr.repository.SolrRepository; +import org.springframework.data.solr.repository.support.SolrRepositoryFactoryBean; + +/** + * Enables auto configuration for Spring Data Solr repositories. + *

+ * Activates when there is no bean of type + * {@link org.springframework.data.solr.repository.support.SolrRepositoryFactoryBean} + * found in context, and both + * {@link org.springframework.data.solr.repository.SolrRepository} and + * {@link org.apache.solr.client.solrj.SolrServer} can be found on classpath. + *

+ * If active auto configuration does the same as + * {@link org.springframework.data.solr.repository.config.EnableSolrRepositories} would + * do. + * + * @author Christoph Strobl + */ +@Configuration +@ConditionalOnClass({ SolrServer.class, SolrRepository.class }) +@ConditionalOnMissingBean(SolrRepositoryFactoryBean.class) +@Import(SolrRepositoriesAutoConfigureRegstrar.class) +public class SolrRepositoriesAutoConfiguration { + +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigureRegstrar.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigureRegstrar.java new file mode 100644 index 0000000000..b63badcdf8 --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigureRegstrar.java @@ -0,0 +1,73 @@ +/* + * 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.boot.autoconfigure.data; + +import java.lang.annotation.Annotation; + +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.data.repository.config.RepositoryConfigurationExtension; +import org.springframework.data.solr.repository.config.EnableSolrRepositories; +import org.springframework.data.solr.repository.config.SolrRepositoryConfigExtension; + +/** + * {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data Solr + * repositories. + * + * @author Christoph Strobl + */ +public class SolrRepositoriesAutoConfigureRegstrar extends + AbstractRepositoryConfigurationSourceSupport { + + /* + * (non-Javadoc) + * + * @see org.springframework.boot.autoconfigure.data. + * AbstractRepositoryConfigurationSourceSupport#getAnnotation() + */ + @Override + protected Class getAnnotation() { + return EnableSolrRepositories.class; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.boot.autoconfigure.data. + * AbstractRepositoryConfigurationSourceSupport#getConfiguration() + */ + @Override + protected Class getConfiguration() { + return EnableSolrRepositoriesConfiguration.class; + } + + /* + * (non-Javadoc) + * + * @see org.springframework.boot.autoconfigure.data. + * AbstractRepositoryConfigurationSourceSupport#getRepositoryConfigurationExtension() + */ + @Override + protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() { + return new SolrRepositoryConfigExtension(); + } + + @EnableSolrRepositories(multicoreSupport = true) + private static class EnableSolrRepositoriesConfiguration { + + } + +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrAutoConfiguration.java new file mode 100644 index 0000000000..2e8b66035a --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrAutoConfiguration.java @@ -0,0 +1,68 @@ +/* + * 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.boot.autoconfigure.solr; + +import javax.annotation.PreDestroy; + +import org.apache.solr.client.solrj.SolrServer; +import org.apache.solr.client.solrj.impl.CloudSolrServer; +import org.apache.solr.client.solrj.impl.HttpSolrServer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.util.StringUtils; + +/** + * Enables auto configuration for Solr. + * + * @author Christoph Strobl + */ +@Configuration +@ConditionalOnClass(SolrServer.class) +@EnableConfigurationProperties(SolrProperties.class) +public class SolrAutoConfiguration { + + private @Autowired SolrProperties properties; + + private SolrServer solrServer; + + @PreDestroy + public void close() { + if (this.solrServer != null) { + this.solrServer.shutdown(); + } + } + + @Bean + @ConditionalOnMissingBean + public SolrServer solrServer() { + + this.solrServer = createSolrServer(); + return this.solrServer; + } + + private SolrServer createSolrServer() { + + if (StringUtils.hasText(this.properties.getZkHost())) { + return new CloudSolrServer(this.properties.getZkHost()); + } + return new HttpSolrServer(this.properties.getHost()); + } +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrProperties.java new file mode 100644 index 0000000000..83de83c5b4 --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrProperties.java @@ -0,0 +1,49 @@ +/* + * 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.boot.autoconfigure.solr; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Configuration properties for Solr. + * + * @author Christoph Strobl + */ +@ConfigurationProperties(prefix = "spring.data.solr") +public class SolrProperties { + + private String host = "http://127.0.0.1:8983/solr"; + + private String zkHost; + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public String getZkHost() { + return zkHost; + } + + public void setZkHost(String zkHost) { + this.zkHost = zkHost; + } + +} 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 cdd3343ee3..d62e1de642 100644 --- a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories @@ -11,6 +11,7 @@ org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration,\ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.boot.autoconfigure.data.JpaRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.MongoRepositoriesAutoConfiguration,\ +org.springframework.boot.autoconfigure.data.SolrRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\ org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\ @@ -31,6 +32,7 @@ org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\ org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration,\ org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\ org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\ +org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\ org.springframework.boot.autoconfigure.velocity.VelocityAutoConfiguration,\ org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\ org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\ diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/JpaRepositoriesAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/JpaRepositoriesAutoConfigurationTests.java index f902d330ef..9a84d3f0bd 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/JpaRepositoriesAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/JpaRepositoriesAutoConfigurationTests.java @@ -22,6 +22,7 @@ import org.junit.Test; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; import org.springframework.boot.autoconfigure.data.alt.CityMongoDbRepository; +import org.springframework.boot.autoconfigure.data.alt.CitySolrRepository; import org.springframework.boot.autoconfigure.data.jpa.City; import org.springframework.boot.autoconfigure.data.jpa.CityRepository; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration; @@ -81,8 +82,10 @@ public class JpaRepositoriesAutoConfigurationTests { } @Configuration - @EnableJpaRepositories(basePackageClasses = org.springframework.boot.autoconfigure.data.alt.CityJpaRepository.class, excludeFilters = { @Filter(type = FilterType.ASSIGNABLE_TYPE, value = CityMongoDbRepository.class) }) - @TestAutoConfigurationPackage(City.class) + @EnableJpaRepositories(basePackageClasses = org.springframework.boot.autoconfigure.data.alt.CityJpaRepository.class, excludeFilters = { + @Filter(type = FilterType.ASSIGNABLE_TYPE, value = CityMongoDbRepository.class), + @Filter(type = FilterType.ASSIGNABLE_TYPE, value = CitySolrRepository.class) }) + @TestAutoConfigurationPackage(City.class) protected static class CustomConfiguration { } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigurationTests.java new file mode 100644 index 0000000000..476c520ee3 --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigurationTests.java @@ -0,0 +1,92 @@ +/* + * 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.boot.autoconfigure.data; + +import static org.hamcrest.core.IsInstanceOf.*; +import static org.hamcrest.core.IsNull.*; +import static org.junit.Assert.*; + +import org.apache.solr.client.solrj.SolrServer; +import org.apache.solr.client.solrj.impl.HttpSolrServer; +import org.junit.Test; +import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; +import org.springframework.boot.autoconfigure.data.alt.CitySolrRepository; +import org.springframework.boot.autoconfigure.data.solr.City; +import org.springframework.boot.autoconfigure.data.solr.CityRepository; +import org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.solr.repository.config.EnableSolrRepositories; + +/** + * @author Christoph Strobl + */ +public class SolrRepositoriesAutoConfigurationTests { + + private AnnotationConfigApplicationContext context; + + @Test + public void testDefaultRepositoryConfiguration() { + + initContext(TestConfiguration.class); + + assertThat(this.context.getBean(CityRepository.class), notNullValue()); + assertThat(this.context.getBean(SolrServer.class), instanceOf(HttpSolrServer.class)); + } + + @Test + public void testNoRepositoryConfiguration() { + + initContext(EmptyConfiguration.class); + assertThat(this.context.getBean(SolrServer.class), instanceOf(HttpSolrServer.class)); + } + + @Test + public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() { + + initContext(CustomizedConfiguration.class); + assertThat(this.context.getBean(CitySolrRepository.class), notNullValue()); + } + + private void initContext(Class configClass) { + + this.context = new AnnotationConfigApplicationContext(); + this.context.register(configClass, SolrAutoConfiguration.class, SolrRepositoriesAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class); + this.context.refresh(); + } + + @Configuration + @TestAutoConfigurationPackage(City.class) + static class TestConfiguration { + + } + + @Configuration + @TestAutoConfigurationPackage(SolrRepositoriesAutoConfigurationTests.class) + static class EmptyConfiguration { + + } + + @Configuration + @TestAutoConfigurationPackage(SolrRepositoriesAutoConfigurationTests.class) + @EnableSolrRepositories(basePackageClasses = CitySolrRepository.class, multicoreSupport = true) + protected static class CustomizedConfiguration { + + } + +} diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/alt/CitySolrRepository.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/alt/CitySolrRepository.java new file mode 100644 index 0000000000..750b3c60ac --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/alt/CitySolrRepository.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.boot.autoconfigure.data.alt; + +import org.springframework.boot.autoconfigure.data.solr.City; +import org.springframework.data.repository.Repository; + +/** + * @author Christoph Strobl + */ +public interface CitySolrRepository extends Repository { + +} diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/City.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/City.java new file mode 100644 index 0000000000..9d4584b163 --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/City.java @@ -0,0 +1,47 @@ +/* + * 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.boot.autoconfigure.data.solr; + +import org.springframework.data.annotation.Id; +import org.springframework.data.solr.core.mapping.Indexed; +import org.springframework.data.solr.core.mapping.SolrDocument; + +/** + * @author Christoph Strobl + */ +@SolrDocument(solrCoreName = "collection1") +public class City { + + private @Id String id; + private @Indexed String name; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/CityRepository.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/CityRepository.java new file mode 100644 index 0000000000..05cf4bd96f --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/CityRepository.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.boot.autoconfigure.data.solr; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.repository.Repository; + +/** + * @author Christoph Strobl + */ +public interface CityRepository extends Repository { + + Page findByNameStartingWith(String name, Pageable page); +} diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml index ad640f1d06..9381ea3a65 100644 --- a/spring-boot-dependencies/pom.xml +++ b/spring-boot-dependencies/pom.xml @@ -87,6 +87,7 @@ 3.0.1 1.7.7 1.13 + 4.7.2 0.7-groovy-2.0 4.0.5.RELEASE 1.3.3.RELEASE @@ -770,6 +771,11 @@ slf4j-log4j12 ${slf4j.version}
+ + org.apache.solr + solr-solrj + ${solr.version} + org.spockframework spock-core diff --git a/spring-boot-samples/pom.xml b/spring-boot-samples/pom.xml index 8fc94ae5ee..9c223a3b2d 100644 --- a/spring-boot-samples/pom.xml +++ b/spring-boot-samples/pom.xml @@ -32,6 +32,7 @@ spring-boot-sample-data-mongodb spring-boot-sample-data-redis spring-boot-sample-data-rest + spring-boot-sample-data-solr spring-boot-sample-flyway spring-boot-sample-integration spring-boot-sample-jetty diff --git a/spring-boot-samples/spring-boot-sample-data-solr/pom.xml b/spring-boot-samples/spring-boot-sample-data-solr/pom.xml new file mode 100644 index 0000000000..6a174cadef --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-data-solr/pom.xml @@ -0,0 +1,42 @@ + + 4.0.0 + + org.springframework.boot + spring-boot-samples + 1.1.0.BUILD-SNAPSHOT + + spring-boot-sample-data-solr + Spring Boot Data Solr Sample + Spring Boot Data Solr Sample + http://projects.spring.io/spring-boot/ + + Pivotal Software, Inc. + http://www.spring.io + + + ${basedir}/../.. + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-data-solr + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/Product.java b/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/Product.java new file mode 100644 index 0000000000..a91a3f8c96 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/Product.java @@ -0,0 +1,103 @@ +/* + * 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 sample.data.solr; + +import java.util.List; + +import org.apache.solr.client.solrj.beans.Field; +import org.springframework.data.annotation.Id; +import org.springframework.data.solr.core.geo.Point; +import org.springframework.data.solr.core.mapping.SolrDocument; + +/** + * @author Christoph Strobl + */ +@SolrDocument(solrCoreName = "collection1") +public class Product { + + @Id + @Field + private String id; + + @Field + private String name; + + @Field + private Double price; + + @Field("cat") + private List category; + + @Field("store") + private Point location; + + public Product() { + } + + public Product(String id, String name) { + super(); + this.id = id; + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Double getPrice() { + return price; + } + + public void setPrice(Double price) { + this.price = price; + } + + public List getCategory() { + return category; + } + + public void setCategory(List category) { + this.category = category; + } + + public Point getLocation() { + return location; + } + + public void setLocation(Point location) { + this.location = location; + } + + @Override + public String toString() { + return "Product [id=" + id + ", name=" + name + ", price=" + price + + ", category=" + category + ", location=" + location + "]"; + } + +} diff --git a/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/ProductRepository.java b/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/ProductRepository.java new file mode 100644 index 0000000000..e5c5b926b8 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/ProductRepository.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 sample.data.solr; + +import java.util.List; + +import org.springframework.data.solr.repository.SolrCrudRepository; + +/** + * @author Christoph Strobl + */ +public interface ProductRepository extends SolrCrudRepository { + + List findByNameStartingWith(String name); + +} diff --git a/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/SampleSolrApplication.java b/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/SampleSolrApplication.java new file mode 100644 index 0000000000..825c787d18 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/SampleSolrApplication.java @@ -0,0 +1,68 @@ +/* + * 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 sample.data.solr; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +/** + * @author Christoph Strobl + */ +@Configuration +@EnableAutoConfiguration +@ComponentScan +public class SampleSolrApplication implements CommandLineRunner { + + @Autowired + private ProductRepository repository; + + @Override + public void run(String... args) throws Exception { + + repository.deleteAll(); + + // insert some products + repository.save(new Product("1", "Nintendo Entertainment System")); + repository.save(new Product("2", "Sega Megadrive")); + repository.save(new Product("3", "Sony Playstation")); + + // fetch all + System.out.println("Products found by findAll():"); + System.out.println("----------------------------"); + for (Product product : repository.findAll()) { + System.out.println(product); + } + System.out.println(); + + // fetch a single product + System.out.println("Products founds with findByNameStartingWith('So'):"); + System.out.println("--------------------------------"); + for (Product product : repository.findByNameStartingWith("So")) { + System.out.println(product); + } + System.out.println(); + } + + public static void main(String[] args) throws Exception { + SpringApplication.run(SampleSolrApplication.class, args); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-data-solr/src/test/java/sample/data/solr/SampleSolrApplicationTests.java b/spring-boot-samples/spring-boot-sample-data-solr/src/test/java/sample/data/solr/SampleSolrApplicationTests.java new file mode 100644 index 0000000000..2361d5b64d --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-data-solr/src/test/java/sample/data/solr/SampleSolrApplicationTests.java @@ -0,0 +1,62 @@ +/* + * 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 sample.data.solr; + +import static org.junit.Assert.*; + +import org.apache.solr.client.solrj.SolrServerException; +import org.junit.Rule; +import org.junit.Test; +import org.springframework.boot.test.OutputCapture; +import org.springframework.core.NestedCheckedException; + +/** + * @author Christoph Strobl + */ +public class SampleSolrApplicationTests { + + @Rule + public OutputCapture outputCapture = new OutputCapture(); + + @Test + public void testDefaultSettings() throws Exception { + + try { + SampleSolrApplication.main(new String[0]); + } catch (IllegalStateException ex) { + if (serverNotRunning(ex)) { + return; + } + } + String output = this.outputCapture.toString(); + assertTrue("Wrong output: " + output, output.contains("name=Sony Playstation")); + } + + private boolean serverNotRunning(IllegalStateException ex) { + + @SuppressWarnings("serial") + NestedCheckedException nested = new NestedCheckedException("failed", ex) { + }; + if (nested.contains(SolrServerException.class)) { + Throwable root = nested.getRootCause(); + if (root.getMessage().contains("Connection refused")) { + return true; + } + } + return false; + } +} diff --git a/spring-boot-starters/pom.xml b/spring-boot-starters/pom.xml index 65a2fe3442..8f14737914 100644 --- a/spring-boot-starters/pom.xml +++ b/spring-boot-starters/pom.xml @@ -28,6 +28,7 @@ spring-boot-starter-data-jpa spring-boot-starter-data-mongodb spring-boot-starter-data-rest + spring-boot-starter-data-solr spring-boot-starter-freemarker spring-boot-starter-integration spring-boot-starter-jdbc diff --git a/spring-boot-starters/spring-boot-starter-data-solr/pom.xml b/spring-boot-starters/spring-boot-starter-data-solr/pom.xml new file mode 100644 index 0000000000..205c2eebba --- /dev/null +++ b/spring-boot-starters/spring-boot-starter-data-solr/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starters + 1.1.0.BUILD-SNAPSHOT + + spring-boot-starter-data-solr + Spring Boot Data Solr Starter + Spring Boot Data Solr Starter + http://projects.spring.io/spring-boot/ + + Pivotal Software, Inc. + http://www.spring.io + + + ${basedir}/../.. + + + + ${project.groupId} + spring-boot-starter + ${project.version} + + + org.apache.solr + solr-solrj + + + org.springframework.data + spring-data-solr + + + diff --git a/spring-boot-starters/spring-boot-starter-data-solr/src/main/resources/META-INF/spring.provides b/spring-boot-starters/spring-boot-starter-data-solr/src/main/resources/META-INF/spring.provides new file mode 100644 index 0000000000..7c307abea5 --- /dev/null +++ b/spring-boot-starters/spring-boot-starter-data-solr/src/main/resources/META-INF/spring.provides @@ -0,0 +1 @@ +provides: spring-data-solr, solr-solrj \ No newline at end of file From e45ef06b56a1edbc01b2fb42aa535c324e417b82 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 22 May 2014 08:45:41 +0100 Subject: [PATCH 2/4] Polish Spring Data Solr integration --- .../SolrRepositoriesAutoConfiguration.java | 7 +++--- ...lrRepositoriesAutoConfigureRegistrar.java} | 25 +++---------------- .../solr/SolrAutoConfiguration.java | 13 +++++----- .../autoconfigure/solr/SolrProperties.java | 9 ++++--- ...JpaRepositoriesAutoConfigurationTests.java | 8 +++--- ...olrRepositoriesAutoConfigurationTests.java | 24 ++++++++++-------- .../boot/autoconfigure/data/solr/City.java | 7 +++--- .../data/solr/CityRepository.java | 3 ++- spring-boot-dependencies/pom.xml | 5 ++++ .../main/java/sample/data/solr/Product.java | 19 ++++++-------- .../sample/data/solr/ProductRepository.java | 5 +--- .../data/solr/SampleSolrApplication.java | 17 ++++++------- .../data/solr/SampleSolrApplicationTests.java | 21 ++++++---------- 13 files changed, 72 insertions(+), 91 deletions(-) rename spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/{SolrRepositoriesAutoConfigureRegstrar.java => SolrRepositoriesAutoConfigureRegistrar.java} (73%) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfiguration.java index 2fa95b9984..588ff956d3 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2012-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. @@ -36,13 +36,14 @@ import org.springframework.data.solr.repository.support.SolrRepositoryFactoryBea * If active auto configuration does the same as * {@link org.springframework.data.solr.repository.config.EnableSolrRepositories} would * do. - * + * * @author Christoph Strobl + * @since 1.1.0 */ @Configuration @ConditionalOnClass({ SolrServer.class, SolrRepository.class }) @ConditionalOnMissingBean(SolrRepositoryFactoryBean.class) -@Import(SolrRepositoriesAutoConfigureRegstrar.class) +@Import(SolrRepositoriesAutoConfigureRegistrar.class) public class SolrRepositoriesAutoConfiguration { } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigureRegstrar.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigureRegistrar.java similarity index 73% rename from spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigureRegstrar.java rename to spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigureRegistrar.java index b63badcdf8..231761167f 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigureRegstrar.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigureRegistrar.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2012-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. @@ -26,40 +26,23 @@ import org.springframework.data.solr.repository.config.SolrRepositoryConfigExten /** * {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data Solr * repositories. - * + * * @author Christoph Strobl + * @since 1.1.0 */ -public class SolrRepositoriesAutoConfigureRegstrar extends +public class SolrRepositoriesAutoConfigureRegistrar extends AbstractRepositoryConfigurationSourceSupport { - /* - * (non-Javadoc) - * - * @see org.springframework.boot.autoconfigure.data. - * AbstractRepositoryConfigurationSourceSupport#getAnnotation() - */ @Override protected Class getAnnotation() { return EnableSolrRepositories.class; } - /* - * (non-Javadoc) - * - * @see org.springframework.boot.autoconfigure.data. - * AbstractRepositoryConfigurationSourceSupport#getConfiguration() - */ @Override protected Class getConfiguration() { return EnableSolrRepositoriesConfiguration.class; } - /* - * (non-Javadoc) - * - * @see org.springframework.boot.autoconfigure.data. - * AbstractRepositoryConfigurationSourceSupport#getRepositoryConfigurationExtension() - */ @Override protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() { return new SolrRepositoryConfigExtension(); diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrAutoConfiguration.java index 2e8b66035a..d9510e2f1f 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2012-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. @@ -22,6 +22,7 @@ import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.impl.CloudSolrServer; import org.apache.solr.client.solrj.impl.HttpSolrServer; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -30,16 +31,18 @@ import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; /** - * Enables auto configuration for Solr. - * + * {@link EnableAutoConfiguration Auto-configuration} for Solr + * * @author Christoph Strobl + * @since 1.1.0 */ @Configuration @ConditionalOnClass(SolrServer.class) @EnableConfigurationProperties(SolrProperties.class) public class SolrAutoConfiguration { - private @Autowired SolrProperties properties; + @Autowired + private SolrProperties properties; private SolrServer solrServer; @@ -53,13 +56,11 @@ public class SolrAutoConfiguration { @Bean @ConditionalOnMissingBean public SolrServer solrServer() { - this.solrServer = createSolrServer(); return this.solrServer; } private SolrServer createSolrServer() { - if (StringUtils.hasText(this.properties.getZkHost())) { return new CloudSolrServer(this.properties.getZkHost()); } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrProperties.java index 83de83c5b4..9055fe1ce1 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/solr/SolrProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2012-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,8 +20,9 @@ import org.springframework.boot.context.properties.ConfigurationProperties; /** * Configuration properties for Solr. - * + * * @author Christoph Strobl + * @since 1.1.0 */ @ConfigurationProperties(prefix = "spring.data.solr") public class SolrProperties { @@ -31,7 +32,7 @@ public class SolrProperties { private String zkHost; public String getHost() { - return host; + return this.host; } public void setHost(String host) { @@ -39,7 +40,7 @@ public class SolrProperties { } public String getZkHost() { - return zkHost; + return this.zkHost; } public void setZkHost(String zkHost) { diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/JpaRepositoriesAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/JpaRepositoriesAutoConfigurationTests.java index 9a84d3f0bd..2df012490b 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/JpaRepositoriesAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/JpaRepositoriesAutoConfigurationTests.java @@ -38,7 +38,7 @@ import static org.junit.Assert.assertNotNull; /** * Tests for {@link JpaRepositoriesAutoConfiguration}. - * + * * @author Dave Syer * @author Oliver Gierke */ @@ -83,9 +83,9 @@ public class JpaRepositoriesAutoConfigurationTests { @Configuration @EnableJpaRepositories(basePackageClasses = org.springframework.boot.autoconfigure.data.alt.CityJpaRepository.class, excludeFilters = { - @Filter(type = FilterType.ASSIGNABLE_TYPE, value = CityMongoDbRepository.class), - @Filter(type = FilterType.ASSIGNABLE_TYPE, value = CitySolrRepository.class) }) - @TestAutoConfigurationPackage(City.class) + @Filter(type = FilterType.ASSIGNABLE_TYPE, value = CityMongoDbRepository.class), + @Filter(type = FilterType.ASSIGNABLE_TYPE, value = CitySolrRepository.class) }) + @TestAutoConfigurationPackage(City.class) protected static class CustomConfiguration { } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigurationTests.java index 476c520ee3..3f3b6d3300 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/SolrRepositoriesAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2012-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. @@ -15,10 +15,6 @@ */ package org.springframework.boot.autoconfigure.data; -import static org.hamcrest.core.IsInstanceOf.*; -import static org.hamcrest.core.IsNull.*; -import static org.junit.Assert.*; - import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.impl.HttpSolrServer; import org.junit.Test; @@ -32,7 +28,13 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext import org.springframework.context.annotation.Configuration; import org.springframework.data.solr.repository.config.EnableSolrRepositories; +import static org.hamcrest.core.IsInstanceOf.instanceOf; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.junit.Assert.assertThat; + /** + * Tests for {@link SolrRepositoriesAutoConfiguration} + * * @author Christoph Strobl */ public class SolrRepositoriesAutoConfigurationTests { @@ -41,23 +43,22 @@ public class SolrRepositoriesAutoConfigurationTests { @Test public void testDefaultRepositoryConfiguration() { - initContext(TestConfiguration.class); assertThat(this.context.getBean(CityRepository.class), notNullValue()); - assertThat(this.context.getBean(SolrServer.class), instanceOf(HttpSolrServer.class)); + assertThat(this.context.getBean(SolrServer.class), + instanceOf(HttpSolrServer.class)); } @Test public void testNoRepositoryConfiguration() { - initContext(EmptyConfiguration.class); - assertThat(this.context.getBean(SolrServer.class), instanceOf(HttpSolrServer.class)); + assertThat(this.context.getBean(SolrServer.class), + instanceOf(HttpSolrServer.class)); } @Test public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() { - initContext(CustomizedConfiguration.class); assertThat(this.context.getBean(CitySolrRepository.class), notNullValue()); } @@ -65,7 +66,8 @@ public class SolrRepositoriesAutoConfigurationTests { private void initContext(Class configClass) { this.context = new AnnotationConfigApplicationContext(); - this.context.register(configClass, SolrAutoConfiguration.class, SolrRepositoriesAutoConfiguration.class, + this.context.register(configClass, SolrAutoConfiguration.class, + SolrRepositoriesAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); this.context.refresh(); } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/City.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/City.java index 9d4584b163..eaa1c0f355 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/City.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/City.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2012-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. @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.boot.autoconfigure.data.solr; import org.springframework.data.annotation.Id; @@ -29,7 +30,7 @@ public class City { private @Indexed String name; public String getId() { - return id; + return this.id; } public void setId(String id) { @@ -37,7 +38,7 @@ public class City { } public String getName() { - return name; + return this.name; } public void setName(String name) { diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/CityRepository.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/CityRepository.java index 05cf4bd96f..f36708a5fd 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/CityRepository.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/solr/CityRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2012-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. @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.boot.autoconfigure.data.solr; import org.springframework.data.domain.Page; diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml index 9381ea3a65..074a5644f1 100644 --- a/spring-boot-dependencies/pom.xml +++ b/spring-boot-dependencies/pom.xml @@ -192,6 +192,11 @@ spring-boot-starter-data-rest 1.1.0.BUILD-SNAPSHOT + + org.springframework.boot + spring-boot-starter-data-solr + 1.1.0.BUILD-SNAPSHOT + org.springframework.boot spring-boot-starter-freemarker diff --git a/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/Product.java b/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/Product.java index a91a3f8c96..53071d17ed 100644 --- a/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/Product.java +++ b/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/Product.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2012-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. @@ -23,9 +23,6 @@ import org.springframework.data.annotation.Id; import org.springframework.data.solr.core.geo.Point; import org.springframework.data.solr.core.mapping.SolrDocument; -/** - * @author Christoph Strobl - */ @SolrDocument(solrCoreName = "collection1") public class Product { @@ -55,7 +52,7 @@ public class Product { } public String getId() { - return id; + return this.id; } public void setId(String id) { @@ -63,7 +60,7 @@ public class Product { } public String getName() { - return name; + return this.name; } public void setName(String name) { @@ -71,7 +68,7 @@ public class Product { } public Double getPrice() { - return price; + return this.price; } public void setPrice(Double price) { @@ -79,7 +76,7 @@ public class Product { } public List getCategory() { - return category; + return this.category; } public void setCategory(List category) { @@ -87,7 +84,7 @@ public class Product { } public Point getLocation() { - return location; + return this.location; } public void setLocation(Point location) { @@ -96,8 +93,8 @@ public class Product { @Override public String toString() { - return "Product [id=" + id + ", name=" + name + ", price=" + price - + ", category=" + category + ", location=" + location + "]"; + return "Product [id=" + this.id + ", name=" + this.name + ", price=" + this.price + + ", category=" + this.category + ", location=" + this.location + "]"; } } diff --git a/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/ProductRepository.java b/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/ProductRepository.java index e5c5b926b8..796779bfc3 100644 --- a/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/ProductRepository.java +++ b/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/ProductRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2012-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,9 +20,6 @@ import java.util.List; import org.springframework.data.solr.repository.SolrCrudRepository; -/** - * @author Christoph Strobl - */ public interface ProductRepository extends SolrCrudRepository { List findByNameStartingWith(String name); diff --git a/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/SampleSolrApplication.java b/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/SampleSolrApplication.java index 825c787d18..1cd4eea8c4 100644 --- a/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/SampleSolrApplication.java +++ b/spring-boot-samples/spring-boot-sample-data-solr/src/main/java/sample/data/solr/SampleSolrApplication.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2012-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. @@ -23,9 +23,6 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -/** - * @author Christoph Strobl - */ @Configuration @EnableAutoConfiguration @ComponentScan @@ -37,17 +34,17 @@ public class SampleSolrApplication implements CommandLineRunner { @Override public void run(String... args) throws Exception { - repository.deleteAll(); + this.repository.deleteAll(); // insert some products - repository.save(new Product("1", "Nintendo Entertainment System")); - repository.save(new Product("2", "Sega Megadrive")); - repository.save(new Product("3", "Sony Playstation")); + this.repository.save(new Product("1", "Nintendo Entertainment System")); + this.repository.save(new Product("2", "Sega Megadrive")); + this.repository.save(new Product("3", "Sony Playstation")); // fetch all System.out.println("Products found by findAll():"); System.out.println("----------------------------"); - for (Product product : repository.findAll()) { + for (Product product : this.repository.findAll()) { System.out.println(product); } System.out.println(); @@ -55,7 +52,7 @@ public class SampleSolrApplication implements CommandLineRunner { // fetch a single product System.out.println("Products founds with findByNameStartingWith('So'):"); System.out.println("--------------------------------"); - for (Product product : repository.findByNameStartingWith("So")) { + for (Product product : this.repository.findByNameStartingWith("So")) { System.out.println(product); } System.out.println(); diff --git a/spring-boot-samples/spring-boot-sample-data-solr/src/test/java/sample/data/solr/SampleSolrApplicationTests.java b/spring-boot-samples/spring-boot-sample-data-solr/src/test/java/sample/data/solr/SampleSolrApplicationTests.java index 2361d5b64d..2bc86666ef 100644 --- a/spring-boot-samples/spring-boot-sample-data-solr/src/test/java/sample/data/solr/SampleSolrApplicationTests.java +++ b/spring-boot-samples/spring-boot-sample-data-solr/src/test/java/sample/data/solr/SampleSolrApplicationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 the original author or authors. + * Copyright 2012-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. @@ -16,17 +16,13 @@ package sample.data.solr; -import static org.junit.Assert.*; - -import org.apache.solr.client.solrj.SolrServerException; import org.junit.Rule; import org.junit.Test; import org.springframework.boot.test.OutputCapture; import org.springframework.core.NestedCheckedException; -/** - * @author Christoph Strobl - */ +import static org.junit.Assert.assertTrue; + public class SampleSolrApplicationTests { @Rule @@ -37,7 +33,8 @@ public class SampleSolrApplicationTests { try { SampleSolrApplication.main(new String[0]); - } catch (IllegalStateException ex) { + } + catch (IllegalStateException ex) { if (serverNotRunning(ex)) { return; } @@ -51,11 +48,9 @@ public class SampleSolrApplicationTests { @SuppressWarnings("serial") NestedCheckedException nested = new NestedCheckedException("failed", ex) { }; - if (nested.contains(SolrServerException.class)) { - Throwable root = nested.getRootCause(); - if (root.getMessage().contains("Connection refused")) { - return true; - } + Throwable root = nested.getRootCause(); + if (root.getMessage().contains("Connection refused")) { + return true; } return false; } From d673002c2eba3f51adcc265da9addd7d838f9ab0 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 22 May 2014 08:58:15 +0100 Subject: [PATCH 3/4] Document Solr integration --- .../src/main/asciidoc/appendix-application-properties.adoc | 4 ++++ .../main/asciidoc/appendix-auto-configuration-classes.adoc | 6 ++++++ spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc | 3 +++ 3 files changed, 13 insertions(+) diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index c85ad208b1..232a1f2d83 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -192,6 +192,10 @@ content into your application; rather pick only the properties that you need. spring.jpa.hibernate.defer-ddl=true # defer processing of DDL until application is running spring.jpa.hibernate.ddl-auto= # defaults to create-drop for embedded dbs + # SOLR ({sc-spring-boot-autoconfigure}/solr/SolrProperties.{sc-ext}[SolrProperties}]) + spring.data.solr.host=http://127.0.0.1:8983/solr + spring.data.solr.zkHost= + # FLYWAY ({sc-spring-boot-autoconfigure}/flyway/FlywayProperties.{sc-ext}[FlywayProperties]) flyway.locations=classpath:db/migrations # locations of migrations scripts flyway.schemas= # schemas to update diff --git a/spring-boot-docs/src/main/asciidoc/appendix-auto-configuration-classes.adoc b/spring-boot-docs/src/main/asciidoc/appendix-auto-configuration-classes.adoc index 4e30347f1d..a65e529a04 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-auto-configuration-classes.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-auto-configuration-classes.adoc @@ -95,6 +95,12 @@ The following auto-configuration classes are from the `spring-boot-autoconfigure |{sc-spring-boot-autoconfigure}/web/ServerPropertiesAutoConfiguration.{sc-ext}[ServerPropertiesAutoConfiguration] |{dc-spring-boot-autoconfigure}/web/ServerPropertiesAutoConfiguration.{dc-ext}[javadoc] +|{sc-spring-boot-autoconfigure}/solr/SolrAutoConfiguration.{sc-ext}[SolrAutoConfiguration] +|{dc-spring-boot-autoconfigure}/solr/SolrAutoConfiguration.{dc-ext}[javadoc] + +|{sc-spring-boot-autoconfigure}/data/SolrRepositoriesAutoConfiguration.{sc-ext}[SolrRepositoriesAutoConfiguration] +|{dc-spring-boot-autoconfigure}/data/SolrRepositoriesAutoConfiguration.{dc-ext}[javadoc] + |{sc-spring-boot-autoconfigure}/thymeleaf/ThymeleafAutoConfiguration.{sc-ext}[ThymeleafAutoConfiguration] |{dc-spring-boot-autoconfigure}/thymeleaf/ThymeleafAutoConfiguration.{dc-ext}[javadoc] diff --git a/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc b/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc index 72670eb75e..f1e616d94b 100644 --- a/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc +++ b/spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc @@ -236,6 +236,9 @@ and Hibernate. |`spring-boot-starter-data-rest` |Support for exposing Spring Data repositories over REST via `spring-data-rest-webmvc`. +|`spring-boot-starter-data-solr` +|Support for the Apache Solr search platform, including `spring-data-solr`. + |`spring-boot-starter-freemarker` |Support for the FreeMarker templating engine From b76a519f654a4c204cadfcaabebf62aee3b951e5 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 22 May 2014 16:45:14 +0100 Subject: [PATCH 4/4] Add a HealthIndicator for Solr --- spring-boot-actuator/pom.xml | 9 +- .../HealthIndicatorAutoConfiguration.java | 37 +++++++- .../actuate/health/SolrHealthIndicator.java | 47 ++++++++++ ...HealthIndicatorAutoConfigurationTests.java | 36 +++++++- .../health/SolrHealthIndicatorTests.java | 91 +++++++++++++++++++ 5 files changed, 213 insertions(+), 7 deletions(-) create mode 100644 spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SolrHealthIndicator.java create mode 100644 spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SolrHealthIndicatorTests.java diff --git a/spring-boot-actuator/pom.xml b/spring-boot-actuator/pom.xml index d7f0cfdff8..6a8e20fb32 100644 --- a/spring-boot-actuator/pom.xml +++ b/spring-boot-actuator/pom.xml @@ -50,7 +50,7 @@ javax.servlet javax.servlet-api true - + org.hibernate hibernate-validator @@ -71,6 +71,11 @@ spring-webmvc true + + org.springframework.data + spring-data-mongodb + true + org.springframework.data spring-data-redis @@ -78,7 +83,7 @@ org.springframework.data - spring-data-mongodb + spring-data-solr true diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfiguration.java index 55d697d6b9..b201e0ab6d 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfiguration.java @@ -21,6 +21,7 @@ import java.util.Map; import javax.sql.DataSource; +import org.apache.solr.client.solrj.SolrServer; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -32,6 +33,7 @@ import org.springframework.boot.actuate.health.OrderedHealthAggregator; import org.springframework.boot.actuate.health.RabbitHealthIndicator; import org.springframework.boot.actuate.health.RedisHealthIndicator; import org.springframework.boot.actuate.health.SimpleDataSourceHealthIndicator; +import org.springframework.boot.actuate.health.SolrHealthIndicator; import org.springframework.boot.actuate.health.VanillaHealthIndicator; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; @@ -44,6 +46,7 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoDataAutoConfiguration; import org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration; +import org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.MongoTemplate; @@ -51,15 +54,16 @@ import org.springframework.data.redis.connection.RedisConnectionFactory; /** * {@link EnableAutoConfiguration Auto-configuration} for {@link HealthIndicator}s. - * + * * @author Christian Dupuis + * @author Andy Wilkinson * @since 1.1.0 */ @Configuration @AutoConfigureBefore({ EndpointAutoConfiguration.class }) @AutoConfigureAfter({ DataSourceAutoConfiguration.class, MongoAutoConfiguration.class, MongoDataAutoConfiguration.class, RedisAutoConfiguration.class, - RabbitAutoConfiguration.class }) + RabbitAutoConfiguration.class, SolrAutoConfiguration.class }) public class HealthIndicatorAutoConfiguration { @Value("${health.status.order:}") @@ -199,4 +203,33 @@ public class HealthIndicatorAutoConfiguration { } } + @Configuration + @ConditionalOnBean(SolrServer.class) + @ConditionalOnExpression("${health.solr.enabled:true}") + public static class SolrHealthIndicatorConfiguration { + + @Autowired + private HealthAggregator healthAggregator; + + @Autowired + private Map solrServers; + + @Bean + @ConditionalOnMissingBean(name = "solrHealthIndicator") + public HealthIndicator rabbitHealthIndicator() { + if (this.solrServers.size() == 1) { + return new SolrHealthIndicator(this.solrServers.entrySet().iterator() + .next().getValue()); + } + + CompositeHealthIndicator composite = new CompositeHealthIndicator( + this.healthAggregator); + for (Map.Entry entry : this.solrServers.entrySet()) { + composite.addHealthIndicator(entry.getKey(), new SolrHealthIndicator( + entry.getValue())); + } + return composite; + } + } + } diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SolrHealthIndicator.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SolrHealthIndicator.java new file mode 100644 index 0000000000..8aadabc43b --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SolrHealthIndicator.java @@ -0,0 +1,47 @@ +/* + * Copyright 2012-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.boot.actuate.health; + +import org.apache.solr.client.solrj.SolrServer; + +/** + * {@link HealthIndicator} for Apache Solr + * + * @author Andy Wilkinson + * @since 1.1.0 + */ +public class SolrHealthIndicator implements HealthIndicator { + + private final SolrServer solrServer; + + public SolrHealthIndicator(SolrServer solrServer) { + this.solrServer = solrServer; + } + + @Override + public Health health() { + Health health = new Health(); + try { + this.solrServer.ping(); + return health.up().withDetail("solrStatus", + this.solrServer.ping().getResponse().get("status")); + } + catch (Exception e) { + return health.down().withException(e); + } + } +} diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfigurationTests.java index f859eb467d..cf78c32d3c 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/HealthIndicatorAutoConfigurationTests.java @@ -26,12 +26,14 @@ import org.springframework.boot.actuate.health.MongoHealthIndicator; import org.springframework.boot.actuate.health.RabbitHealthIndicator; import org.springframework.boot.actuate.health.RedisHealthIndicator; import org.springframework.boot.actuate.health.SimpleDataSourceHealthIndicator; +import org.springframework.boot.actuate.health.SolrHealthIndicator; import org.springframework.boot.actuate.health.VanillaHealthIndicator; import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoDataAutoConfiguration; import org.springframework.boot.autoconfigure.redis.RedisAutoConfiguration; +import org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration; import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.annotation.AnnotationConfigApplicationContext; @@ -39,7 +41,7 @@ import static org.junit.Assert.assertEquals; /** * Tests for {@link HealthIndicatorAutoConfiguration}. - * + * * @author Christian Dupuis */ public class HealthIndicatorAutoConfigurationTests { @@ -130,11 +132,12 @@ public class HealthIndicatorAutoConfigurationTests { public void combinedHealthIndicator() { this.context = new AnnotationConfigApplicationContext(); this.context.register(MongoAutoConfiguration.class, RedisAutoConfiguration.class, - MongoDataAutoConfiguration.class, HealthIndicatorAutoConfiguration.class); + MongoDataAutoConfiguration.class, SolrAutoConfiguration.class, + HealthIndicatorAutoConfiguration.class); this.context.refresh(); Map beans = this.context .getBeansOfType(HealthIndicator.class); - assertEquals(2, beans.size()); + assertEquals(3, beans.size()); } @Test @@ -190,4 +193,31 @@ public class HealthIndicatorAutoConfigurationTests { assertEquals(VanillaHealthIndicator.class, beans.values().iterator().next() .getClass()); } + + @Test + public void solrHeathIndicator() { + this.context = new AnnotationConfigApplicationContext(); + this.context.register(SolrAutoConfiguration.class, + HealthIndicatorAutoConfiguration.class); + this.context.refresh(); + Map beans = this.context + .getBeansOfType(HealthIndicator.class); + assertEquals(1, beans.size()); + assertEquals(SolrHealthIndicator.class, beans.values().iterator().next() + .getClass()); + } + + @Test + public void notSolrHeathIndicator() { + this.context = new AnnotationConfigApplicationContext(); + this.context.register(SolrAutoConfiguration.class, + HealthIndicatorAutoConfiguration.class); + EnvironmentTestUtils.addEnvironment(this.context, "health.solr.enabled:false"); + this.context.refresh(); + Map beans = this.context + .getBeansOfType(HealthIndicator.class); + assertEquals(1, beans.size()); + assertEquals(VanillaHealthIndicator.class, beans.values().iterator().next() + .getClass()); + } } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SolrHealthIndicatorTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SolrHealthIndicatorTests.java new file mode 100644 index 0000000000..e29b7ab5a1 --- /dev/null +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/health/SolrHealthIndicatorTests.java @@ -0,0 +1,91 @@ +/* + * Copyright 2012-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.boot.actuate.health; + +import java.io.IOException; + +import org.apache.solr.client.solrj.SolrServer; +import org.apache.solr.client.solrj.response.SolrPingResponse; +import org.apache.solr.common.util.NamedList; +import org.junit.After; +import org.junit.Test; +import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.HealthIndicatorAutoConfiguration; +import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Tests for {@link SolrHealthIndicator} + * + * @author Andy Wilkinson + */ +public class SolrHealthIndicatorTests { + + private AnnotationConfigApplicationContext context; + + @After + public void close() { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void indicatorExists() { + this.context = new AnnotationConfigApplicationContext( + PropertyPlaceholderAutoConfiguration.class, SolrAutoConfiguration.class, + EndpointAutoConfiguration.class, HealthIndicatorAutoConfiguration.class); + assertEquals(1, this.context.getBeanNamesForType(SolrServer.class).length); + SolrHealthIndicator healthIndicator = this.context + .getBean(SolrHealthIndicator.class); + assertNotNull(healthIndicator); + } + + @Test + public void solrIsUp() throws Exception { + SolrServer solrServer = mock(SolrServer.class); + SolrPingResponse pingResponse = new SolrPingResponse(); + NamedList response = new NamedList(); + response.add("status", "OK"); + pingResponse.setResponse(response); + when(solrServer.ping()).thenReturn(pingResponse); + + SolrHealthIndicator healthIndicator = new SolrHealthIndicator(solrServer); + Health health = healthIndicator.health(); + assertEquals(Status.UP, health.getStatus()); + assertEquals("OK", health.getDetails().get("solrStatus")); + } + + @Test + public void solrIsDown() throws Exception { + SolrServer solrServer = mock(SolrServer.class); + when(solrServer.ping()).thenThrow(new IOException("Connection failed")); + + SolrHealthIndicator healthIndicator = new SolrHealthIndicator(solrServer); + Health health = healthIndicator.health(); + assertEquals(Status.DOWN, health.getStatus()); + assertTrue(((String) health.getDetails().get("error")) + .contains("Connection failed")); + } +}