This commit is contained in:
Phillip Webb 2014-05-22 20:32:36 +01:00
parent 94a255074f
commit 1a475102de
43 changed files with 212 additions and 132 deletions

View File

@ -50,7 +50,7 @@
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId> <artifactId>hibernate-validator</artifactId>

View File

@ -37,9 +37,9 @@ import org.springframework.boot.actuate.endpoint.RequestMappingEndpoint;
import org.springframework.boot.actuate.endpoint.ShutdownEndpoint; import org.springframework.boot.actuate.endpoint.ShutdownEndpoint;
import org.springframework.boot.actuate.endpoint.TraceEndpoint; import org.springframework.boot.actuate.endpoint.TraceEndpoint;
import org.springframework.boot.actuate.endpoint.VanillaPublicMetrics; import org.springframework.boot.actuate.endpoint.VanillaPublicMetrics;
import org.springframework.boot.actuate.health.OrderedHealthAggregator;
import org.springframework.boot.actuate.health.HealthAggregator; import org.springframework.boot.actuate.health.HealthAggregator;
import org.springframework.boot.actuate.health.HealthIndicator; import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.actuate.health.OrderedHealthAggregator;
import org.springframework.boot.actuate.metrics.reader.MetricReader; import org.springframework.boot.actuate.metrics.reader.MetricReader;
import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository; import org.springframework.boot.actuate.metrics.repository.InMemoryMetricRepository;
import org.springframework.boot.actuate.trace.InMemoryTraceRepository; import org.springframework.boot.actuate.trace.InMemoryTraceRepository;

View File

