Merge branch 'solr'

This commit is contained in:
Andy Wilkinson
2014-05-22 17:30:07 +01:00
29 changed files with 1004 additions and 9 deletions

View File

@@ -50,7 +50,7 @@
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<optional>true</optional>
</dependency>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
@@ -71,6 +71,11 @@
<artifactId>spring-webmvc</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
@@ -78,7 +83,7 @@
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<artifactId>spring-data-solr</artifactId>
<optional>true</optional>
</dependency>
<dependency>

View File

@@ -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<String, SolrServer> 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<String, SolrServer> entry : this.solrServers.entrySet()) {
composite.addHealthIndicator(entry.getKey(), new SolrHealthIndicator(
entry.getValue()));
}
return composite;
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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<String, HealthIndicator> 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<String, HealthIndicator> 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<String, HealthIndicator> beans = this.context
.getBeansOfType(HealthIndicator.class);
assertEquals(1, beans.size());
assertEquals(VanillaHealthIndicator.class, beans.values().iterator().next()
.getClass());
}
}

View File

@@ -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<Object> response = new NamedList<Object>();
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"));
}
}

View File

@@ -56,6 +56,11 @@
<artifactId>activemq-pool</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
@@ -171,6 +176,11 @@
<artifactId>spring-data-redis</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-solr</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId>

View File

@@ -0,0 +1,49 @@
/*
* 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.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.
* <p>
* 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.
* </p>
* 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(SolrRepositoriesAutoConfigureRegistrar.class)
public class SolrRepositoriesAutoConfiguration {
}

View File

@@ -0,0 +1,56 @@
/*
* 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.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
* @since 1.1.0
*/
public class SolrRepositoriesAutoConfigureRegistrar extends
AbstractRepositoryConfigurationSourceSupport {
@Override
protected Class<? extends Annotation> getAnnotation() {
return EnableSolrRepositories.class;
}
@Override
protected Class<?> getConfiguration() {
return EnableSolrRepositoriesConfiguration.class;
}
@Override
protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() {
return new SolrRepositoryConfigExtension();
}
@EnableSolrRepositories(multicoreSupport = true)
private static class EnableSolrRepositoriesConfiguration {
}
}

View File

@@ -0,0 +1,69 @@
/*
* 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.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.EnableAutoConfiguration;
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;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Solr
*
* @author Christoph Strobl
* @since 1.1.0
*/
@Configuration
@ConditionalOnClass(SolrServer.class)
@EnableConfigurationProperties(SolrProperties.class)
public class SolrAutoConfiguration {
@Autowired
private 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());
}
}

View File

