diff --git a/docs/src/main/asciidoc/spring-cloud-commons.adoc b/docs/src/main/asciidoc/spring-cloud-commons.adoc index 73a8c438..38fdab00 100644 --- a/docs/src/main/asciidoc/spring-cloud-commons.adoc +++ b/docs/src/main/asciidoc/spring-cloud-commons.adoc @@ -321,6 +321,33 @@ By default, implementations of `DiscoveryClient` will auto-register the local Sp Commons now provides a `ServiceRegistry` interface which provides methods like `register(Registration)` and `deregister(Registration)` which allow you to provide custom registered services. `Registration` is a marker interface. +[source,java,indent=0] +---- +@Configuration +@EnableDiscoveryClient(autoRegister=false) +public class MyConfiguration { + private ServiceRegistry registry; + + public MyConfiguration(ServiceRegistry registry) { + this.registry = registry; + } + + // called via some external process, such as an event or a custom actuator endpoint + public void register() { + Registration registration = constructRegistration(); + this.registry.register(registration); + } +} +---- + +Each `ServiceRegistry` implementation has its own `Registry` implementation. + + +==== ServiceRegistry Auto-Registration + +By default, the `ServiceRegistry` implementation will auto-register the running service. To disable that behavior, there are two methods. You can set `@EnableDiscoveryClient(autoRegister=false)` to permanently disable auto-registration. You can also set `spring.cloud.service-registry.auto-registration.enabled=false` to disable the behavior via configuration. + + ==== Service Registry Actuator Endpoint A `/service-registry` actuator endpoint is provided by Commons. This endpoint relys on a `Registration` bean in the Spring Application Context. Calling `/service-registry/instance-status` via a GET will return the status of the `Registration`. A POST to the same endpoint with a `String` body will change the status of the current `Registration` to the new value. Please see the documentation of the `ServiceRegistry` implementation you are using for the allowed values for updating the status and the values retured for the status. @@ -362,9 +389,10 @@ for details of how the `RestTemplate` is set up. ==== Retrying Failed Requests A load balanced `RestTemplate` can be configured to retry failed requests. -By default this logic is disabled, you can enable it by setting -`spring.cloud.loadbalancer.retry.enabled=true`. The load balanced `RestTemplate` will -honor some of the Ribbon configuration values related to retrying failed requests. +By default this logic is disabled, you can enable it by adding link:https://github.com/spring-projects/spring-retry[Spring Retry] to your application's classpath. The load balanced `RestTemplate` will +honor some of the Ribbon configuration values related to retrying failed requests. If +you would like to disable the retry logic with Spring Retry on the classpath +you can set `spring.cloud.loadbalancer.retry.enabled=false`. The properties you can use are `client.ribbon.MaxAutoRetries`, `client.ribbon.MaxAutoRetriesNextServer`, and `client.ribbon.OkToRetryOnAllOperations`. See the https://github.com/Netflix/ribbon/wiki/Getting-Started#the-properties-file-sample-clientproperties[Ribbon documentation] diff --git a/mvnw b/mvnw index 0a7dac22..25f750cb 100755 --- a/mvnw +++ b/mvnw @@ -238,6 +238,14 @@ else echo $MAVEN_ARGS | grep -q milestone && MAVEN_ARGS=$(echo $MAVEN_ARGS | sed -e 's/-Pmilestone//') fi +if echo $VERSION | egrep -q 'RELEASE'; then + echo Activating \"central\" profile for version=\"$VERSION\" + echo $MAVEN_ARGS | grep -q milestone || MAVEN_ARGS="$MAVEN_ARGS -Pcentral" +else + echo Deactivating \"central\" profile for version=\"$VERSION\" + echo $MAVEN_ARGS | grep -q central && MAVEN_ARGS=$(echo $MAVEN_ARGS | sed -e 's/-Pcentral//') +fi + exec "$JAVACMD" \ $MAVEN_OPTS \ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ diff --git a/mvnw.cmd b/mvnw.cmd index fc830243..b0dc0e7e 100644 --- a/mvnw.cmd +++ b/mvnw.cmd @@ -1,145 +1,145 @@ -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Maven2 Start Up Batch script -@REM -@REM Required ENV vars: -@REM JAVA_HOME - location of a JDK home dir -@REM -@REM Optional ENV vars -@REM M2_HOME - location of maven2's installed home dir -@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands -@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending -@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven -@REM e.g. to debug Maven itself, use -@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files -@REM ---------------------------------------------------------------------------- - -@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' -@echo off -@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' -@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% - -@REM set %HOME% to equivalent of $HOME -if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") - -@REM Execute a user defined script before this one -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre -@REM check for pre script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" -if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" -:skipRcPre - -@setlocal - -set ERROR_CODE=0 - -@REM To isolate internal variables from possible post scripts, we use another setlocal -@setlocal - -@REM ==== START VALIDATION ==== -if not "%JAVA_HOME%" == "" goto OkJHome - -echo. -echo Error: JAVA_HOME not found in your environment. >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -:OkJHome -if exist "%JAVA_HOME%\bin\java.exe" goto init - -echo. -echo Error: JAVA_HOME is set to an invalid directory. >&2 -echo JAVA_HOME = "%JAVA_HOME%" >&2 -echo Please set the JAVA_HOME variable in your environment to match the >&2 -echo location of your Java installation. >&2 -echo. -goto error - -@REM ==== END VALIDATION ==== - -:init - -set MAVEN_CMD_LINE_ARGS=%* - -@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". -@REM Fallback to current working directory if not found. - -set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% -IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir - -set EXEC_DIR=%CD% -set WDIR=%EXEC_DIR% -:findBaseDir -IF EXIST "%WDIR%"\.mvn goto baseDirFound -cd .. -IF "%WDIR%"=="%CD%" goto baseDirNotFound -set WDIR=%CD% -goto findBaseDir - -:baseDirFound -set MAVEN_PROJECTBASEDIR=%WDIR% -cd "%EXEC_DIR%" -goto endDetectBaseDir - -:baseDirNotFound -set MAVEN_PROJECTBASEDIR=%EXEC_DIR% -cd "%EXEC_DIR%" - -:endDetectBaseDir - -IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig - -@setlocal EnableExtensions EnableDelayedExpansion -for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a -@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% - -:endReadAdditionalConfig - -SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +set MAVEN_CMD_LINE_ARGS=%* + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" set WRAPPER_JAR="".\.mvn\wrapper\maven-wrapper.jar"" -set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain - -%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% -if ERRORLEVEL 1 goto error -goto end - -:error -set ERROR_CODE=1 - -:end -@endlocal & set ERROR_CODE=%ERROR_CODE% - -if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost -@REM check for post script, once with legacy .bat ending and once with .cmd ending -if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" -if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" -:skipRcPost - -@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' -if "%MAVEN_BATCH_PAUSE%" == "on" pause - -if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% - -exit /B %ERROR_CODE% +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS% +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/pom.xml b/pom.xml index 4049312b..1023b238 100644 --- a/pom.xml +++ b/pom.xml @@ -26,23 +26,6 @@ - - org.apache.maven.plugins - maven-javadoc-plugin - - - aggregate - - aggregate-jar - - package - false - - true - - - - org.apache.maven.plugins maven-compiler-plugin @@ -68,23 +51,6 @@ - - org.apache.maven.plugins - maven-jar-plugin - 3.0.0 - - - - test-jar - - - - - - **/*.properties - - - diff --git a/spring-cloud-commons/pom.xml b/spring-cloud-commons/pom.xml index 48d2ad05..7e561f47 100644 --- a/spring-cloud-commons/pom.xml +++ b/spring-cloud-commons/pom.xml @@ -13,6 +13,28 @@ jar Spring Cloud Commons Spring Cloud Commons + + + + org.apache.maven.plugins + maven-jar-plugin + 3.0.0 + + + test-compile + + test-jar + + + + + + **/*.properties + + + + + org.springframework.boot diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/DiscoveryClient.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/DiscoveryClient.java index 41f429e4..c2d553d9 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/DiscoveryClient.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/DiscoveryClient.java @@ -21,7 +21,7 @@ import java.util.List; import org.springframework.cloud.client.ServiceInstance; /** - * DiscoveryClient represents operations commonly available to Discovery service such as + * DiscoveryClient represents read operations commonly available to Discovery service such as * Netflix Eureka or consul.io * @author Spencer Gibb */ diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClient.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClient.java index 6c6a9bc0..351b3458 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClient.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClient.java @@ -24,8 +24,13 @@ import org.springframework.cloud.client.discovery.DiscoveryClient; /** * DiscoveryClient used when no implementations are found on the classpath + * + * @deprecated Use {@link org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClient instead} + * * @author Dave Syer */ + +@Deprecated public class NoopDiscoveryClient implements DiscoveryClient { private final ServiceInstance instance; diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientAutoConfiguration.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientAutoConfiguration.java index 424d5930..6dd788b6 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientAutoConfiguration.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientAutoConfiguration.java @@ -39,12 +39,17 @@ import org.springframework.core.env.Environment; import lombok.extern.apachecommons.CommonsLog; /** + * + * @deprecated Use + * {@link org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration instead} + * * @author Dave Syer */ @Configuration @EnableConfigurationProperties @ConditionalOnMissingBean(DiscoveryClient.class) @CommonsLog +@Deprecated public class NoopDiscoveryClientAutoConfiguration implements ApplicationListener { diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClient.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClient.java new file mode 100644 index 00000000..95aa15ed --- /dev/null +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClient.java @@ -0,0 +1,50 @@ +package org.springframework.cloud.client.discovery.simple; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryProperties.SimpleServiceInstance; + +/** + * A {@link org.springframework.cloud.client.discovery.DiscoveryClient} that will use the + * properties file as a source of service instances + * + * @author Biju Kunjummen + */ +public class SimpleDiscoveryClient implements DiscoveryClient { + + private SimpleDiscoveryProperties simpleDiscoveryProperties; + + public SimpleDiscoveryClient(SimpleDiscoveryProperties simpleDiscoveryProperties) { + this.simpleDiscoveryProperties = simpleDiscoveryProperties; + } + + @Override + public String description() { + return "Simple Discovery Client"; + } + + @Override + public ServiceInstance getLocalServiceInstance() { + return null; + } + + @Override + public List getInstances(String serviceId) { + List serviceInstances = new ArrayList<>(); + List serviceInstanceForService = this.simpleDiscoveryProperties + .getInstances().get(serviceId); + + if (serviceInstanceForService != null) { + serviceInstances.addAll(serviceInstanceForService); + } + return serviceInstances; + } + + @Override + public List getServices() { + return new ArrayList<>(this.simpleDiscoveryProperties.getInstances().keySet()); + } +} diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientAutoConfiguration.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientAutoConfiguration.java new file mode 100644 index 00000000..9115daae --- /dev/null +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientAutoConfiguration.java @@ -0,0 +1,31 @@ +package org.springframework.cloud.client.discovery.simple; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.client.discovery.noop.NoopDiscoveryClientAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Spring Boot Auto-Configuration for Simple Properties based Discovery Client + * + * @author Biju Kunjummen + */ + +@Configuration +@ConditionalOnMissingBean(DiscoveryClient.class) +@EnableConfigurationProperties(SimpleDiscoveryProperties.class) +@AutoConfigureBefore(NoopDiscoveryClientAutoConfiguration.class) +public class SimpleDiscoveryClientAutoConfiguration { + + @Autowired + private SimpleDiscoveryProperties simpleDiscoveryProperties; + + @Bean + public DiscoveryClient simpleDiscoveryClient() { + return new SimpleDiscoveryClient(simpleDiscoveryProperties); + } +} diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryProperties.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryProperties.java new file mode 100644 index 00000000..5643edea --- /dev/null +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryProperties.java @@ -0,0 +1,85 @@ +package org.springframework.cloud.client.discovery.simple; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.client.ServiceInstance; + +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Properties to hold the details of a + * {@link org.springframework.cloud.client.discovery.DiscoveryClient} service instances + * for a given service + * + * @author Biju Kunjummen + */ + +@ConfigurationProperties(prefix = "spring.cloud.discovery.client.simple") +public class SimpleDiscoveryProperties { + private Map> instances = new HashMap<>(); + + public Map> getInstances() { + return instances; + } + + public void setInstances(Map> instances) { + this.instances = instances; + } + + public static class SimpleServiceInstance implements ServiceInstance { + + private URI resolvedUri; + private String host; + private int port; + private boolean secure; + + public SimpleServiceInstance() { + } + + public SimpleServiceInstance(String uri) { + setUri(uri); + } + + public void setUri(String uri) { + this.resolvedUri = URI.create(uri); + this.host = this.resolvedUri.getHost(); + this.port = this.resolvedUri.getPort(); + String scheme = this.resolvedUri.getScheme(); + if ("https".equals(scheme)) { + this.secure = true; + } + } + + @Override + public String getServiceId() { + return null; + } + + @Override + public String getHost() { + return this.host; + } + + @Override + public int getPort() { + return this.port; + } + + @Override + public boolean isSecure() { + return this.secure; + } + + @Override + public URI getUri() { + return this.resolvedUri; + } + + @Override + public Map getMetadata() { + return null; + } + } +} diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancedRetryPolicy.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancedRetryPolicy.java index 02ee113c..903f3e05 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancedRetryPolicy.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancedRetryPolicy.java @@ -49,4 +49,16 @@ public interface LoadBalancedRetryPolicy { * @param throwable the throwable from the failed execution. */ public abstract void registerThrowable(LoadBalancedRetryContext context, Throwable throwable); + + /** + * If an exception is not thrown when making a request, than this method will be + * called to see if the client would like to retry the request based on the status + * code returned. For example in CloudFoundry the router will return a 404 + * when an app is not available. Since HTTP clients do not throw an exception when + * a 404 is returned than retryableStatusCode allows + * clients to force a retry. + * @param statusCode The HTTP status code. + * @return True if a retry should be attempted, false to just return the response + */ + public boolean retryableStatusCode(int statusCode); } diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerRetryProperties.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerRetryProperties.java index 634249c0..b750d895 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerRetryProperties.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/loadbalancer/LoadBalancerRetryProperties.java @@ -23,7 +23,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; */ @ConfigurationProperties("spring.cloud.loadbalancer.retry") public class LoadBalancerRetryProperties { - private boolean enabled = false; + private boolean enabled = true; /** * Returns true if the load balancer should retry failed requests. diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/serviceregistry/Registration.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/serviceregistry/Registration.java index f9e31df1..9f3e7022 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/serviceregistry/Registration.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/serviceregistry/Registration.java @@ -1,7 +1,10 @@ package org.springframework.cloud.client.serviceregistry; /** + * A marker interface used by a {@link ServiceRegistry}. + * * @author Spencer Gibb + * @since 1.2.0 */ public interface Registration { diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/serviceregistry/ServiceRegistry.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/serviceregistry/ServiceRegistry.java index eb3d73ee..bcd695e8 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/serviceregistry/ServiceRegistry.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/serviceregistry/ServiceRegistry.java @@ -1,19 +1,48 @@ package org.springframework.cloud.client.serviceregistry; /** - * TODO: write javadoc + * Contract to register and deregister instances with a Service Registry. + * * @author Spencer Gibb + * @since 1.2.0 */ public interface ServiceRegistry { + + /** + * Register the registration. Registrations typically have information about + * instances such as: hostname and port. + * @param registration the registraion + */ void register(R registration); + /** + * Deregister the registration. + * @param registration + */ void deregister(R registration); + /** + * Close the ServiceRegistry. This a lifecycle method. + */ void close(); - // TODO: return value for success? + /** + * Sets the status of the registration. The status values are determined + * by the individual implementations. + * + * @see org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint + * @param registration the registration to update + * @param status the status to set + */ void setStatus(R registration, String status); - // TODO: concrete return value? Interface? - Object getStatus(R registration); + /** + * Gets the status of a particular registration. + * + * @see org.springframework.cloud.client.serviceregistry.endpoint.ServiceRegistryEndpoint + * @param registration the registration to query + * @param the type of the status + * @return the status of the registration + */ + T getStatus(R registration); } diff --git a/spring-cloud-commons/src/main/resources/META-INF/spring.factories b/spring-cloud-commons/src/main/resources/META-INF/spring.factories index e8cf54ed..4e17ff9a 100644 --- a/spring-cloud-commons/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-commons/src/main/resources/META-INF/spring.factories @@ -6,7 +6,8 @@ org.springframework.cloud.client.hypermedia.CloudHypermediaAutoConfiguration,\ org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration,\ org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\ org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,\ -org.springframework.cloud.commons.util.UtilAutoConfiguration +org.springframework.cloud.commons.util.UtilAutoConfiguration,\ +org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration # Environment Post Processors diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientConfigurationTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/DiscoveryClientAutoConfigurationDefaultTests.java similarity index 60% rename from spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientConfigurationTests.java rename to spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/DiscoveryClientAutoConfigurationDefaultTests.java index dfe1e1ee..b62e7aca 100644 --- a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientConfigurationTests.java +++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/DiscoveryClientAutoConfigurationDefaultTests.java @@ -1,4 +1,4 @@ -package org.springframework.cloud.client.discovery.noop; +package org.springframework.cloud.client.discovery.simple; import org.junit.Test; import org.junit.runner.RunWith; @@ -10,22 +10,22 @@ import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.junit4.SpringRunner; -import static org.junit.Assert.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; /** - * Tests if @EnableDiscoveryClient is NOT used, then NoopDiscoveryClient is created. - * @author Spencer Gibb + * DiscoveryClient implementation defaults to {@link SimpleDiscoveryClient} + * @author Biju Kunjummen */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = NoopDiscoveryClientConfigurationTests.App.class) -public class NoopDiscoveryClientConfigurationTests { +@SpringBootTest(classes = DiscoveryClientAutoConfigurationDefaultTests.App.class) +public class DiscoveryClientAutoConfigurationDefaultTests { @Autowired DiscoveryClient discoveryClient; @Test - public void testDiscoveryClientIsNoop() { - assertTrue("discoveryClient is wrong instance type", discoveryClient instanceof NoopDiscoveryClient); + public void simpleDiscoveryClientShouldBeTheDefault() { + assertThat(discoveryClient).isInstanceOf(SimpleDiscoveryClient.class); } @EnableAutoConfiguration diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientPropertiesMappingTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientPropertiesMappingTests.java new file mode 100644 index 00000000..6b6b7150 --- /dev/null +++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientPropertiesMappingTests.java @@ -0,0 +1,88 @@ +package org.springframework.cloud.client.discovery.simple; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +import java.net.URI; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for mapping properties to instances in {@link SimpleDiscoveryClient} + * + * @author Biju Kunjummen + */ + +@RunWith(SpringRunner.class) +@SpringBootTest(properties = { + "spring.cloud.discovery.client.simple.instances.service1[0].uri=http://s1-1:8080", + "spring.cloud.discovery.client.simple.instances.service1[1].uri=https://s1-2:8443", + "spring.cloud.discovery.client.simple.instances.service2[0].uri=https://s2-1:8080", + "spring.cloud.discovery.client.simple.instances.service2[1].uri=https://s2-2:443" }) +public class SimpleDiscoveryClientPropertiesMappingTests { + + @Autowired + private SimpleDiscoveryProperties props; + + @Autowired + private DiscoveryClient discoveryClient; + + @Test + public void propsShouldGetCleanlyMapped() { + assertThat(props.getInstances().size()).isEqualTo(2); + assertThat(props.getInstances().get("service1").size()).isEqualTo(2); + assertThat(props.getInstances().get("service1").get(0).getHost()) + .isEqualTo("s1-1"); + assertThat(props.getInstances().get("service1").get(0).getPort()).isEqualTo(8080); + assertThat(props.getInstances().get("service1").get(0).getUri()) + .isEqualTo(URI.create("http://s1-1:8080")); + assertThat(props.getInstances().get("service1").get(0).isSecure()) + .isEqualTo(false); + + assertThat(props.getInstances().get("service2").size()).isEqualTo(2); + assertThat(props.getInstances().get("service2").get(0).getHost()) + .isEqualTo("s2-1"); + assertThat(props.getInstances().get("service2").get(0).getPort()).isEqualTo(8080); + assertThat(props.getInstances().get("service2").get(0).getUri()) + .isEqualTo(URI.create("https://s2-1:8080")); + assertThat(props.getInstances().get("service2").get(0).isSecure()) + .isEqualTo(true); + } + + @Test + public void testDiscoveryClientShouldResolveSimpleValues() { + assertThat(this.discoveryClient.description()) + .isEqualTo("Simple Discovery Client"); + assertThat(this.discoveryClient.getInstances("service1")).hasSize(2); + + ServiceInstance s1 = this.discoveryClient.getInstances("service1").get(0); + assertThat(s1.getHost()).isEqualTo("s1-1"); + assertThat(s1.getPort()).isEqualTo(8080); + assertThat(s1.getUri()).isEqualTo(URI.create("http://s1-1:8080")); + assertThat(s1.isSecure()).isEqualTo(false); + } + + @Test + public void testGetServices() { + assertThat(this.discoveryClient.getServices()) + .containsExactlyInAnyOrder("service1", "service2"); + } + + @Test + public void testGetANonExistentServiceShouldReturnAnEmptyList() { + assertThat(this.discoveryClient.getInstances("nonexistent")).isNotNull(); + assertThat(this.discoveryClient.getInstances("nonexistent")).isEmpty(); + } + + @Configuration + @EnableAutoConfiguration + public static class SampleConfig { + } +} diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientTests.java new file mode 100644 index 00000000..a418901c --- /dev/null +++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/SimpleDiscoveryClientTests.java @@ -0,0 +1,47 @@ +package org.springframework.cloud.client.discovery.simple; + +import java.net.URI; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryProperties.SimpleServiceInstance; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Biju Kunjummen + */ +public class SimpleDiscoveryClientTests { + + private SimpleDiscoveryClient simpleDiscoveryClient; + + @Before + public void setUp() { + SimpleDiscoveryProperties simpleDiscoveryProperties = new SimpleDiscoveryProperties(); + + Map> map = new HashMap<>(); + SimpleServiceInstance service1Inst1 = new SimpleServiceInstance( + "http://host1:8080"); + SimpleServiceInstance service1Inst2 = new SimpleServiceInstance( + "https://host2:8443"); + map.put("service1", Arrays.asList(service1Inst1, service1Inst2)); + simpleDiscoveryProperties.setInstances(map); + this.simpleDiscoveryClient = new SimpleDiscoveryClient(simpleDiscoveryProperties); + } + + @Test + public void shouldBeAbleToRetrieveServiceDetailsByName() { + List instances = this.simpleDiscoveryClient + .getInstances("service1"); + assertThat(instances.size()).isEqualTo(2); + assertThat(instances.get(0).getHost()).isEqualTo("host1"); + assertThat(instances.get(0).getPort()).isEqualTo(8080); + assertThat(instances.get(0).getUri()).isEqualTo(URI.create("http://host1:8080")); + assertThat(instances.get(0).isSecure()).isEqualTo(false); + } +} diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientConfigurationAdditionalTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/UserDefinedDiscoveryClientOverridesDefaultsTests.java similarity index 72% rename from spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientConfigurationAdditionalTests.java rename to spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/UserDefinedDiscoveryClientOverridesDefaultsTests.java index ca1d3e8b..04672f17 100644 --- a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/noop/NoopDiscoveryClientConfigurationAdditionalTests.java +++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/simple/UserDefinedDiscoveryClientOverridesDefaultsTests.java @@ -1,6 +1,4 @@ -package org.springframework.cloud.client.discovery.noop; - -import java.util.List; +package org.springframework.cloud.client.discovery.simple; import org.junit.Test; import org.junit.runner.RunWith; @@ -14,22 +12,26 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.junit4.SpringRunner; -import static org.junit.Assert.assertFalse; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; /** - * Tests if @EnableDiscoveryClient is NOT used, then NoopDiscoveryClient is created. - * @author Spencer Gibb + * @author Biju Kunjummen */ @RunWith(SpringRunner.class) -@SpringBootTest(classes = NoopDiscoveryClientConfigurationAdditionalTests.App.class) -public class NoopDiscoveryClientConfigurationAdditionalTests { +@SpringBootTest(classes = UserDefinedDiscoveryClientOverridesDefaultsTests.App.class) +public class UserDefinedDiscoveryClientOverridesDefaultsTests { @Autowired DiscoveryClient discoveryClient; @Test public void testDiscoveryClientIsNotNoop() { - assertFalse("discoveryClient is wrong instance type", discoveryClient instanceof NoopDiscoveryClient); + assertThat(discoveryClient).isNotInstanceOf(SimpleDiscoveryClient.class); + + assertThat(discoveryClient.description()) + .isEqualTo("user defined discovery client"); } @EnableAutoConfiguration @@ -41,7 +43,7 @@ public class NoopDiscoveryClientConfigurationAdditionalTests { return new DiscoveryClient() { @Override public String description() { - return null; + return "user defined discovery client"; } @Override diff --git a/spring-cloud-context/pom.xml b/spring-cloud-context/pom.xml index cb41aa42..8d15c17b 100644 --- a/spring-cloud-context/pom.xml +++ b/spring-cloud-context/pom.xml @@ -59,5 +59,12 @@ spring-boot-starter-test test + + org.springframework.cloud + spring-cloud-commons + ${project.version} + test-jar + test + diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/autoconfigure/RefreshAutoConfiguration.java b/spring-cloud-context/src/main/java/org/springframework/cloud/autoconfigure/RefreshAutoConfiguration.java index 36ccf711..439b48fc 100644 --- a/spring-cloud-context/src/main/java/org/springframework/cloud/autoconfigure/RefreshAutoConfiguration.java +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/autoconfigure/RefreshAutoConfiguration.java @@ -30,6 +30,7 @@ import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguratio import org.springframework.cloud.context.environment.EnvironmentManager; import org.springframework.cloud.context.refresh.ContextRefresher; import org.springframework.cloud.context.scope.refresh.RefreshScope; +import org.springframework.cloud.endpoint.event.RefreshEventListener; import org.springframework.cloud.logging.LoggingRebinder; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; @@ -89,4 +90,10 @@ public class RefreshAutoConfiguration { return new ContextRefresher(context, scope); } + @Bean + public RefreshEventListener refreshEventListener( + ContextRefresher contextRefresher) { + return new RefreshEventListener(contextRefresher); + } + } diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/autoconfigure/RefreshEndpointAutoConfiguration.java b/spring-cloud-context/src/main/java/org/springframework/cloud/autoconfigure/RefreshEndpointAutoConfiguration.java index 32c58d29..38fb06ce 100644 --- a/spring-cloud-context/src/main/java/org/springframework/cloud/autoconfigure/RefreshEndpointAutoConfiguration.java +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/autoconfigure/RefreshEndpointAutoConfiguration.java @@ -16,16 +16,10 @@ package org.springframework.cloud.autoconfigure; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.boot.actuate.autoconfigure.ConditionalOnEnabledHealthIndicator; import org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration; import org.springframework.boot.actuate.endpoint.Endpoint; -import org.springframework.boot.actuate.endpoint.InfoEndpoint; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -34,18 +28,14 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClas import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration; -import org.springframework.cloud.context.environment.EnvironmentChangeEvent; import org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder; import org.springframework.cloud.context.refresh.ContextRefresher; import org.springframework.cloud.context.restart.RestartEndpoint; import org.springframework.cloud.context.scope.refresh.RefreshScope; import org.springframework.cloud.endpoint.RefreshEndpoint; -import org.springframework.cloud.endpoint.event.RefreshEventListener; import org.springframework.cloud.health.RefreshScopeHealthIndicator; -import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.integration.monitor.IntegrationMBeanExporter; /** @@ -119,11 +109,5 @@ public class RefreshEndpointAutoConfiguration { return endpoint; } - @Bean - public RefreshEventListener refreshEventListener( - RefreshEndpoint refreshEndpoint) { - return new RefreshEventListener(refreshEndpoint); - } - } } \ No newline at end of file diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/encrypt/EncryptionBootstrapConfiguration.java b/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/encrypt/EncryptionBootstrapConfiguration.java index 5996f263..17b53742 100644 --- a/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/encrypt/EncryptionBootstrapConfiguration.java +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/encrypt/EncryptionBootstrapConfiguration.java @@ -21,6 +21,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.autoconfigure.condition.SpringBootCondition; +import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.bootstrap.encrypt.KeyProperties.KeyStore; import org.springframework.cloud.context.encrypt.EncryptorFactory; @@ -109,21 +110,22 @@ public class EncryptionBootstrapConfiguration { public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { Environment environment = context.getEnvironment(); - if (hasProperty(environment, "encrypt.keyStore.location")) { - if (hasProperty(environment, "encrypt.keyStore.password")) { + RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(environment); + if (hasProperty(propertyResolver, environment, "encrypt.keyStore.location")) { + if (hasProperty(propertyResolver, environment, "encrypt.keyStore.password")) { return ConditionOutcome.match("Keystore found in Environment"); } return ConditionOutcome .noMatch("Keystore found but no password in Environment"); } - else if (hasProperty(environment, "encrypt.key")) { + else if (hasProperty(propertyResolver, environment, "encrypt.key")) { return ConditionOutcome.match("Key found in Environment"); } return ConditionOutcome.noMatch("Keystore nor key found in Environment"); } - private boolean hasProperty(Environment environment, String key) { - String value = environment.getProperty(key); + private boolean hasProperty(RelaxedPropertyResolver propertyResolver, Environment environment, String key) { + String value = propertyResolver.getProperty(key); if (value == null) { return false; } diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/endpoint/event/RefreshEventListener.java b/spring-cloud-context/src/main/java/org/springframework/cloud/endpoint/event/RefreshEventListener.java index 4cda9706..16cf5e7f 100644 --- a/spring-cloud-context/src/main/java/org/springframework/cloud/endpoint/event/RefreshEventListener.java +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/endpoint/event/RefreshEventListener.java @@ -1,25 +1,25 @@ package org.springframework.cloud.endpoint.event; -import java.util.Arrays; +import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import org.springframework.boot.context.event.ApplicationReadyEvent; -import org.springframework.cloud.endpoint.RefreshEndpoint; +import org.springframework.cloud.context.refresh.ContextRefresher; import org.springframework.context.event.EventListener; import lombok.extern.apachecommons.CommonsLog; /** - * Calls {@link RefreshEndpoint#refresh()} when a {@link RefreshEvent} is received. + * Calls {@link RefreshEventListener#refresh} when a {@link RefreshEvent} is received. * Only responds to {@link RefreshEvent} after receiving an {@link ApplicationReadyEvent} as the RefreshEvent's might come to early in the application lifecycle. * @author Spencer Gibb */ @CommonsLog public class RefreshEventListener { - private RefreshEndpoint refresh; + private ContextRefresher refresh; private AtomicBoolean ready = new AtomicBoolean(false); - public RefreshEventListener(RefreshEndpoint refresh) { + public RefreshEventListener(ContextRefresher refresh) { this.refresh = refresh; } @@ -32,8 +32,8 @@ public class RefreshEventListener { public void handle(RefreshEvent event) { if (this.ready.get()) { // don't handle events before app is ready log.debug("Event received " + event.getEventDesc()); - String[] keys = this.refresh.refresh(); - log.info("Refresh keys changed: " + Arrays.asList(keys)); + Set keys = this.refresh.refresh(); + log.info("Refresh keys changed: " + keys); } } } diff --git a/spring-cloud-context/src/test/java/org/springframework/cloud/autoconfigure/RefreshAutoConfigurationClassPathTests.java b/spring-cloud-context/src/test/java/org/springframework/cloud/autoconfigure/RefreshAutoConfigurationClassPathTests.java new file mode 100644 index 00000000..a6b190cb --- /dev/null +++ b/spring-cloud-context/src/test/java/org/springframework/cloud/autoconfigure/RefreshAutoConfigurationClassPathTests.java @@ -0,0 +1,42 @@ +package org.springframework.cloud.autoconfigure; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.cloud.ClassPathExclusions; +import org.springframework.cloud.FilteredClassPathRunner; +import org.springframework.cloud.endpoint.event.RefreshEventListener; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Configuration; + +import static org.junit.Assert.assertFalse; + +/** + * @author Spencer Gibb + */ +@RunWith(FilteredClassPathRunner.class) +@ClassPathExclusions({"spring-boot-actuator-*.jar", "spring-boot-starter-actuator-*.jar"}) +public class RefreshAutoConfigurationClassPathTests { + + @Test + public void refreshEventListenerCreated() { + try (ConfigurableApplicationContext context = getApplicationContext( + Config.class)) { + assertFalse(context.getBeansOfType(RefreshEventListener.class).isEmpty()); + assertFalse(context.containsBean("refeshEndpoint")); + } + } + + private static ConfigurableApplicationContext getApplicationContext( + Class configuration, String... properties) { + return new SpringApplicationBuilder(configuration).web(false) + .properties(properties).run(); + } + + @Configuration + @EnableAutoConfiguration + static class Config { + + } +} diff --git a/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/encrypt/EncryptionBootstrapConfigurationTests.java b/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/encrypt/EncryptionBootstrapConfigurationTests.java index 52c654ba..91d67cdc 100644 --- a/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/encrypt/EncryptionBootstrapConfigurationTests.java +++ b/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/encrypt/EncryptionBootstrapConfigurationTests.java @@ -19,6 +19,20 @@ public class EncryptionBootstrapConfigurationTests { .run(); TextEncryptor encryptor = context.getBean(TextEncryptor.class); assertEquals("foo", encryptor.decrypt(encryptor.encrypt("foo"))); + context.close(); + } + + @Test + public void rsaKeyStoreWithRelaxedProperties() { + ConfigurableApplicationContext context = new SpringApplicationBuilder( + EncryptionBootstrapConfiguration.class).web(false).properties( + "encrypt.key-store.location:classpath:/server.jks", + "encrypt.key-store.password:letmein", + "encrypt.key-store.alias:mytestkey", "encrypt.key-store.secret:changeme") + .run(); + TextEncryptor encryptor = context.getBean(TextEncryptor.class); + assertEquals("foo", encryptor.decrypt(encryptor.encrypt("foo"))); + context.close(); } }