@ -208,7 +208,6 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
if (this.applicationContext instanceof ConfigurableApplicationContext) { if (this.applicationContext instanceof ConfigurableApplicationContext) {
((ConfigurableApplicationContext) this.applicationContext) ((ConfigurableApplicationContext) this.applicationContext)
.addApplicationListener(new ApplicationListener<ContextClosedEvent>() { .addApplicationListener(new ApplicationListener<ContextClosedEvent>() {
@Override @Override
public void onApplicationEvent(ContextClosedEvent event) { public void onApplicationEvent(ContextClosedEvent event) {
if (event.getApplicationContext() == EndpointWebMvcAutoConfiguration.this.applicationContext) { if (event.getApplicationContext() == EndpointWebMvcAutoConfiguration.this.applicationContext) {

View File

@ -54,7 +54,7 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for {@link HealthIndicator}s. * {@link EnableAutoConfiguration Auto-configuration} for {@link HealthIndicator}s.
* *
* @author Christian Dupuis * @author Christian Dupuis
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 1.1.0 * @since 1.1.0

View File

@ -41,4 +41,5 @@ public class HealthMvcEndpointProperties {
public void setMapping(Map<String, HttpStatus> mapping) { public void setMapping(Map<String, HttpStatus> mapping) {
this.mapping = mapping; this.mapping = mapping;
} }
}
}

View File

@ -31,22 +31,53 @@ import org.springframework.web.bind.annotation.ResponseBody;
/** /**
* Adapter to expose {@link HealthEndpoint} as an {@link MvcEndpoint}. * Adapter to expose {@link HealthEndpoint} as an {@link MvcEndpoint}.
* *
* @author Christian Dupuis * @author Christian Dupuis
* @since 1.1.0 * @since 1.1.0
*/ */
public class HealthMvcEndpoint extends EndpointMvcAdapter { public class HealthMvcEndpoint extends EndpointMvcAdapter {
private Map<String, HttpStatus> statusMapping; private Map<String, HttpStatus> statusMapping = new HashMap<String, HttpStatus>();
public HealthMvcEndpoint(HealthEndpoint delegate) { public HealthMvcEndpoint(HealthEndpoint delegate) {
super(delegate); super(delegate);
setupDefaultStatusMapping(); setupDefaultStatusMapping();
} }
private void setupDefaultStatusMapping() {
addStatusMapping(Status.DOWN, HttpStatus.SERVICE_UNAVAILABLE);
addStatusMapping(Status.OUT_OF_SERVICE, HttpStatus.SERVICE_UNAVAILABLE);
}
/**
* Set specific status mappings
* @param statusMapping a map of status code to {@link HttpStatus}
*/
public void setStatusMapping(Map<String, HttpStatus> statusMapping) { public void setStatusMapping(Map<String, HttpStatus> statusMapping) {
Assert.notNull(statusMapping, "StatusMapping must not be null"); Assert.notNull(statusMapping, "StatusMapping must not be null");
this.statusMapping = statusMapping; this.statusMapping = new HashMap<String, HttpStatus>(statusMapping);
}
/**
* Add a status mapping to the existing set
* @param status the status to map
* @param httpStatus the http status
*/
public void addStatusMapping(Status status, HttpStatus httpStatus) {
Assert.notNull(status, "Status must not be null");
Assert.notNull(httpStatus, "HttpStatus must not be null");
addStatusMapping(status.getCode(), httpStatus);
}
/**
* Add a status mapping to the existing set
* @param statusCode the status code to map
* @param httpStatus the http status
*/
public void addStatusMapping(String statusCode, HttpStatus httpStatus) {
Assert.notNull(statusCode, "StatusCode must not be null");
Assert.notNull(httpStatus, "HttpStatus must not be null");
this.statusMapping.put(statusCode, httpStatus);
} }
@RequestMapping @RequestMapping
@ -62,16 +93,10 @@ public class HealthMvcEndpoint extends EndpointMvcAdapter {
Health health = (Health) getDelegate().invoke(); Health health = (Health) getDelegate().invoke();
Status status = health.getStatus(); Status status = health.getStatus();
if (this.statusMapping.containsKey(status.getCode())) { if (this.statusMapping.containsKey(status.getCode())) {
return new ResponseEntity<Health>(health, return new ResponseEntity<Health>(health, this.statusMapping.get(status
this.statusMapping.get(status.getCode())); .getCode()));
} }
return health; return health;
} }
private void setupDefaultStatusMapping() {
this.statusMapping = new HashMap<String, HttpStatus>();
this.statusMapping.put(Status.DOWN.getCode(), HttpStatus.SERVICE_UNAVAILABLE);
this.statusMapping.put(Status.OUT_OF_SERVICE.getCode(),
HttpStatus.SERVICE_UNAVAILABLE);
}
} }

View File

@ -32,15 +32,15 @@ public abstract class AbstractHealthAggregator implements HealthAggregator {
@Override @Override
public final Health aggregate(Map<String, Health> healths) { public final Health aggregate(Map<String, Health> healths) {
Health health = new Health(); Health health = new Health();
List<Status> status = new ArrayList<Status>(); List<Status> status = new ArrayList<Status>();
for (Map.Entry<String, Health> h : healths.entrySet()) { for (Map.Entry<String, Health> entry : healths.entrySet()) {
health.withDetail(h.getKey(), h.getValue()); health.withDetail(entry.getKey(), entry.getValue());
status.add(h.getValue().getStatus()); status.add(entry.getValue().getStatus());
} }
health.status(aggregateStatus(status)); health.status(aggregateStatus(status));
return health; return health;
} }
protected abstract Status aggregateStatus(List<Status> status); protected abstract Status aggregateStatus(List<Status> status);
} }

View File

@ -19,7 +19,6 @@ package org.springframework.boot.actuate.health;
/** /**
* Base {@link HealthIndicator} implementations that encapsulates creation of * Base {@link HealthIndicator} implementations that encapsulates creation of
* {@link Health} instance and error handling. * {@link Health} instance and error handling.
*
* <p> * <p>
* This implementation is only suitable if an {@link Exception} raised from * This implementation is only suitable if an {@link Exception} raised from
* {@link #doHealthCheck(Health)} should create a {@link Status#DOWN} health status. * {@link #doHealthCheck(Health)} should create a {@link Status#DOWN} health status.

View File

@ -31,27 +31,24 @@ import com.fasterxml.jackson.annotation.JsonUnwrapped;
/** /**
* Value object used to carry information about the health information of a component or * Value object used to carry information about the health information of a component or
* subsystem. * subsystem.
*
* <p> * <p>
* {@link Health} contains a {@link Status} to express the state of a component or * {@link Health} contains a {@link Status} to express the state of a component or
* subsystem and some additional details to carry some contextual information. * subsystem and some additional details to carry some contextual information.
*
* <p> * <p>
* {@link Health} has a fluent API to make it easy to construct instances. Typical usage * {@link Health} has a fluent API to make it easy to construct instances. Typical usage
* in a {@link HealthIndicator} would be: * in a {@link HealthIndicator} would be:
* *
* <code> * <pre class="code">
* Health health = new Health(); * Health health = new Health();
* try { * try {
* // do some test to determine state of component * // do some test to determine state of component
* * health.up().withDetail(&quot;version&quot;, &quot;1.1.2&quot;);
* health.up().withDetail("version", "1.1.2"); * }
* } * catch (Exception ex) {
* catch (Exception ex) { * health.down().withException(ex);
* health.down().withException(ex); * }
* } * return health;
* return health; * </pre>
* </code>
* *
* @author Christian Dupuis * @author Christian Dupuis
* @since 1.1.0 * @since 1.1.0
@ -64,7 +61,7 @@ public class Health {
private Map<String, Object> details; private Map<String, Object> details;
public Health() { public Health() {
this(Status.UNKOWN); this(Status.UNKNOWN);
} }
public Health(Status status) { public Health(Status status) {

View File

@ -21,13 +21,11 @@ import java.util.Map;
/** /**
* Strategy interface used by {@link CompositeHealthIndicator} to aggregate {@link Health} * Strategy interface used by {@link CompositeHealthIndicator} to aggregate {@link Health}
* instances into a final one. * instances into a final one.
*
* <p> * <p>
* This is especially useful to combine subsystem states expressed through * This is especially useful to combine subsystem states expressed through
* {@link Health#getStatus()} into one state for the entire system. The default * {@link Health#getStatus()} into one state for the entire system. The default
* implementation {@link OrderedHealthAggregator} sorts {@link Status} instances based on * implementation {@link OrderedHealthAggregator} sorts {@link Status} instances based on
* a priority list. * a priority list.
*
* <p> * <p>
* It is possible to add more complex {@link Status} types to the system. In that case * It is possible to add more complex {@link Status} types to the system. In that case
* either the {@link OrderedHealthAggregator} needs to be properly configured or users * either the {@link OrderedHealthAggregator} needs to be properly configured or users

View File

@ -21,38 +21,64 @@ import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import org.springframework.util.Assert;
/** /**
* Default {@link HealthAggregator} implementation that aggregates {@link Health} * Default {@link HealthAggregator} implementation that aggregates {@link Health}
* instances and determines the final system state based on a simple ordered list. * instances and determines the final system state based on a simple ordered list.
*
* <p> * <p>
* If a different order is required or a new {@link Status} type will be used, the order * If a different order is required or a new {@link Status} type will be used, the order
* can be set by calling {@link #setStatusOrder(List)}. * can be set by calling {@link #setStatusOrder(List)}.
* *
* @author Christian Dupuis * @author Christian Dupuis
* @since 1.1.0 * @since 1.1.0
*/ */
public class OrderedHealthAggregator extends AbstractHealthAggregator { public class OrderedHealthAggregator extends AbstractHealthAggregator {
private List<String> statusOrder = Arrays.asList("DOWN", "OUT_OF_SERVICE", "UP", private List<String> statusOrder;
"UNKOWN");
/**
* Create a new {@link OrderedHealthAggregator} instance.
*/
public OrderedHealthAggregator() {
setStatusOrder(Status.DOWN, Status.OUT_OF_SERVICE, Status.UP, Status.UNKNOWN);
}
/**
* Set the ordering of the status.
* @param statusOrder an ordered list of the status
*/
public void setStatusOrder(Status... statusOrder) {
String[] order = new String[statusOrder.length];
for (int i = 0; i < statusOrder.length; i++) {
order[i] = statusOrder[i].getCode();
}
setStatusOrder(Arrays.asList(order));
}
/**
* Set the ordering of the status.
* @param statusOrder an ordered list of the status codes
*/
public void setStatusOrder(List<String> statusOrder) { public void setStatusOrder(List<String> statusOrder) {
Assert.notNull(statusOrder, "StatusOrder must not be null");
this.statusOrder = statusOrder; this.statusOrder = statusOrder;
} }
@Override @Override
protected Status aggregateStatus(List<Status> status) { protected Status aggregateStatus(List<Status> status) {
// If no status is given return UNKOWN // If no status is given return UNKNOWN
if (status.size() == 0) { if (status.size() == 0) {
return Status.UNKOWN; return Status.UNKNOWN;
} }
// Sort given Status instances by configured order // Sort given Status instances by configured order
Collections.sort(status, new StatusComparator(this.statusOrder)); Collections.sort(status, new StatusComparator(this.statusOrder));
return status.get(0); return status.get(0);
} }
/**
* {@link Comparator} used to order {@link Status}.
*/
private class StatusComparator implements Comparator<Status> { private class StatusComparator implements Comparator<Status> {
private final List<String> statusOrder; private final List<String> statusOrder;
@ -63,8 +89,9 @@ public class OrderedHealthAggregator extends AbstractHealthAggregator {
@Override @Override
public int compare(Status s1, Status s2) { public int compare(Status s1, Status s2) {
return Integer.valueOf(this.statusOrder.indexOf(s1.getCode())).compareTo( int i1 = this.statusOrder.indexOf(s1.getCode());
Integer.valueOf(this.statusOrder.indexOf(s2.getCode()))); int i2 = this.statusOrder.indexOf(s2.getCode());
return (i1 < i2 ? -1 : (i1 == i2 ? s1.getCode().compareTo(s2.getCode()) : 1));
} }
} }

View File

@ -25,11 +25,9 @@ import com.fasterxml.jackson.annotation.JsonProperty;
/** /**
* Value object to express state of a component or subsystem. * Value object to express state of a component or subsystem.
*
* <p> * <p>
* Status provides convenient constants for commonly used states like {@link #UP}, * Status provides convenient constants for commonly used states like {@link #UP},
* {@link #DOWN} or {@link #OUT_OF_SERVICE}. * {@link #DOWN} or {@link #OUT_OF_SERVICE}.
*
* <p> * <p>
* Custom states can also be created and used throughout the Spring Boot Health subsystem. * Custom states can also be created and used throughout the Spring Boot Health subsystem.
* *
@ -42,7 +40,7 @@ public class Status {
/** /**
* Convenient constant value representing unknown state * Convenient constant value representing unknown state
*/ */
public static final Status UNKOWN = new Status("UNKOWN"); public static final Status UNKNOWN = new Status("UNKNOWN");
/** /**
* Convenient constant value representing up state * Convenient constant value representing up state
@ -63,10 +61,19 @@ public class Status {
private final String description; private final String description;
/**
* Create a new {@link Status} instance with the given code and an empty description.
* @param code the status code
*/
public Status(String code) { public Status(String code) {
this(code, ""); this(code, "");
} }
/**
* Create a new {@link Status} instance with the given code and description.
* @param code the status code
* @param description a description of the status
*/
public Status(String code, String description) { public Status(String code, String description) {
Assert.notNull(code, "Code must not be null"); Assert.notNull(code, "Code must not be null");
Assert.notNull(description, "Description must not be null"); Assert.notNull(description, "Description must not be null");
@ -74,16 +81,32 @@ public class Status {
this.description = description; this.description = description;
} }
/**
* @return the code for this status
*/
@JsonProperty("status") @JsonProperty("status")
public String getCode() { public String getCode() {
return this.code; return this.code;
} }
/**
* @return the description of this status
*/
@JsonInclude(Include.NON_EMPTY) @JsonInclude(Include.NON_EMPTY)
public String getDescription() { public String getDescription() {
return this.description; return this.description;
} }
@Override
public String toString() {
return this.code;
}
@Override
public int hashCode() {
return this.code.hashCode();
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == this) { if (obj == this) {
@ -95,8 +118,4 @@ public class Status {
return false; return false;
} }
@Override }
public int hashCode() {
return this.code.hashCode();
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2014-2015 the original author or authors. * Copyright 2014-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,7 +29,6 @@ import org.springframework.boot.actuate.metrics.repository.MultiMetricRepository
* has been populated using that exporter. * has been populated using that exporter.
* *
* @author Dave Syer * @author Dave Syer
*
* @since 1.1.0 * @since 1.1.0
*/ */
public class MultiMetricRichGaugeReader implements RichGaugeReader { public class MultiMetricRichGaugeReader implements RichGaugeReader {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -25,6 +25,7 @@ import org.springframework.boot.actuate.metrics.Metric;
* name prefix (their group name). * name prefix (their group name).
* *
* @author Dave Syer * @author Dave Syer
* @since 1.1.0
*/ */
public interface PrefixMetricWriter { public interface PrefixMetricWriter {

View File

@ -33,7 +33,7 @@ import static org.mockito.Mockito.when;
/** /**
* Tests for {@link HealthMvcEndpoint}. * Tests for {@link HealthMvcEndpoint}.
* *
* @author Christian Dupuis * @author Christian Dupuis
*/ */
public class HealthMvcEndpointTests { public class HealthMvcEndpointTests {

View File

@ -123,8 +123,9 @@ public class CompositeHealthIndicatorTests {
Health result = composite.health(); Health result = composite.health();
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
assertEquals( assertEquals("{\"status\":\"UNKNOWN\",\"db\":{\"status\":\"UNKNOWN\""
"{\"status\":\"UNKOWN\",\"db\":{\"status\":\"UNKOWN\",\"db1\":{\"status\":\"UNKOWN\",\"1\":\"1\"},\"db2\":{\"status\":\"UNKOWN\",\"2\":\"2\"}}}", + ",\"db1\":{\"status\":\"UNKNOWN\",\"1\":\"1\"},"
+ "\"db2\":{\"status\":\"UNKNOWN\",\"2\":\"2\"}}}",
mapper.writeValueAsString(result)); mapper.writeValueAsString(result));
} }

View File

@ -36,7 +36,7 @@ import static org.junit.Assert.assertTrue;
/** /**
* Tests for {@link MongoHealthIndicator}. * Tests for {@link MongoHealthIndicator}.
* *
* @author Christian Dupuis * @author Christian Dupuis
*/ */
public class MongoHealthIndicatorTests { public class MongoHealthIndicatorTests {

View File

@ -27,7 +27,7 @@ import static org.junit.Assert.assertEquals;
/** /**
* Tests for {@link OrderedHealthAggregator}. * Tests for {@link OrderedHealthAggregator}.
* *
* @author Christian Dupuis * @author Christian Dupuis
*/ */
public class OrderedHealthAggregatorTests { public class OrderedHealthAggregatorTests {
@ -40,35 +40,47 @@ public class OrderedHealthAggregatorTests {
} }
@Test @Test
public void testDefaultOrdering() { public void defaultOrder() {
Map<String, Health> healths = new HashMap<String, Health>(); Map<String, Health> healths = new HashMap<String, Health>();
healths.put("h1", new Health(Status.DOWN)); healths.put("h1", new Health(Status.DOWN));
healths.put("h2", new Health(Status.UP)); healths.put("h2", new Health(Status.UP));
healths.put("h3", new Health(Status.UNKOWN)); healths.put("h3", new Health(Status.UNKNOWN));
healths.put("h4", new Health(Status.OUT_OF_SERVICE)); healths.put("h4", new Health(Status.OUT_OF_SERVICE));
assertEquals(Status.DOWN, this.healthAggregator.aggregate(healths).getStatus()); assertEquals(Status.DOWN, this.healthAggregator.aggregate(healths).getStatus());
} }
@Test @Test
public void testDefaultOrderingWithCustomStatus() { public void customOrder() {
this.healthAggregator.setStatusOrder(Status.UNKNOWN, Status.UP,
Status.OUT_OF_SERVICE, Status.DOWN);
Map<String, Health> healths = new HashMap<String, Health>(); Map<String, Health> healths = new HashMap<String, Health>();
healths.put("h1", new Health(Status.DOWN)); healths.put("h1", new Health(Status.DOWN));
healths.put("h2", new Health(Status.UP)); healths.put("h2", new Health(Status.UP));
healths.put("h3", new Health(Status.UNKOWN)); healths.put("h3", new Health(Status.UNKNOWN));
healths.put("h4", new Health(Status.OUT_OF_SERVICE)); healths.put("h4", new Health(Status.OUT_OF_SERVICE));
healths.put("h5", new Health(new Status("CUSTOM"))); assertEquals(Status.UNKNOWN, this.healthAggregator.aggregate(healths).getStatus());
assertEquals(new Status("CUSTOM"),
this.healthAggregator.aggregate(healths).getStatus());
} }
@Test @Test
public void testDefaultOrderingWithCustomStatusAndOrder() { public void defaultOrderWithCustomStatus() {
this.healthAggregator.setStatusOrder(Arrays.asList("DOWN", "OUT_OF_SERVICE",
"UP", "UNKOWN", "CUSTOM"));
Map<String, Health> healths = new HashMap<String, Health>(); Map<String, Health> healths = new HashMap<String, Health>();
healths.put("h1", new Health(Status.DOWN)); healths.put("h1", new Health(Status.DOWN));
healths.put("h2", new Health(Status.UP)); healths.put("h2", new Health(Status.UP));
healths.put("h3", new Health(Status.UNKOWN)); healths.put("h3", new Health(Status.UNKNOWN));
healths.put("h4", new Health(Status.OUT_OF_SERVICE));
healths.put("h5", new Health(new Status("CUSTOM")));
assertEquals(new Status("CUSTOM"), this.healthAggregator.aggregate(healths)
.getStatus());
}
@Test
public void customOrderWithCustomStatus() {
this.healthAggregator.setStatusOrder(Arrays.asList("DOWN", "OUT_OF_SERVICE",
"UP", "UNKNOWN", "CUSTOM"));
Map<String, Health> healths = new HashMap<String, Health>();
healths.put("h1", new Health(Status.DOWN));
healths.put("h2", new Health(Status.UP));
healths.put("h3", new Health(Status.UNKNOWN));
healths.put("h4", new Health(Status.OUT_OF_SERVICE)); healths.put("h4", new Health(Status.OUT_OF_SERVICE));
healths.put("h5", new Health(new Status("CUSTOM"))); healths.put("h5", new Health(new Status("CUSTOM")));
assertEquals(Status.DOWN, this.healthAggregator.aggregate(healths).getStatus()); assertEquals(Status.DOWN, this.healthAggregator.aggregate(healths).getStatus());

View File

@ -36,7 +36,7 @@ import static org.junit.Assert.assertTrue;
/** /**
* Tests for {@link RedisHealthIndicator}. * Tests for {@link RedisHealthIndicator}.
* *
* @author Christian Dupuis * @author Christian Dupuis
*/ */
public class RedisHealthIndicatorTests { public class RedisHealthIndicatorTests {

View File

@ -36,12 +36,13 @@ import static org.mockito.Mockito.when;
/** /**
* Tests for {@link SimpleDataSourceHealthIndicator}. * Tests for {@link SimpleDataSourceHealthIndicator}.
* *
* @author Dave Syer * @author Dave Syer
*/ */
public class SimpleDataSourceHealthIndicatorTests { public class SimpleDataSourceHealthIndicatorTests {
private final SimpleDataSourceHealthIndicator indicator = new SimpleDataSourceHealthIndicator(); private final SimpleDataSourceHealthIndicator indicator = new SimpleDataSourceHealthIndicator();
private DriverManagerDataSource dataSource; private DriverManagerDataSource dataSource;
@Before @Before
@ -63,7 +64,7 @@ public class SimpleDataSourceHealthIndicatorTests {
public void customQuery() { public void customQuery() {
this.indicator.setDataSource(this.dataSource); this.indicator.setDataSource(this.dataSource);
new JdbcTemplate(this.dataSource) new JdbcTemplate(this.dataSource)
.execute("CREATE TABLE FOO (id INTEGER IDENTITY PRIMARY KEY)"); .execute("CREATE TABLE FOO (id INTEGER IDENTITY PRIMARY KEY)");
this.indicator.setQuery("SELECT COUNT(*) from FOO"); this.indicator.setQuery("SELECT COUNT(*) from FOO");
Health health = this.indicator.health(); Health health = this.indicator.health();
System.err.println(health); System.err.println(health);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,7 +22,7 @@ import static org.junit.Assert.assertEquals;
/** /**
* Tests for {@link VanillaHealthIndicator}. * Tests for {@link VanillaHealthIndicator}.
* *
* @author Phillip Webb * @author Phillip Webb
*/ */
public class VanillaHealthIndicatorTests { public class VanillaHealthIndicatorTests {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -40,6 +40,8 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
/** /**
* Tests for {@link RedisMultiMetricRepository}.
*
* @author Dave Syer * @author Dave Syer
*/ */
@RunWith(Parameterized.class) @RunWith(Parameterized.class)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -25,6 +25,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
/** /**
* Tests for {@link MultiMetricRichGaugeReader}.
*
* @author Dave Syer * @author Dave Syer
*/ */
public class MultiMetricRichGaugeReaderTests { public class MultiMetricRichGaugeReaderTests {

View File

@ -26,11 +26,11 @@ import org.springframework.data.solr.repository.config.SolrRepositoryConfigExten
/** /**
* {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data Solr * {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data Solr
* repositories. * repositories.
* *
* @author Christoph Strobl * @author Christoph Strobl
* @since 1.1.0 * @since 1.1.0
*/ */
public class SolrRepositoriesAutoConfigureRegistrar extends class SolrRepositoriesAutoConfigureRegistrar extends
AbstractRepositoryConfigurationSourceSupport { AbstractRepositoryConfigurationSourceSupport {
@Override @Override

View File

@ -32,7 +32,7 @@ import org.springframework.util.StringUtils;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for Solr * {@link EnableAutoConfiguration Auto-configuration} for Solr
* *
* @author Christoph Strobl * @author Christoph Strobl
* @since 1.1.0 * @since 1.1.0
*/ */
@ -66,4 +66,5 @@ public class SolrAutoConfiguration {
} }
return new HttpSolrServer(this.properties.getHost()); return new HttpSolrServer(this.properties.getHost());
} }
} }

View File

@ -19,8 +19,8 @@ package org.springframework.boot.autoconfigure.solr;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
/** /**
* Configuration properties for Solr. * {@link ConfigurationProperties} for Solr.
* *
* @author Christoph Strobl * @author Christoph Strobl
* @since 1.1.0 * @since 1.1.0
*/ */

View File

@ -42,7 +42,7 @@ import org.springframework.util.StringUtils;
* {@link ConfigurationProperties properties} for a web server (e.g. port and path * {@link ConfigurationProperties properties} for a web server (e.g. port and path
* settings). Will be used to customize an {@link EmbeddedServletContainerFactory} when an * settings). Will be used to customize an {@link EmbeddedServletContainerFactory} when an
* {@link EmbeddedServletContainerCustomizerBeanPostProcessor} is active. * {@link EmbeddedServletContainerCustomizerBeanPostProcessor} is active.
* *
* @author Dave Syer * @author Dave Syer
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
@ -159,7 +159,7 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
} }
public int getMaxHttpHeaderSize() { public int getMaxHttpHeaderSize() {
return maxHttpHeaderSize; return this.maxHttpHeaderSize;
} }
public void setMaxHttpHeaderSize(int maxHttpHeaderSize) { public void setMaxHttpHeaderSize(int maxHttpHeaderSize) {

View File

@ -38,7 +38,7 @@ import static org.junit.Assert.assertNotNull;
/** /**
* Tests for {@link JpaRepositoriesAutoConfiguration}. * Tests for {@link JpaRepositoriesAutoConfiguration}.
* *
* @author Dave Syer * @author Dave Syer
* @author Oliver Gierke * @author Oliver Gierke
*/ */

View File

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.autoconfigure.data; package org.springframework.boot.autoconfigure.data;
import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.SolrServer;
@ -34,7 +35,7 @@ import static org.junit.Assert.assertThat;
/** /**
* Tests for {@link SolrRepositoriesAutoConfiguration} * Tests for {@link SolrRepositoriesAutoConfiguration}
* *
* @author Christoph Strobl * @author Christoph Strobl
*/ */
public class SolrRepositoriesAutoConfigurationTests { public class SolrRepositoriesAutoConfigurationTests {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2014-2014 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -13,14 +13,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.autoconfigure.data.alt; package org.springframework.boot.autoconfigure.data.alt;
import org.springframework.boot.autoconfigure.data.solr.City; import org.springframework.boot.autoconfigure.data.solr.City;
import org.springframework.data.repository.Repository; import org.springframework.data.repository.Repository;
/**
* @author Christoph Strobl
*/
public interface CitySolrRepository extends Repository<City, String> { public interface CitySolrRepository extends Repository<City, String> {
} }

View File

@ -34,7 +34,7 @@ import static org.mockito.Mockito.verify;
/** /**
* Tests for {@link ServerProperties}. * Tests for {@link ServerProperties}.
* *
* @author Dave Syer * @author Dave Syer
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
@ -98,7 +98,7 @@ public class ServerPropertiesTests {
} }
@Test @Test
public void testCustomizeTomcatHeaderSize() throws Exception { public void testCustomizeTomcatHeaderSize() throws Exception {
Map<String, String> map = new HashMap<String, String>(); Map<String, String> map = new HashMap<String, String>();
map.put("server.tomcat.maxHttpHeaderSize", "9999"); map.put("server.tomcat.maxHttpHeaderSize", "9999");
new RelaxedDataBinder(this.properties, "server").bind(new MutablePropertyValues( new RelaxedDataBinder(this.properties, "server").bind(new MutablePropertyValues(

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2014 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -24,7 +24,10 @@ import org.eclipse.aether.repository.ProxySelector;
import org.eclipse.aether.repository.RemoteRepository; import org.eclipse.aether.repository.RemoteRepository;
/** /**
* Composite {@link ProxySelector}.
*
* @author Dave Syer * @author Dave Syer
* @since 1.1.0
*/ */
public class CompositeProxySelector implements ProxySelector { public class CompositeProxySelector implements ProxySelector {

View File

@ -948,7 +948,7 @@
<version>${spring-integration.version}</version> <version>${spring-integration.version}</version>
<scope>import</scope> <scope>import</scope>
<type>pom</type> <type>pom</type>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.mobile</groupId> <groupId>org.springframework.mobile</groupId>
<artifactId>spring-mobile-device</artifactId> <artifactId>spring-mobile-device</artifactId>

View File

@ -1,12 +1,13 @@
<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"> <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> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.springframework.boot</groupId> <!-- Your own application should inherit from spring-boot-starter-parent -->
<artifactId>spring-boot-samples</artifactId> <groupId>org.springframework.boot</groupId>
<version>1.1.0.BUILD-SNAPSHOT</version> <artifactId>spring-boot-samples</artifactId>
</parent> <version>1.1.0.BUILD-SNAPSHOT</version>
<artifactId>spring-boot-sample-data-solr</artifactId> </parent>
<name>Spring Boot Data Solr Sample</name> <artifactId>spring-boot-sample-data-solr</artifactId>
<name>Spring Boot Data Solr Sample</name>
<description>Spring Boot Data Solr Sample</description> <description>Spring Boot Data Solr Sample</description>
<url>http://projects.spring.io/spring-boot/</url> <url>http://projects.spring.io/spring-boot/</url>
<organization> <organization>
@ -17,10 +18,6 @@
<main.basedir>${basedir}/../..</main.basedir> <main.basedir>${basedir}/../..</main.basedir>
</properties> </properties>
<dependencies> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId> <artifactId>spring-boot-starter-data-solr</artifactId>

View File

@ -54,4 +54,5 @@ public class SampleSolrApplicationTests {
} }
return false; return false;
} }
} }

View File

@ -19,9 +19,8 @@
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>${project.groupId}</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId> <artifactId>spring-boot-starter</artifactId>
<version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.solr</groupId> <groupId>org.apache.solr</groupId>

View File

@ -30,7 +30,7 @@ import java.util.Set;
/** /**
* A {@link JavaAgentDetector} that detects jars supplied via the {@code -javaagent} JVM * A {@link JavaAgentDetector} that detects jars supplied via the {@code -javaagent} JVM
* input argument. * input argument.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @since 1.1.0 * @since 1.1.0
*/ */
@ -58,7 +58,7 @@ public class InputArgumentsJavaAgentDetector implements JavaAgentDetector {
}); });
} }
catch (Exception ex) { catch (Exception ex) {
return Collections.<String> emptyList(); return Collections.emptyList();
} }
} }
@ -89,7 +89,6 @@ public class InputArgumentsJavaAgentDetector implements JavaAgentDetector {
} }
return path; return path;
} }
return null; return null;
} }

View File

@ -20,9 +20,8 @@ import java.net.URL;
/** /**
* A strategy for detecting Java agents * A strategy for detecting Java agents
* *
* @author Andy Wilkinson * @author Andy Wilkinson
*
* @since 1.1 * @since 1.1
*/ */
public interface JavaAgentDetector { public interface JavaAgentDetector {
@ -30,7 +29,6 @@ public interface JavaAgentDetector {
/** /**
* Returns {@code true} if {@code url} points to a Java agent jar file, otherwise * Returns {@code true} if {@code url} points to a Java agent jar file, otherwise
* {@code false} is returned. * {@code false} is returned.
*
* @param url The url to examine * @param url The url to examine
*/ */
public boolean isJavaAgentJar(URL url); public boolean isJavaAgentJar(URL url);

View File

@ -296,6 +296,11 @@ public final class MimeMappings implements Iterable<Mapping> {
return (previous == null ? null : previous.getMimeType()); return (previous == null ? null : previous.getMimeType());
} }
@Override
public int hashCode() {
return this.map.hashCode();
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == null) { if (obj == null) {
@ -311,11 +316,6 @@ public final class MimeMappings implements Iterable<Mapping> {
return false; return false;
} }
@Override
public int hashCode() {
return this.map.hashCode();
}
/** /**
* Create a new unmodifiable view of the specified mapping. Methods that attempt to * Create a new unmodifiable view of the specified mapping. Methods that attempt to
* modify the returned map will throw {@link UnsupportedOperationException}s. * modify the returned map will throw {@link UnsupportedOperationException}s.
@ -350,6 +350,11 @@ public final class MimeMappings implements Iterable<Mapping> {
return this.mimeType; return this.mimeType;
} }
@Override
public int hashCode() {
return this.extension.hashCode();
}
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (obj == null) { if (obj == null) {
@ -366,11 +371,6 @@ public final class MimeMappings implements Iterable<Mapping> {
return false; return false;
} }
@Override
public int hashCode() {
return this.extension.hashCode();
}
} }
} }