@@ -0,0 +1,50 @@
/*
* 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.autoconfigure.solr;
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 {
private String host = "http://127.0.0.1:8983/solr";
private String zkHost;
public String getHost() {
return this.host;
}
public void setHost(String host) {
this.host = host;
}
public String getZkHost() {
return this.zkHost;
}
public void setZkHost(String zkHost) {
this.zkHost = zkHost;
}
}

View File

@@ -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,\

View File

@@ -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;
@@ -37,7 +38,7 @@ import static org.junit.Assert.assertNotNull;
/**
* Tests for {@link JpaRepositoriesAutoConfiguration}.
*
*
* @author Dave Syer
* @author Oliver Gierke
*/
@@ -81,7 +82,9 @@ public class JpaRepositoriesAutoConfigurationTests {
}
@Configuration
@EnableJpaRepositories(basePackageClasses = org.springframework.boot.autoconfigure.data.alt.CityJpaRepository.class, excludeFilters = { @Filter(type = FilterType.ASSIGNABLE_TYPE, value = CityMongoDbRepository.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 {

View File

@@ -0,0 +1,94 @@
/*
* 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.autoconfigure.data;
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;
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 {
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 {
}
}

View File

@@ -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<City, String> {
}

View File

@@ -0,0 +1,48 @@
/*
* 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.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 this.id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -0,0 +1,29 @@
/*
* 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.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<City, String> {
Page<City> findByNameStartingWith(String name, Pageable page);
}

View File

@@ -87,6 +87,7 @@
<servlet-api.version>3.0.1</servlet-api.version>
<slf4j.version>1.7.7</slf4j.version>
<snakeyaml.version>1.13</snakeyaml.version>
<solr.version>4.7.2</solr.version>
<spock.version>0.7-groovy-2.0</spock.version>
<spring.version>4.0.5.RELEASE</spring.version>
<spring-amqp.version>1.3.3.RELEASE</spring-amqp.version>
@@ -191,6 +192,11 @@
<artifactId>spring-boot-starter-data-rest</artifactId>
<version>1.1.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
<version>1.1.0.BUILD-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
@@ -770,6 +776,11 @@
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>${solr.version}</version>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>

View File

@@ -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

View File

@@ -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]

View File

@@ -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

View File

@@ -32,6 +32,7 @@
<module>spring-boot-sample-data-mongodb</module>
<module>spring-boot-sample-data-redis</module>
<module>spring-boot-sample-data-rest</module>
<module>spring-boot-sample-data-solr</module>
<module>spring-boot-sample-flyway</module>
<module>spring-boot-sample-integration</module>
<module>spring-boot-sample-jetty</module>

View File

@@ -0,0 +1,42 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-samples</artifactId>
<version>1.1.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-boot-sample-data-solr</artifactId>
<name>Spring Boot Data Solr Sample</name>
<description>Spring Boot Data Solr Sample</description>
<url>http://projects.spring.io/spring-boot/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>http://www.spring.io</url>
</organization>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,100 @@
/*
* 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 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;
@SolrDocument(solrCoreName = "collection1")
public class Product {
@Id
@Field
private String id;
@Field
private String name;
@Field
private Double price;
@Field("cat")
private List<String> 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 this.id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Double getPrice() {
return this.price;
}
public void setPrice(Double price) {
this.price = price;
}
public List<String> getCategory() {
return this.category;
}
public void setCategory(List<String> category) {
this.category = category;
}
public Point getLocation() {
return this.location;
}
public void setLocation(Point location) {
this.location = location;
}
@Override
public String toString() {
return "Product [id=" + this.id + ", name=" + this.name + ", price=" + this.price
+ ", category=" + this.category + ", location=" + this.location + "]";
}
}

View File

@@ -0,0 +1,27 @@
/*
* 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 sample.data.solr;
import java.util.List;
import org.springframework.data.solr.repository.SolrCrudRepository;
public interface ProductRepository extends SolrCrudRepository<Product, String> {
List<Product> findByNameStartingWith(String name);
}

View File

@@ -0,0 +1,65 @@
/*
* 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 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;
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class SampleSolrApplication implements CommandLineRunner {
@Autowired
private ProductRepository repository;
@Override
public void run(String... args) throws Exception {
this.repository.deleteAll();
// insert some products
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 : this.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 : this.repository.findByNameStartingWith("So")) {
System.out.println(product);
}
System.out.println();
}
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleSolrApplication.class, args);
}
}

View File

@@ -0,0 +1,57 @@
/*
* 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 sample.data.solr;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.boot.test.OutputCapture;
import org.springframework.core.NestedCheckedException;
import static org.junit.Assert.assertTrue;
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) {
};
Throwable root = nested.getRootCause();
if (root.getMessage().contains("Connection refused")) {
return true;
}
return false;
}
}

View File

@@ -28,6 +28,7 @@
<module>spring-boot-starter-data-jpa</module>
<module>spring-boot-starter-data-mongodb</module>
<module>spring-boot-starter-data-rest</module>
<module>spring-boot-starter-data-solr</module>
<module>spring-boot-starter-freemarker</module>
<module>spring-boot-starter-integration</module>
<module>spring-boot-starter-jdbc</module>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starters</artifactId>
<version>1.1.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-boot-starter-data-solr</artifactId>
<name>Spring Boot Data Solr Starter</name>
<description>Spring Boot Data Solr Starter</description>
<url>http://projects.spring.io/spring-boot/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>http://www.spring.io</url>
</organization>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-solr</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1 @@
provides: spring-data-solr, solr-solrj