initial commit

This commit is contained in:
Spencer Gibb
2014-12-01 14:54:06 -07:00
commit 0aa9ae5de2
17 changed files with 494 additions and 0 deletions

13
.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
*~
#*
*#
.#*
.classpath
.project
.settings/
.springBeans
target/
_site/
.idea
*.iml
*.swp

60
.settings.xml Normal file
View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<settings>
<servers>
<server>
<id>repo.spring.io</id>
<username>${env.CI_DEPLOY_USERNAME}</username>
<password>${env.CI_DEPLOY_PASSWORD}</password>
</server>
</servers>
<profiles>
<profile>
<id>spring</id>
<activation><activeByDefault>true</activeByDefault></activation>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>http://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>http://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>http://repo.spring.io/libs-snapshot-local</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
</settings>

19
.travis.yml Normal file
View File

@@ -0,0 +1,19 @@
language: java
before_install:
- git config user.name "$GIT_NAME"
- git config user.email "$GIT_EMAIL"
- git config credential.helper "store --file=.git/credentials"
- echo "https://$GH_TOKEN:@github.com" > .git/credentials
- gem install asciidoctor
install:
- mvn --settings .settings.xml install -P docs -q -U -DskipTests=true -Dmaven.test.redirectTestOutputToFile=true
- ./docs/src/main/asciidoc/ghpages.sh
script:
- '[ "${TRAVIS_PULL_REQUEST}" != "false" ] || mvn --settings .settings.xml deploy -nsu -Dmaven.test.redirectTestOutputToFile=true'
- '[ "${TRAVIS_PULL_REQUEST}" = "false" ] || mvn --settings .settings.xml install -nsu -Dmaven.test.redirectTestOutputToFile=true'
env:
global:
- GIT_NAME="Dave Syer"
- GIT_EMAIL=dsyer@pivotal.io
- CI_DEPLOY_USERNAME=buildmaster
- secure: aeLXRC5oFSddwnZt1/7G2/OHr7jDbxz0ET7sej3I+eSbe3N5vbzQ6FC08es4l89l54ciXd90I1g2BMw7DTYKOO373FP78XPdAEbifJTU4DGd6fCELmoTtUPhjunBIk7E49hisPbv82892IYYA7qi/hzG548cPyZ1IgiJjq0NCsc=

4
README.md Normal file
View File

@@ -0,0 +1,4 @@
## Spring Cloud Commons
========
Developer preview of common classes used in different Spring Cloud implementations (eg. Spring Cloud Netflix vs. Spring Cloud Consul)

77
pom.xml Normal file
View File

@@ -0,0 +1,77 @@
<?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>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Spring Cloud Commons</name>
<description>Spring Cloud Commons</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
<scm>
<url>https://github.com/spring-cloud/spring-cloud-commons</url>
<connection>scm:git:git://github.com/spring-cloud/spring-cloud-commons.git</connection>
<developerConnection>scm:git:ssh://git@github.com/spring-cloud/spring-cloud-commons.git</developerConnection>
<tag>HEAD</tag>
</scm>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.12.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
<properties>
</properties>
</project>

View File

@@ -0,0 +1,27 @@
package org.springframework.boot.actuate.autoconfigure;
import static org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration.ManagementServerPort;
import org.springframework.beans.factory.BeanFactory;
/**
* @author Spencer Gibb
*/
public class ManagementServerPortUtils {
public static ManagementServerPort get(BeanFactory beanFactory) {
return ManagementServerPort.get(beanFactory);
}
public static boolean isDifferent(BeanFactory beanFactory) {
return get(beanFactory) == ManagementServerPort.DIFFERENT;
}
public static boolean isDisabled(BeanFactory beanFactory) {
return get(beanFactory) == ManagementServerPort.DISABLE;
}
public static boolean isSame(BeanFactory beanFactory) {
return get(beanFactory) == ManagementServerPort.SAME;
}
}

View File

@@ -0,0 +1,19 @@
package org.springframework.cloud.client;
import org.springframework.cloud.client.discovery.DiscoveryHealthIndicator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
/**
* @author Spencer Gibb
*/
@Configuration
@Order(0)
public class CommonsClientAutoConfiguration {
@Bean
public DiscoveryHealthIndicator discoveryHealthIndicator() {
return new DiscoveryHealthIndicator();
}
}

View File

@@ -0,0 +1,13 @@
package org.springframework.cloud.client;
import lombok.Data;
/**
* @author Spencer Gibb
*/
@Data
public class DefaultServiceInstance implements ServiceInstance {
private final String serviceId;
private final String host;
private final int port;
}

View File

@@ -0,0 +1,12 @@
package org.springframework.cloud.client;
/**
* @author Spencer Gibb
* TODO: name? Server? HostAndPort? Instance?
*/
public interface ServiceInstance {
public String getServiceId();
public String getHost();
public int getPort();
}

View File

