diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..9df3ab04 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +/application.yml +/application.properties +asciidoctor.css +*~ +.#* +*# +target +bin +_site/ +.classpath +.project +.settings +.springBeans +.DS_Store +*.sw* +*.iml +.idea +.factorypath diff --git a/spring-cloud-commons/.settings.xml b/.settings.xml similarity index 100% rename from spring-cloud-commons/.settings.xml rename to .settings.xml diff --git a/spring-cloud-context/.travis.yml b/.travis.yml similarity index 96% rename from spring-cloud-context/.travis.yml rename to .travis.yml index d142bde0..0c61dedd 100644 --- a/spring-cloud-context/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ before_install: - 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 +- ./docs/src/main/asciidoc/ghpages.sh script: - '[ "${TRAVIS_PULL_REQUEST}" != "false" ] || mvn --settings .settings.xml deploy -nsu -Dmaven.test.redirectTestOutputToFile=true' diff --git a/README.adoc b/README.adoc new file mode 100644 index 00000000..26f18f4d --- /dev/null +++ b/README.adoc @@ -0,0 +1,6 @@ +// Do not edit this file (e.g. go instead to src/main/asciidoc) + + +http://pivotal.io/platform-as-a-service/migrating-to-cloud-native-application-architectures-ebook[Cloud Native] is a style of application development that encourages easy adoption of best practices in the areas of continuous delivery and value-driven development. A related discipline is that of building http://12factor.net/[12-factor Apps] in which development practices are aligned with delivery and operations goals, for instance by using declarative programming and management and monitoring. Spring Cloud facilitates these styles of development in a number of specific ways and the starting point is a set of features that all components in a distributed system either need or need easy access to when required. + +Many of those features are covered by http://projects.spring.io/spring-boot[Spring Boot], which we build on in Spring Cloud. Some more are delivered by Spring Cloud as two libraries: Spring Cloud Context and Spring Cloud Commons. Spring Cloud Context provides utilities and special services for the `ApplicationContext` of a Spring Cloud application (bootstrap context, encryption, refresh scope and environment endpoints). Spring Cloud Commons is a set of abstractions and common classes used in different Spring Cloud implementations (eg. Spring Cloud Netflix vs. Spring Cloud Consul). \ No newline at end of file diff --git a/docs/src/main/adoc/README.adoc b/docs/src/main/adoc/README.adoc deleted file mode 100644 index 4a5fff5a..00000000 --- a/docs/src/main/adoc/README.adoc +++ /dev/null @@ -1,3 +0,0 @@ -= Spring Cloud Commons and Context - -Common classes used in different Spring Cloud implementations (eg. Spring Cloud Netflix vs. Spring Cloud Consul). \ No newline at end of file diff --git a/docs/src/main/asciidoc/README.adoc b/docs/src/main/asciidoc/README.adoc new file mode 100644 index 00000000..349f19eb --- /dev/null +++ b/docs/src/main/asciidoc/README.adoc @@ -0,0 +1 @@ +include::intro.adoc[] diff --git a/docs/src/main/asciidoc/intro.adoc b/docs/src/main/asciidoc/intro.adoc new file mode 100644 index 00000000..ff500372 --- /dev/null +++ b/docs/src/main/asciidoc/intro.adoc @@ -0,0 +1,4 @@ + +http://pivotal.io/platform-as-a-service/migrating-to-cloud-native-application-architectures-ebook[Cloud Native] is a style of application development that encourages easy adoption of best practices in the areas of continuous delivery and value-driven development. A related discipline is that of building http://12factor.net/[12-factor Apps] in which development practices are aligned with delivery and operations goals, for instance by using declarative programming and management and monitoring. Spring Cloud facilitates these styles of development in a number of specific ways and the starting point is a set of features that all components in a distributed system either need or need easy access to when required. + +Many of those features are covered by http://projects.spring.io/spring-boot[Spring Boot], which we build on in Spring Cloud. Some more are delivered by Spring Cloud as two libraries: Spring Cloud Context and Spring Cloud Commons. Spring Cloud Context provides utilities and special services for the `ApplicationContext` of a Spring Cloud application (bootstrap context, encryption, refresh scope and environment endpoints). Spring Cloud Commons is a set of abstractions and common classes used in different Spring Cloud implementations (eg. Spring Cloud Netflix vs. Spring Cloud Consul). \ No newline at end of file diff --git a/docs/src/main/adoc/spring-cloud-commons.adoc b/docs/src/main/asciidoc/spring-cloud-commons.adoc similarity index 93% rename from docs/src/main/adoc/spring-cloud-commons.adoc rename to docs/src/main/asciidoc/spring-cloud-commons.adoc index 9a532b35..b3f06dca 100644 --- a/docs/src/main/adoc/spring-cloud-commons.adoc +++ b/docs/src/main/asciidoc/spring-cloud-commons.adoc @@ -1,99 +1,22 @@ -=== Environment Changes += Cloud Native Applications +:toc: -The application will listen for an `EnvironmentChangedEvent` and react -to the change in a couple of standard ways (additional -`ApplicationListeners` can be added as `@Beans` by the user in the -normal way). When an `EnvironmentChangedEvent` is observed it will -have a list of key values that have changed, and the application will -use those to: +include::intro.adoc[] -* Re-bind any `@ConfigurationProperties` beans in the context -* Set the logger levels for any properties in `logging.level.*` +== Spring Cloud Context: Application Context Services -Note that the Config Client does not by default poll for changes in -the `Environment`, and generally we would not recommend that approach -for detecting changes (although you could set it up with a -`@Scheduled` annotation). If you have a scaled-out client application -then it is better to broadcast the `EnvironmentChangedEvent` to all -the instances instead of having them polling for changes (e.g. using -the https://github.com/spring-cloud/spring-cloud-bus[Spring Cloud -Bus]). - -The `EnvironmentChangedEvent` covers a large class of refresh use -cases, as long as you can actually make a change to the `Environment` -and publish the event (those APIs are public and part of core -Spring). You can verify the changes are bound to -`@ConfigurationProperties` beans by visiting the `/configprops` -endpoint (normal Spring Boot Actuator feature). For instance a -`DataSource` can have its `maxPoolSize` changed at runtime (the -default `DataSource` created by Spring Boot is an -`@ConfigurationProperties` bean) and grow capacity -dynamically. Re-binding `@ConfigurationProperties` does not cover -another large class of use cases, where you need more control over the -refresh, and where you need a change to be atomic over the whole -`ApplicationContext`. To address those concerns we have -`@RefreshScope`. - -=== Refresh Scope - -A Spring `@Bean` that is marked as `@RefreshScope` will get special -treatment when there is a configuration change. This addresses the -problem of stateful beans that only get their configuration injected -when they are initialized. For instance if a `DataSource` has open -connections when the database URL is changed via the `Environment`, we -probably want the holders of those connections to be able to complete -what they are doing. Then the next time someone borrows a connection -from the pool he gets one with the new URL. - -Refresh scope beans are lazy proxies that initialize when they are -used (i.e. when a method is called), and the scope acts as a cache of -initialized values. To force a bean to re-initialize on the next -method call you just need to invalidate its cache entry. - -The `RefreshScope` is a bean in the context and it has a public method -`refreshAll()` to refresh all beans in the scope by clearing the -target cache. There is also a `refresh(String)` method to refresh an -individual bean by name. This functionality is exposed in the -`/refresh` endpoint (over HTTP or JMX). - -NOTE: `@RefreshScope` works (technically) on an `@Configuration` -class, but it might lead to surprising behaviour: e.g. it does *not* -mean that all the `@Beans` defined in that class are themselves -`@RefreshScope`. Specifically, anything that depends on those beans -cannot rely on them being updated when a refresh is initiated, unless -it is itself in `@RefreshScope` (in which it will be rebuilt on a -refresh and its dependencies re-injected, at which point they will be -re-initialized from the refreshed `@Configuration`). - -=== Encryption and Decryption - -The Config Client has an `Environment` pre-processor for decrypting -property values locally. It follows the same rules as the Config -Server, and has the same external configuration via `encrypt.\*`. Thus -you can use encrypted values in the form `{cipher}*` and as long as -there is a valid key then they will be decrypted before the main -application context gets the `Environment`. To use the encryption -features in a client you need to include Spring Security RSA in your -classpath (Maven co-ordinates -"org.springframework.security:spring-security-rsa") and you also need -the full strength JCE extensions in your JVM (google it and download -from Oracle). - -=== Endpoints - -For a Spring Boot Actuator application there are some additional management endpoints: - -* POST to `/env` to update the `Environment` and rebind `@ConfigurationProperties` and log levels -* `/refresh` for re-loading the boot strap context and refreshing the `@RefreshScope` beans -* `/restart` for closing the `ApplicationContext` and restarting it (disabled by default) -* `/pause` and `/resume` for calling the `Lifecycle` methods (`stop()` and `start()` on the `ApplicationContext`) +Spring Boot has an opinionated view of how to build an application +with Spring: for instance it has conventional locations for common +configuration file, and endpoints for common management and monitoring +tasks. Spring Cloud builds on top of that and adds a few features that +probably all components in a system would use or occasionally need. === The Bootstrap Application Context -The Config Client operates by creating a "bootstrap" application +A Spring Cloud application operates by creating a "bootstrap" context, which is a parent context for the main application. Out of the box it is responsible for loading configuration properties from -the Config Server, and also decrypting properties in the local +the external sources, and also decrypting properties in the local external configuration files. The two contexts share an `Environment` which is the source of external properties for any Spring application. Bootstrap properties are added with high precedence, so @@ -255,3 +178,96 @@ org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomP then the "customProperty" `PropertySource` will show up in any application that includes that jar on its classpath. +=== Environment Changes + +The application will listen for an `EnvironmentChangedEvent` and react +to the change in a couple of standard ways (additional +`ApplicationListeners` can be added as `@Beans` by the user in the +normal way). When an `EnvironmentChangedEvent` is observed it will +have a list of key values that have changed, and the application will +use those to: + +* Re-bind any `@ConfigurationProperties` beans in the context +* Set the logger levels for any properties in `logging.level.*` + +Note that the Config Client does not by default poll for changes in +the `Environment`, and generally we would not recommend that approach +for detecting changes (although you could set it up with a +`@Scheduled` annotation). If you have a scaled-out client application +then it is better to broadcast the `EnvironmentChangedEvent` to all +the instances instead of having them polling for changes (e.g. using +the https://github.com/spring-cloud/spring-cloud-bus[Spring Cloud +Bus]). + +The `EnvironmentChangedEvent` covers a large class of refresh use +cases, as long as you can actually make a change to the `Environment` +and publish the event (those APIs are public and part of core +Spring). You can verify the changes are bound to +`@ConfigurationProperties` beans by visiting the `/configprops` +endpoint (normal Spring Boot Actuator feature). For instance a +`DataSource` can have its `maxPoolSize` changed at runtime (the +default `DataSource` created by Spring Boot is an +`@ConfigurationProperties` bean) and grow capacity +dynamically. Re-binding `@ConfigurationProperties` does not cover +another large class of use cases, where you need more control over the +refresh, and where you need a change to be atomic over the whole +`ApplicationContext`. To address those concerns we have +`@RefreshScope`. + +=== Refresh Scope + +A Spring `@Bean` that is marked as `@RefreshScope` will get special +treatment when there is a configuration change. This addresses the +problem of stateful beans that only get their configuration injected +when they are initialized. For instance if a `DataSource` has open +connections when the database URL is changed via the `Environment`, we +probably want the holders of those connections to be able to complete +what they are doing. Then the next time someone borrows a connection +from the pool he gets one with the new URL. + +Refresh scope beans are lazy proxies that initialize when they are +used (i.e. when a method is called), and the scope acts as a cache of +initialized values. To force a bean to re-initialize on the next +method call you just need to invalidate its cache entry. + +The `RefreshScope` is a bean in the context and it has a public method +`refreshAll()` to refresh all beans in the scope by clearing the +target cache. There is also a `refresh(String)` method to refresh an +individual bean by name. This functionality is exposed in the +`/refresh` endpoint (over HTTP or JMX). + +NOTE: `@RefreshScope` works (technically) on an `@Configuration` +class, but it might lead to surprising behaviour: e.g. it does *not* +mean that all the `@Beans` defined in that class are themselves +`@RefreshScope`. Specifically, anything that depends on those beans +cannot rely on them being updated when a refresh is initiated, unless +it is itself in `@RefreshScope` (in which it will be rebuilt on a +refresh and its dependencies re-injected, at which point they will be +re-initialized from the refreshed `@Configuration`). + +=== Encryption and Decryption + +The Config Client has an `Environment` pre-processor for decrypting +property values locally. It follows the same rules as the Config +Server, and has the same external configuration via `encrypt.\*`. Thus +you can use encrypted values in the form `{cipher}*` and as long as +there is a valid key then they will be decrypted before the main +application context gets the `Environment`. To use the encryption +features in a client you need to include Spring Security RSA in your +classpath (Maven co-ordinates +"org.springframework.security:spring-security-rsa") and you also need +the full strength JCE extensions in your JVM (google it and download +from Oracle). + +=== Endpoints + +For a Spring Boot Actuator application there are some additional management endpoints: + +* POST to `/env` to update the `Environment` and rebind `@ConfigurationProperties` and log levels +* `/refresh` for re-loading the boot strap context and refreshing the `@RefreshScope` beans +* `/restart` for closing the `ApplicationContext` and restarting it (disabled by default) +* `/pause` and `/resume` for calling the `Lifecycle` methods (`stop()` and `start()` on the `ApplicationContext`) + +== Spring Cloud Commons: Common Abstractions + +Patterns such as service discovery, load balancing and circuit breakers lend themselves to a common abstraction layer that can be consumed by all Spring Cloud clients, independent of the implementation (e.g. discovery via Eureka or Consul). \ No newline at end of file diff --git a/docs/src/main/ruby/generate_readme.sh b/docs/src/main/ruby/generate_readme.sh new file mode 100755 index 00000000..79aadce4 --- /dev/null +++ b/docs/src/main/ruby/generate_readme.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env ruby + +base_dir = File.join(File.dirname(__FILE__),'../../..') +src_dir = File.join(base_dir, "/src/main/asciidoc") +require 'asciidoctor' +require 'optparse' + +options = {} +file = "#{src_dir}/README.adoc" + +OptionParser.new do |o| + o.on('-o OUTPUT_FILE', 'Output file (default is stdout)') { |file| options[:to_file] = file unless file=='-' } + o.on('-h', '--help') { puts o; exit } + o.parse! +end + +file = ARGV[0] if ARGV.length>0 + +srcDir = File.dirname(file) +out = "// Do not edit this file (e.g. go instead to src/main/asciidoc)\n\n" +doc = Asciidoctor.load_file file, safe: :safe, parse: false, attributes: 'allow-uri-read' +out << doc.reader.read + +unless options[:to_file] + puts out +else + File.open(options[:to_file],'w+') do |file| + file.write(out) + end +end diff --git a/spring-cloud-commons/.gitignore b/spring-cloud-commons/.gitignore deleted file mode 100644 index 8c5133e4..00000000 --- a/spring-cloud-commons/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -*~ -#* -*# -.#* -.classpath -.project -.settings/ -.springBeans -target/ -_site/ -.idea -*.iml -*.swp diff --git a/spring-cloud-commons/.travis.yml b/spring-cloud-commons/.travis.yml deleted file mode 100644 index d142bde0..00000000 --- a/spring-cloud-commons/.travis.yml +++ /dev/null @@ -1,25 +0,0 @@ -sudo: false -cache: - directories: - - $HOME/.m2 -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="Spencer Gibb" - - GIT_EMAIL=sgibb@pivotal.io - - CI_DEPLOY_USERNAME=sgibb - - secure: WPmrAQJQGBziwGFKwTiDRGrG1nuy9dvoWOQt7WKHW0RBqDbUpZgGeHq6OD2FcE86eRo+tPDihyunsWltei+sfq5bUECkGFQBLGffcTuxyu2j4lTByVazeYKa3en3j7nOiQjI99MqgCHrdyRwtS9EF1SnYXRuSZXwb0Ic8h4Zns4= diff --git a/spring-cloud-context/.gitignore b/spring-cloud-context/.gitignore deleted file mode 100644 index 8c5133e4..00000000 --- a/spring-cloud-context/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -*~ -#* -*# -.#* -.classpath -.project -.settings/ -.springBeans -target/ -_site/ -.idea -*.iml -*.swp diff --git a/spring-cloud-context/.settings.xml b/spring-cloud-context/.settings.xml deleted file mode 100644 index 006f51ef..00000000 --- a/spring-cloud-context/.settings.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - repo.spring.io - ${env.CI_DEPLOY_USERNAME} - ${env.CI_DEPLOY_PASSWORD} - - - - - spring - true - - - spring-snapshots - Spring Snapshots - http://repo.spring.io/libs-snapshot-local - - true - - - - spring-milestones - Spring Milestones - http://repo.spring.io/libs-milestone-local - - false - - - - spring-releases - Spring Releases - http://repo.spring.io/release - - false - - - - - - spring-snapshots - Spring Snapshots - http://repo.spring.io/libs-snapshot-local - - true - - - - spring-milestones - Spring Milestones - http://repo.spring.io/libs-milestone-local - - false - - - - - -