Added an option to use SC-Zookeeper in a non-web app

without this change when you don't use web environment then your context fails to start
    with this change we allow users to use sc-zookeeper as a clients without the need to register in SC-Zookeeper

    fixes #91
This commit is contained in:
Marcin Grzejszczak
2017-01-03 13:56:42 +01:00
committed by Dave Syer
parent 358f9a9df0
commit 1b44ab895f
6 changed files with 132 additions and 10 deletions

View File

@@ -95,11 +95,11 @@ a modified file in the correct place. Just commit it and push the change.
If you don't have an IDE preference we would recommend that you use
http://www.springsource.com/developer/sts[Spring Tools Suite] or
http://eclipse.org[Eclipse] when working with the code. We use the
http://eclipse.org/m2e/[m2eclipe] eclipse plugin for maven support. Other IDEs and tools
http://eclipse.org/m2e/[m2eclipse] eclipse plugin for maven support. Other IDEs and tools
should also work without issue as long as they use Maven 3.3.3 or better.
==== Importing into eclipse with m2eclipse
We recommend the http://eclipse.org/m2e/[m2eclipe] eclipse plugin when working with
We recommend the http://eclipse.org/m2e/[m2eclipse] eclipse plugin when working with
eclipse. If you don't already have m2eclipse installed it is available from the "eclipse
marketplace".

View File

@@ -84,6 +84,9 @@ public class ZookeeperDiscoveryClient implements DiscoveryClient {
public List<org.springframework.cloud.client.ServiceInstance> getInstances(
final String serviceId) {
try {
if (this.serviceDiscovery.getServiceDiscovery() == null) {
return Collections.EMPTY_LIST;
}
String serviceIdToQuery = getServiceIdToQuery(serviceId);
Collection<ServiceInstance<ZookeeperInstance>> zkInstances = this.serviceDiscovery
.getServiceDiscovery().queryForInstances(serviceIdToQuery);

View File

@@ -43,6 +43,7 @@ public class ZookeeperLifecycle extends AbstractDiscoveryLifecycle {
this.serviceDiscovery.setPort(this.properties.getInstancePort());
this.serviceDiscovery.build();
}
this.serviceDiscovery.buildServiceDiscovery();
}
@Override
@@ -91,6 +92,7 @@ public class ZookeeperLifecycle extends AbstractDiscoveryLifecycle {
protected void setConfiguredPort(int port) {
this.serviceDiscovery.setPort(port);
this.serviceDiscovery.build();
this.serviceDiscovery.buildServiceDiscovery();
}
@Override

View File

@@ -21,14 +21,14 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractServerList;
import org.apache.curator.x.discovery.ServiceDiscovery;
import org.apache.curator.x.discovery.ServiceInstance;
import org.springframework.cloud.zookeeper.discovery.dependency.ZookeeperDependencies;
import org.springframework.util.StringUtils;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractServerList;
import static org.springframework.util.ReflectionUtils.rethrowRuntimeException;
/**
@@ -76,6 +76,9 @@ public class ZookeeperServerList extends AbstractServerList<ZookeeperServer> {
@SuppressWarnings("unchecked")
private List<ZookeeperServer> getServers() {
try {
if (this.serviceDiscovery == null) {
return Collections.EMPTY_LIST;
}
Collection<ServiceInstance<ZookeeperInstance>> instances = this.serviceDiscovery
.queryForInstances(this.serviceId);
if (instances == null || instances.isEmpty()) {

View File

@@ -90,9 +90,13 @@ public class ZookeeperServiceDiscovery implements ApplicationContextAware {
this.context = context;
}
/**
* Builds Service Instance - needs to be used when you want to register your application
* in Zookeeper
*/
public void build() {
if (this.built.compareAndSet(false, true)) {
if (this.port.get() <= 0) {
if (this.port.get() <= 0 && this.properties.isRegister()) {
throw new IllegalStateException("Cannot create instance whose port is not greater than 0");
}
String host = this.properties.getInstanceHost();
@@ -100,13 +104,22 @@ public class ZookeeperServiceDiscovery implements ApplicationContextAware {
throw new IllegalStateException("instanceHost must not be empty");
}
UriSpec uriSpec = new UriSpec(this.properties.getUriSpec());
configureServiceInstance(this.serviceInstance, this.appName,
this.context, this.port, host, uriSpec);
configureServiceDiscovery(this.serviceDiscovery, this.curator, this.properties,
this.instanceSerializer, this.serviceInstance);
if (this.properties.isRegister()) {
configureServiceInstance(this.serviceInstance, this.appName,
this.context, this.port, host, uriSpec);
}
}
}
/**
* Builds Service Discovery - needs to be used if you want to use Zookeeper as a client application.
* You don't have to register in Zookeeper to use Service Discovery.
*/
public void buildServiceDiscovery() {
configureServiceDiscovery(this.serviceDiscovery, this.curator, this.properties,
this.instanceSerializer, this.serviceInstance);
}
/**
* One can override this method to provide custom way of registering a service
* instance (e.g. when no payload is required).

View File

@@ -0,0 +1,101 @@
package org.springframework.cloud.zookeeper.discovery.issues.issue91;
import org.apache.curator.test.TestingServer;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.autoconfigure.EndpointMBeanExportAutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.SocketUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.jayway.awaitility.Awaitility;
import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Marcin Grzejszczak
*/
public class Issue91Tests {
TestingServer server;
String connectionString;
@Before
public void setup() throws Exception {
this.server = new TestingServer(SocketUtils.findAvailableTcpPort());
this.connectionString = "--spring.cloud.zookeeper.connectString=" + this.server.getConnectString();
}
@After
public void cleanup() throws Exception {
this.server.close();
}
@Test
public void should_work_when_using_web_client_without_the_web_environment()
throws Exception {
SpringApplication producerApp = new SpringApplication(HelloProducer.class);
producerApp.setWebEnvironment(true);
SpringApplication clientApplication = new SpringApplication(HelloClient.class);
clientApplication.setWebEnvironment(false);
try (ConfigurableApplicationContext producerContext = producerApp.run(this.connectionString, "--server.port=0",
"--spring.application.name=hello-world")) {
try (final ConfigurableApplicationContext context = clientApplication.run(this.connectionString,
"--spring.cloud.zookeeper.discovery.register=false")) {
Awaitility.await().until(new Runnable() {
@Override public void run() {
try {
HelloClient bean = context.getBean(HelloClient.class);
then(bean.discoveryClient.getServices()).isNotEmpty();
then(bean.discoveryClient.getInstances("hello-world")).isNotEmpty();
String string = bean.restTemplate.getForObject("http://hello-world/", String.class);
then(string).isEqualTo("foo");
} catch (IllegalStateException e) {
throw new AssertionError(e);
}
}
});
}
}
}
}
@EnableAutoConfiguration(exclude = {EndpointMBeanExportAutoConfiguration.class,
JmxAutoConfiguration.class})
@EnableDiscoveryClient
@Configuration
class HelloClient {
@LoadBalanced @Bean RestTemplate restTemplate() {
return new RestTemplate();
}
@Autowired DiscoveryClient discoveryClient;
@Autowired RestTemplate restTemplate;
}
@EnableAutoConfiguration(exclude = {EndpointMBeanExportAutoConfiguration.class,
JmxAutoConfiguration.class})
@EnableDiscoveryClient
@RestController
class HelloProducer {
@RequestMapping("/")
public String foo() {
return "foo";
}
}