@@ -0,0 +1,107 @@
package org.springframework.cloud.client.discovery;
import org.springframework.beans.BeansException;
import org.springframework.boot.actuate.autoconfigure.ManagementServerPortUtils;
import org.springframework.boot.actuate.autoconfigure.ManagementServerProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.env.Environment;
import javax.annotation.PreDestroy;
/**
* @author Spencer Gibb
*/
public abstract class AbstractDiscoveryLifecycle implements DiscoveryLifecycle, ApplicationContextAware {
protected boolean autoStartup = true;
protected boolean running;
protected int order = 0;
protected ApplicationContext context;
protected Environment environment;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
environment = context.getEnvironment();
}
@Override
public boolean isAutoStartup() {
return autoStartup;
}
@Override
public void stop(Runnable callback) {
stop();
callback.run();
}
@Override
public void start() {
if (!isEnabled()) return;
register();
if (ManagementServerPortUtils.isDifferent(context)) {
registerManagement();
}
running = true;
}
protected abstract void register();
protected void registerManagement() {}
protected abstract void deregister();
protected void deregisterManagement() {}
protected abstract boolean isEnabled();
protected String getManagementServiceId() {
return context.getId() + ":management"; //TODO: configurable management suffix
}
protected String getManagementServiceName() {
return getAppName() + ":management"; //TODO: configurable management suffix
}
protected Integer getManagementPort() {
return context.getBean(ManagementServerProperties.class).getPort();
}
protected String getAppName() {
return environment.getProperty("spring.application.name");
}
@Override
public void stop() {
if (isEnabled()) {
deregister();
if (getManagementPort() != null) {
deregisterManagement();
}
}
running = false;
}
@PreDestroy
public void destroy() {
stop();
}
@Override
public boolean isRunning() {
return running;
}
@Override
public int getOrder() {
return order;
}
@Override
public int getPhase() {
return 0;
}
}

View File

@@ -0,0 +1,30 @@
package org.springframework.cloud.client.discovery;
import org.springframework.cloud.client.ServiceInstance;
import java.util.List;
/**
* @author Spencer Gibb
*/
//TODO: merge with LoadBalancerClient?
public interface DiscoveryClient {
/**
* @return ServiceInstance with information used to register the local service
*/
public ServiceInstance getLocalServiceInstance();
/**
* Get all ServiceInstance's associated with a particular serviceId
* @param serviceId the serviceId to query
* @return a List of ServiceInstance
*/
public List<ServiceInstance> getInstances(String serviceId);
public List<ServiceInstance> getAllInstances();
/**
* @return all known service id's
*/
public List<String> getServices();
}

View File

@@ -0,0 +1,42 @@
package org.springframework.cloud.client.discovery;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/**
* @author Spencer Gibb
*/
@Slf4j
public class DiscoveryHealthIndicator extends AbstractHealthIndicator implements ApplicationContextAware {
private ApplicationContext context;
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
try {
DiscoveryClient client = context.getBean(DiscoveryClient.class);
if (client == null) {
builder.unknown().withDetail("warning", "No DiscoveryClient found");
return;
}
List<ServiceInstance> instances = client.getAllInstances();
builder.up().withDetail("instances", instances);
} catch (Exception e) {
log.error("Error", e);
builder.down(e);
}
}
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.context = context;
}
}

View File

@@ -0,0 +1,10 @@
package org.springframework.cloud.client.discovery;
import org.springframework.context.SmartLifecycle;
import org.springframework.core.Ordered;
/**
* @author Spencer Gibb
*/
public interface DiscoveryLifecycle extends SmartLifecycle, Ordered {
}

View File

@@ -0,0 +1,25 @@
package org.springframework.cloud.client.discovery;
import org.springframework.context.ApplicationEvent;
/**
* @author Spencer Gibb
*/
public class InstanceRegisteredEvent<T> extends ApplicationEvent {
private T config;
/**
* Create a new ApplicationEvent.
*
* @param source the component that published the event (never {@code null})
* @param config the configuration of the instance
*/
public InstanceRegisteredEvent(Object source, T config) {
super(source);
this.config = config;
}
public T getConfig() {
return config;
}
}

View File

@@ -0,0 +1,23 @@
package org.springframework.cloud.client.loadbalancer;
import org.springframework.cloud.client.ServiceInstance;
/**
* @author Spencer Gibb
*/
public interface LoadBalancerClient {
/**
* Choose a {@see ServiceInstance} from the LoadBalancer for the specified service
* @param serviceId the service id to look up the LoadBalancer
* @return a ServiceInstance that matches the serviceId
*/
public ServiceInstance choose(String serviceId);
/**
* Choose a {@see ServiceInstance} from the LoadBalancer for the specified service
* @param serviceId the service id to look up the LoadBalancer
* @param request allows implementations to execute pre and post actions such as incrementing metrics
* @return the result of the LoadBalancerRequest callback on the selected ServiceInstance
*/
public <T> T choose(String serviceId, LoadBalancerRequest<T> request);
}

View File

@@ -0,0 +1,10 @@
package org.springframework.cloud.client.loadbalancer;
import org.springframework.cloud.client.ServiceInstance;
/**
* @author Spencer Gibb
*/
public interface LoadBalancerRequest<T> {
public T apply(ServiceInstance instance);
}

View File

@@ -0,0 +1,3 @@
# Bootstrap Configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.client.CommonsClientAutoConfiguration