diff --git a/spring-cloud-bus/2.1.0.RC3/css/highlight.css b/spring-cloud-bus/2.1.0.RC3/css/highlight.css new file mode 100644 index 00000000..ffefef72 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/css/highlight.css @@ -0,0 +1,35 @@ +/* + code highlight CSS resemblign the Eclipse IDE default color schema + @author Costin Leau +*/ + +.hl-keyword { + color: #7F0055; + font-weight: bold; +} + +.hl-comment { + color: #3F5F5F; + font-style: italic; +} + +.hl-multiline-comment { + color: #3F5FBF; + font-style: italic; +} + +.hl-tag { + color: #3F7F7F; +} + +.hl-attribute { + color: #7F007F; +} + +.hl-value { + color: #2A00FF; +} + +.hl-string { + color: #2A00FF; +} \ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/css/manual-multipage.css b/spring-cloud-bus/2.1.0.RC3/css/manual-multipage.css new file mode 100644 index 00000000..0c484531 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/css/manual-multipage.css @@ -0,0 +1,9 @@ +@IMPORT url("manual.css"); + +body.firstpage { + background: url("../images/background.png") no-repeat center top; +} + +div.part h1 { + border-top: none; +} diff --git a/spring-cloud-bus/2.1.0.RC3/css/manual-singlepage.css b/spring-cloud-bus/2.1.0.RC3/css/manual-singlepage.css new file mode 100644 index 00000000..4a7fd140 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/css/manual-singlepage.css @@ -0,0 +1,6 @@ +@IMPORT url("manual.css"); + +body { + background: url("../images/background.png") no-repeat center top; +} + diff --git a/spring-cloud-bus/2.1.0.RC3/css/manual.css b/spring-cloud-bus/2.1.0.RC3/css/manual.css new file mode 100644 index 00000000..0ecbe2e8 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/css/manual.css @@ -0,0 +1,344 @@ +@IMPORT url("highlight.css"); + +html { + padding: 0pt; + margin: 0pt; +} + +body { + color: #333333; + margin: 15px 30px; + font-family: Helvetica, Arial, Freesans, Clean, Sans-serif; + line-height: 1.6; + -webkit-font-smoothing: antialiased; +} + +code { + font-size: 16px; + font-family: Consolas, "Liberation Mono", Courier, monospace; +} + +:not(a)>code { + color: #6D180B; +} + +:not(pre)>code { + background-color: #F2F2F2; + border: 1px solid #CCCCCC; + border-radius: 4px; + padding: 1px 3px 0; + text-shadow: none; + white-space: nowrap; +} + +body>*:first-child { + margin-top: 0 !important; +} + +div { + margin: 0pt; +} + +hr { + border: 1px solid #CCCCCC; + background: #CCCCCC; +} + +h1,h2,h3,h4,h5,h6 { + color: #000000; + cursor: text; + font-weight: bold; + margin: 30px 0 10px; + padding: 0; +} + +h1,h2,h3 { + margin: 40px 0 10px; +} + +h1 { + margin: 70px 0 30px; + padding-top: 20px; +} + +div.part h1 { + border-top: 1px dotted #CCCCCC; +} + +h1,h1 code { + font-size: 32px; +} + +h2,h2 code { + font-size: 24px; +} + +h3,h3 code { + font-size: 20px; +} + +h4,h1 code,h5,h5 code,h6,h6 code { + font-size: 18px; +} + +div.book,div.chapter,div.appendix,div.part,div.preface { + min-width: 300px; + max-width: 1200px; + margin: 0 auto; +} + +p.releaseinfo { + font-weight: bold; + margin-bottom: 40px; + margin-top: 40px; +} + +div.authorgroup { + line-height: 1; +} + +p.copyright { + line-height: 1; + margin-bottom: -5px; +} + +.legalnotice p { + font-style: italic; + font-size: 14px; + line-height: 1; +} + +div.titlepage+p,div.titlepage+p { + margin-top: 0; +} + +pre { + line-height: 1.0; + color: black; +} + +a { + color: #4183C4; + text-decoration: none; +} + +p { + margin: 15px 0; + text-align: left; +} + +ul,ol { + padding-left: 30px; +} + +li p { + margin: 0; +} + +div.table { + margin: 1em; + padding: 0.5em; + text-align: center; +} + +div.table table,div.informaltable table { + display: table; + width: 100%; +} + +div.table td { + padding-left: 7px; + padding-right: 7px; +} + +.sidebar { + line-height: 1.4; + padding: 0 20px; + background-color: #F8F8F8; + border: 1px solid #CCCCCC; + border-radius: 3px 3px 3px 3px; +} + +.sidebar p.title { + color: #6D180B; +} + +pre.programlisting,pre.screen { + font-size: 15px; + padding: 6px 10px; + background-color: #F8F8F8; + border: 1px solid #CCCCCC; + border-radius: 3px 3px 3px 3px; + clear: both; + overflow: auto; + line-height: 1.4; + font-family: Consolas, "Liberation Mono", Courier, monospace; +} + +table { + border-collapse: collapse; + border-spacing: 0; + border: 1px solid #DDDDDD !important; + border-radius: 4px !important; + border-collapse: separate !important; + line-height: 1.6; +} + +table thead { + background: #F5F5F5; +} + +table tr { + border: none; + border-bottom: none; +} + +table th { + font-weight: bold; +} + +table th,table td { + border: none !important; + padding: 6px 13px; +} + +table tr:nth-child(2n) { + background-color: #F8F8F8; +} + +td p { + margin: 0 0 15px 0; +} + +div.table-contents td p { + margin: 0; +} + +div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist * + { + border: none !important; + background: none !important; + margin: 0; +} + +div.important p,div.note p,div.tip p,div.warning p { + color: #6F6F6F; + line-height: 1.6; +} + +div.important code,div.note code,div.tip code,div.warning code { + background-color: #F2F2F2 !important; + border: 1px solid #CCCCCC !important; + border-radius: 4px !important; + padding: 1px 3px 0 !important; + text-shadow: none !important; + white-space: nowrap !important; +} + +.note th,.tip th,.warning th { + display: none; +} + +.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td + { + border-right: 1px solid #CCCCCC !important; + padding-top: 10px; +} + +div.calloutlist p,div.calloutlist td { + padding: 0; + margin: 0; +} + +div.calloutlist>table>tbody>tr>td:first-child { + padding-left: 10px; + width: 30px !important; +} + +div.important,div.note,div.tip,div.warning { + margin-left: 0px !important; + margin-right: 20px !important; + margin-top: 20px; + margin-bottom: 20px; + padding-top: 10px; + padding-bottom: 10px; +} + +div.toc { + line-height: 1.2; +} + +dl,dt { + margin-top: 1px; + margin-bottom: 0; +} + +div.toc>dl>dt { + font-size: 32px; + font-weight: bold; + margin: 30px 0 10px 0; + display: block; +} + +div.toc>dl>dd>dl>dt { + font-size: 24px; + font-weight: bold; + margin: 20px 0 10px 0; + display: block; +} + +div.toc>dl>dd>dl>dd>dl>dt { + font-weight: bold; + font-size: 20px; + margin: 10px 0 0 0; +} + +tbody.footnotes * { + border: none !important; +} + +div.footnote p { + margin: 0; + line-height: 1; +} + +div.footnote p sup { + margin-right: 6px; + vertical-align: middle; +} + +div.navheader { + border-bottom: 1px solid #CCCCCC; +} + +div.navfooter { + border-top: 1px solid #CCCCCC; +} + +.title { + margin-left: -1em; + padding-left: 1em; +} + +.title>a { + position: absolute; + visibility: hidden; + display: block; + font-size: 0.85em; + margin-top: 0.05em; + margin-left: -1em; + vertical-align: text-top; + color: black; +} + +.title>a:before { + content: "\00A7"; +} + +.title:hover>a,.title>a:hover,.title:hover>a:hover { + visibility: visible; +} + +.title:focus>a,.title>a:focus,.title:focus>a:focus { + outline: 0; +} diff --git a/spring-cloud-bus/2.1.0.RC3/ghpages.sh b/spring-cloud-bus/2.1.0.RC3/ghpages.sh new file mode 100644 index 00000000..57c5da3a --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/ghpages.sh @@ -0,0 +1,330 @@ +#!/bin/bash -x + +set -e + +# Set default props like MAVEN_PATH, ROOT_FOLDER etc. +function set_default_props() { + # The script should be executed from the root folder + ROOT_FOLDER=`pwd` + echo "Current folder is ${ROOT_FOLDER}" + + if [[ ! -e "${ROOT_FOLDER}/.git" ]]; then + echo "You're not in the root folder of the project!" + exit 1 + fi + + # Prop that will let commit the changes + COMMIT_CHANGES="no" + MAVEN_PATH=${MAVEN_PATH:-} + echo "Path to Maven is [${MAVEN_PATH}]" + REPO_NAME=${PWD##*/} + echo "Repo name is [${REPO_NAME}]" + SPRING_CLOUD_STATIC_REPO=${SPRING_CLOUD_STATIC_REPO:-git@github.com:spring-cloud/spring-cloud-static.git} + echo "Spring Cloud Static repo is [${SPRING_CLOUD_STATIC_REPO}" +} + +# Check if gh-pages exists and docs have been built +function check_if_anything_to_sync() { + git remote set-url --push origin `git config remote.origin.url | sed -e 's/^git:/https:/'` + + if ! (git remote set-branches --add origin gh-pages && git fetch -q); then + echo "No gh-pages, so not syncing" + exit 0 + fi + + if ! [ -d docs/target/generated-docs ] && ! [ "${BUILD}" == "yes" ]; then + echo "No gh-pages sources in docs/target/generated-docs, so not syncing" + exit 0 + fi +} + +function retrieve_current_branch() { + # Code getting the name of the current branch. For master we want to publish as we did until now + # http://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch + # If there is a branch already passed will reuse it - otherwise will try to find it + CURRENT_BRANCH=${BRANCH} + if [[ -z "${CURRENT_BRANCH}" ]] ; then + CURRENT_BRANCH=$(git symbolic-ref -q HEAD) + CURRENT_BRANCH=${CURRENT_BRANCH##refs/heads/} + CURRENT_BRANCH=${CURRENT_BRANCH:-HEAD} + fi + echo "Current branch is [${CURRENT_BRANCH}]" + git checkout ${CURRENT_BRANCH} || echo "Failed to check the branch... continuing with the script" +} + +# Switches to the provided value of the release version. We always prefix it with `v` +function switch_to_tag() { + git checkout v${VERSION} +} + +# Build the docs if switch is on +function build_docs_if_applicable() { + if [[ "${BUILD}" == "yes" ]] ; then + ./mvnw clean install -P docs -pl docs -DskipTests + fi +} + +# Get the name of the `docs.main` property +# Get whitelisted branches - assumes that a `docs` module is available under `docs` profile +function retrieve_doc_properties() { + MAIN_ADOC_VALUE=$("${MAVEN_PATH}"mvn -q \ + -Dexec.executable="echo" \ + -Dexec.args='${docs.main}' \ + --non-recursive \ + org.codehaus.mojo:exec-maven-plugin:1.3.1:exec) + echo "Extracted 'main.adoc' from Maven build [${MAIN_ADOC_VALUE}]" + + + WHITELIST_PROPERTY=${WHITELIST_PROPERTY:-"docs.whitelisted.branches"} + WHITELISTED_BRANCHES_VALUE=$("${MAVEN_PATH}"mvn -q \ + -Dexec.executable="echo" \ + -Dexec.args="\${${WHITELIST_PROPERTY}}" \ + org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \ + -P docs \ + -pl docs) + echo "Extracted '${WHITELIST_PROPERTY}' from Maven build [${WHITELISTED_BRANCHES_VALUE}]" +} + +# Stash any outstanding changes +function stash_changes() { + git diff-index --quiet HEAD && dirty=$? || (echo "Failed to check if the current repo is dirty. Assuming that it is." && dirty="1") + if [ "$dirty" != "0" ]; then git stash; fi +} + +# Switch to gh-pages branch to sync it with current branch +function add_docs_from_target() { + local DESTINATION_REPO_FOLDER + if [[ -z "${DESTINATION}" && -z "${CLONE}" ]] ; then + DESTINATION_REPO_FOLDER=${ROOT_FOLDER} + elif [[ "${CLONE}" == "yes" ]]; then + mkdir -p ${ROOT_FOLDER}/target + local clonedStatic=${ROOT_FOLDER}/target/spring-cloud-static + if [[ ! -e "${clonedStatic}/.git" ]]; then + echo "Cloning Spring Cloud Static to target" + git clone ${SPRING_CLOUD_STATIC_REPO} ${clonedStatic} && git checkout gh-pages + else + echo "Spring Cloud Static already cloned - will pull changes" + cd ${clonedStatic} && git checkout gh-pages && git pull origin gh-pages + fi + DESTINATION_REPO_FOLDER=${clonedStatic}/${REPO_NAME} + mkdir -p ${DESTINATION_REPO_FOLDER} + else + if [[ ! -e "${DESTINATION}/.git" ]]; then + echo "[${DESTINATION}] is not a git repository" + exit 1 + fi + DESTINATION_REPO_FOLDER=${DESTINATION}/${REPO_NAME} + mkdir -p ${DESTINATION_REPO_FOLDER} + echo "Destination was provided [${DESTINATION}]" + fi + cd ${DESTINATION_REPO_FOLDER} + git checkout gh-pages + git pull origin gh-pages + + # Add git branches + ################################################################### + if [[ -z "${VERSION}" ]] ; then + copy_docs_for_current_version + else + copy_docs_for_provided_version + fi + commit_changes_if_applicable +} + + +# Copies the docs by using the retrieved properties from Maven build +function copy_docs_for_current_version() { + if [[ "${CURRENT_BRANCH}" == "master" ]] ; then + echo -e "Current branch is master - will copy the current docs only to the root folder" + for f in docs/target/generated-docs/*; do + file=${f#docs/target/generated-docs/*} + if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then + # Not ignored... + cp -rf $f ${ROOT_FOLDER}/ + git add -A ${ROOT_FOLDER}/$file + fi + done + COMMIT_CHANGES="yes" + else + echo -e "Current branch is [${CURRENT_BRANCH}]" + # http://stackoverflow.com/questions/29300806/a-bash-script-to-check-if-a-string-is-present-in-a-comma-separated-list-of-strin + if [[ ",${WHITELISTED_BRANCHES_VALUE}," = *",${CURRENT_BRANCH},"* ]] ; then + mkdir -p ${ROOT_FOLDER}/${CURRENT_BRANCH} + echo -e "Branch [${CURRENT_BRANCH}] is whitelisted! Will copy the current docs to the [${CURRENT_BRANCH}] folder" + for f in docs/target/generated-docs/*; do + file=${f#docs/target/generated-docs/*} + if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then + # Not ignored... + # We want users to access 1.0.0.RELEASE/ instead of 1.0.0.RELEASE/spring-cloud.sleuth.html + if [[ "${file}" == "${MAIN_ADOC_VALUE}.html" ]] ; then + # We don't want to copy the spring-cloud-sleuth.html + # we want it to be converted to index.html + cp -rf $f ${ROOT_FOLDER}/${CURRENT_BRANCH}/index.html + git add -A ${ROOT_FOLDER}/${CURRENT_BRANCH}/index.html + else + cp -rf $f ${ROOT_FOLDER}/${CURRENT_BRANCH} + git add -A ${ROOT_FOLDER}/${CURRENT_BRANCH}/$file + fi + fi + done + COMMIT_CHANGES="yes" + else + echo -e "Branch [${CURRENT_BRANCH}] is not on the white list! Check out the Maven [${WHITELIST_PROPERTY}] property in + [docs] module available under [docs] profile. Won't commit any changes to gh-pages for this branch." + fi + fi +} + +# Copies the docs by using the explicitly provided version +function copy_docs_for_provided_version() { + local FOLDER=${DESTINATION_REPO_FOLDER}/${VERSION} + mkdir -p ${FOLDER} + echo -e "Current tag is [v${VERSION}] Will copy the current docs to the [${FOLDER}] folder" + for f in ${ROOT_FOLDER}/docs/target/generated-docs/*; do + file=${f#${ROOT_FOLDER}/docs/target/generated-docs/*} + copy_docs_for_branch ${file} ${FOLDER} + done + COMMIT_CHANGES="yes" + CURRENT_BRANCH="v${VERSION}" +} + +# Copies the docs from target to the provided destination +# Params: +# $1 - file from target +# $2 - destination to which copy the files +function copy_docs_for_branch() { + local file=$1 + local destination=$2 + if ! git ls-files -i -o --exclude-standard --directory | grep -q ^${file}$; then + # Not ignored... + # We want users to access 1.0.0.RELEASE/ instead of 1.0.0.RELEASE/spring-cloud.sleuth.html + if [[ ("${file}" == "${MAIN_ADOC_VALUE}.html") || ("${file}" == "${REPO_NAME}.html") ]] ; then + # We don't want to copy the spring-cloud-sleuth.html + # we want it to be converted to index.html + cp -rf $f ${destination}/index.html + git add -A ${destination}/index.html + else + cp -rf $f ${destination} + git add -A ${destination}/$file + fi + fi +} + +function commit_changes_if_applicable() { + if [[ "${COMMIT_CHANGES}" == "yes" ]] ; then + COMMIT_SUCCESSFUL="no" + git commit -a -m "Sync docs from ${CURRENT_BRANCH} to gh-pages" && COMMIT_SUCCESSFUL="yes" || echo "Failed to commit changes" + + # Uncomment the following push if you want to auto push to + # the gh-pages branch whenever you commit to master locally. + # This is a little extreme. Use with care! + ################################################################### + if [[ "${COMMIT_SUCCESSFUL}" == "yes" ]] ; then + git push origin gh-pages + fi + fi +} + +# Switch back to the previous branch and exit block +function checkout_previous_branch() { + # If -version was provided we need to come back to root project + cd ${ROOT_FOLDER} + git checkout ${CURRENT_BRANCH} || echo "Failed to check the branch... continuing with the script" + if [ "$dirty" != "0" ]; then git stash pop; fi + exit 0 +} + +# Assert if properties have been properly passed +function assert_properties() { +echo "VERSION [${VERSION}], DESTINATION [${DESTINATION}], CLONE [${CLONE}]" +if [[ "${VERSION}" != "" && (-z "${DESTINATION}" && -z "${CLONE}") ]] ; then echo "Version was set but destination / clone was not!"; exit 1;fi +if [[ ("${DESTINATION}" != "" && "${CLONE}" != "") && -z "${VERSION}" ]] ; then echo "Destination / clone was set but version was not!"; exit 1;fi +if [[ "${DESTINATION}" != "" && "${CLONE}" == "yes" ]] ; then echo "Destination and clone was set. Pick one!"; exit 1;fi +} + +# Prints the usage +function print_usage() { +cat </` +- if the destination switch is passed (-d) then the script will check if the provided dir is a git repo and then will + switch to gh-pages of that repo and copy the generated docs to `docs//` + +USAGE: + +You can use the following options: + +-v|--version - the script will apply the whole procedure for a particular library version +-d|--destination - the root of destination folder where the docs should be copied. You have to use the full path. + E.g. point to spring-cloud-static folder. Can't be used with (-c) +-b|--build - will run the standard build process after checking out the branch +-c|--clone - will automatically clone the spring-cloud-static repo instead of providing the destination. + Obviously can't be used with (-d) + +EOF +} + + +# ========================================== +# ____ ____ _____ _____ _____ _______ +# / ____|/ ____| __ \|_ _| __ \__ __| +# | (___ | | | |__) | | | | |__) | | | +# \___ \| | | _ / | | | ___/ | | +# ____) | |____| | \ \ _| |_| | | | +# |_____/ \_____|_| \_\_____|_| |_| +# +# ========================================== + +while [[ $# > 0 ]] +do +key="$1" +case ${key} in + -v|--version) + VERSION="$2" + shift # past argument + ;; + -d|--destination) + DESTINATION="$2" + shift # past argument + ;; + -b|--build) + BUILD="yes" + ;; + -c|--clone) + CLONE="yes" + ;; + -h|--help) + print_usage + exit 0 + ;; + *) + echo "Invalid option: [$1]" + print_usage + exit 1 + ;; +esac +shift # past argument or value +done + +assert_properties +set_default_props +check_if_anything_to_sync +if [[ -z "${VERSION}" ]] ; then + retrieve_current_branch +else + switch_to_tag +fi +build_docs_if_applicable +retrieve_doc_properties +stash_changes +add_docs_from_target +checkout_previous_branch \ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/images/background.png b/spring-cloud-bus/2.1.0.RC3/images/background.png new file mode 100644 index 00000000..15dca6fb Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/images/background.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/images/callouts/1.png b/spring-cloud-bus/2.1.0.RC3/images/callouts/1.png new file mode 100644 index 00000000..7d473430 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/images/callouts/1.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/images/callouts/2.png b/spring-cloud-bus/2.1.0.RC3/images/callouts/2.png new file mode 100644 index 00000000..5d09341b Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/images/callouts/2.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/images/callouts/3.png b/spring-cloud-bus/2.1.0.RC3/images/callouts/3.png new file mode 100644 index 00000000..ef7b7004 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/images/callouts/3.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/images/caution.png b/spring-cloud-bus/2.1.0.RC3/images/caution.png new file mode 100644 index 00000000..8a5e4fca Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/images/caution.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/images/important.png b/spring-cloud-bus/2.1.0.RC3/images/important.png new file mode 100644 index 00000000..ec54df65 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/images/important.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/images/logo.png b/spring-cloud-bus/2.1.0.RC3/images/logo.png new file mode 100644 index 00000000..ade2ce6e Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/images/logo.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/images/note.png b/spring-cloud-bus/2.1.0.RC3/images/note.png new file mode 100644 index 00000000..88d997b1 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/images/note.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/images/tip.png b/spring-cloud-bus/2.1.0.RC3/images/tip.png new file mode 100644 index 00000000..6530abb4 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/images/tip.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/images/warning.png b/spring-cloud-bus/2.1.0.RC3/images/warning.png new file mode 100644 index 00000000..0d5b5244 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/images/warning.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/index.html b/spring-cloud-bus/2.1.0.RC3/index.html new file mode 100644 index 00000000..f39b1595 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/index.html @@ -0,0 +1,117 @@ + + + + + + + +spring-cloud-bus + + + + + + + + +
+
+
+
+

2.1.0.RC3

+
+
+
+
+

Pick The Documentation Option

+
+
+ +
+
+
+
+ + + + + \ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/multi/css/highlight.css b/spring-cloud-bus/2.1.0.RC3/multi/css/highlight.css new file mode 100644 index 00000000..ffefef72 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/multi/css/highlight.css @@ -0,0 +1,35 @@ +/* + code highlight CSS resemblign the Eclipse IDE default color schema + @author Costin Leau +*/ + +.hl-keyword { + color: #7F0055; + font-weight: bold; +} + +.hl-comment { + color: #3F5F5F; + font-style: italic; +} + +.hl-multiline-comment { + color: #3F5FBF; + font-style: italic; +} + +.hl-tag { + color: #3F7F7F; +} + +.hl-attribute { + color: #7F007F; +} + +.hl-value { + color: #2A00FF; +} + +.hl-string { + color: #2A00FF; +} \ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/multi/css/manual-multipage.css b/spring-cloud-bus/2.1.0.RC3/multi/css/manual-multipage.css new file mode 100644 index 00000000..0c484531 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/multi/css/manual-multipage.css @@ -0,0 +1,9 @@ +@IMPORT url("manual.css"); + +body.firstpage { + background: url("../images/background.png") no-repeat center top; +} + +div.part h1 { + border-top: none; +} diff --git a/spring-cloud-bus/2.1.0.RC3/multi/css/manual-singlepage.css b/spring-cloud-bus/2.1.0.RC3/multi/css/manual-singlepage.css new file mode 100644 index 00000000..4a7fd140 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/multi/css/manual-singlepage.css @@ -0,0 +1,6 @@ +@IMPORT url("manual.css"); + +body { + background: url("../images/background.png") no-repeat center top; +} + diff --git a/spring-cloud-bus/2.1.0.RC3/multi/css/manual.css b/spring-cloud-bus/2.1.0.RC3/multi/css/manual.css new file mode 100644 index 00000000..0ecbe2e8 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/multi/css/manual.css @@ -0,0 +1,344 @@ +@IMPORT url("highlight.css"); + +html { + padding: 0pt; + margin: 0pt; +} + +body { + color: #333333; + margin: 15px 30px; + font-family: Helvetica, Arial, Freesans, Clean, Sans-serif; + line-height: 1.6; + -webkit-font-smoothing: antialiased; +} + +code { + font-size: 16px; + font-family: Consolas, "Liberation Mono", Courier, monospace; +} + +:not(a)>code { + color: #6D180B; +} + +:not(pre)>code { + background-color: #F2F2F2; + border: 1px solid #CCCCCC; + border-radius: 4px; + padding: 1px 3px 0; + text-shadow: none; + white-space: nowrap; +} + +body>*:first-child { + margin-top: 0 !important; +} + +div { + margin: 0pt; +} + +hr { + border: 1px solid #CCCCCC; + background: #CCCCCC; +} + +h1,h2,h3,h4,h5,h6 { + color: #000000; + cursor: text; + font-weight: bold; + margin: 30px 0 10px; + padding: 0; +} + +h1,h2,h3 { + margin: 40px 0 10px; +} + +h1 { + margin: 70px 0 30px; + padding-top: 20px; +} + +div.part h1 { + border-top: 1px dotted #CCCCCC; +} + +h1,h1 code { + font-size: 32px; +} + +h2,h2 code { + font-size: 24px; +} + +h3,h3 code { + font-size: 20px; +} + +h4,h1 code,h5,h5 code,h6,h6 code { + font-size: 18px; +} + +div.book,div.chapter,div.appendix,div.part,div.preface { + min-width: 300px; + max-width: 1200px; + margin: 0 auto; +} + +p.releaseinfo { + font-weight: bold; + margin-bottom: 40px; + margin-top: 40px; +} + +div.authorgroup { + line-height: 1; +} + +p.copyright { + line-height: 1; + margin-bottom: -5px; +} + +.legalnotice p { + font-style: italic; + font-size: 14px; + line-height: 1; +} + +div.titlepage+p,div.titlepage+p { + margin-top: 0; +} + +pre { + line-height: 1.0; + color: black; +} + +a { + color: #4183C4; + text-decoration: none; +} + +p { + margin: 15px 0; + text-align: left; +} + +ul,ol { + padding-left: 30px; +} + +li p { + margin: 0; +} + +div.table { + margin: 1em; + padding: 0.5em; + text-align: center; +} + +div.table table,div.informaltable table { + display: table; + width: 100%; +} + +div.table td { + padding-left: 7px; + padding-right: 7px; +} + +.sidebar { + line-height: 1.4; + padding: 0 20px; + background-color: #F8F8F8; + border: 1px solid #CCCCCC; + border-radius: 3px 3px 3px 3px; +} + +.sidebar p.title { + color: #6D180B; +} + +pre.programlisting,pre.screen { + font-size: 15px; + padding: 6px 10px; + background-color: #F8F8F8; + border: 1px solid #CCCCCC; + border-radius: 3px 3px 3px 3px; + clear: both; + overflow: auto; + line-height: 1.4; + font-family: Consolas, "Liberation Mono", Courier, monospace; +} + +table { + border-collapse: collapse; + border-spacing: 0; + border: 1px solid #DDDDDD !important; + border-radius: 4px !important; + border-collapse: separate !important; + line-height: 1.6; +} + +table thead { + background: #F5F5F5; +} + +table tr { + border: none; + border-bottom: none; +} + +table th { + font-weight: bold; +} + +table th,table td { + border: none !important; + padding: 6px 13px; +} + +table tr:nth-child(2n) { + background-color: #F8F8F8; +} + +td p { + margin: 0 0 15px 0; +} + +div.table-contents td p { + margin: 0; +} + +div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist * + { + border: none !important; + background: none !important; + margin: 0; +} + +div.important p,div.note p,div.tip p,div.warning p { + color: #6F6F6F; + line-height: 1.6; +} + +div.important code,div.note code,div.tip code,div.warning code { + background-color: #F2F2F2 !important; + border: 1px solid #CCCCCC !important; + border-radius: 4px !important; + padding: 1px 3px 0 !important; + text-shadow: none !important; + white-space: nowrap !important; +} + +.note th,.tip th,.warning th { + display: none; +} + +.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td + { + border-right: 1px solid #CCCCCC !important; + padding-top: 10px; +} + +div.calloutlist p,div.calloutlist td { + padding: 0; + margin: 0; +} + +div.calloutlist>table>tbody>tr>td:first-child { + padding-left: 10px; + width: 30px !important; +} + +div.important,div.note,div.tip,div.warning { + margin-left: 0px !important; + margin-right: 20px !important; + margin-top: 20px; + margin-bottom: 20px; + padding-top: 10px; + padding-bottom: 10px; +} + +div.toc { + line-height: 1.2; +} + +dl,dt { + margin-top: 1px; + margin-bottom: 0; +} + +div.toc>dl>dt { + font-size: 32px; + font-weight: bold; + margin: 30px 0 10px 0; + display: block; +} + +div.toc>dl>dd>dl>dt { + font-size: 24px; + font-weight: bold; + margin: 20px 0 10px 0; + display: block; +} + +div.toc>dl>dd>dl>dd>dl>dt { + font-weight: bold; + font-size: 20px; + margin: 10px 0 0 0; +} + +tbody.footnotes * { + border: none !important; +} + +div.footnote p { + margin: 0; + line-height: 1; +} + +div.footnote p sup { + margin-right: 6px; + vertical-align: middle; +} + +div.navheader { + border-bottom: 1px solid #CCCCCC; +} + +div.navfooter { + border-top: 1px solid #CCCCCC; +} + +.title { + margin-left: -1em; + padding-left: 1em; +} + +.title>a { + position: absolute; + visibility: hidden; + display: block; + font-size: 0.85em; + margin-top: 0.05em; + margin-left: -1em; + vertical-align: text-top; + color: black; +} + +.title>a:before { + content: "\00A7"; +} + +.title:hover>a,.title>a:hover,.title:hover>a:hover { + visibility: visible; +} + +.title:focus>a,.title>a:focus,.title:focus>a:focus { + outline: 0; +} diff --git a/spring-cloud-bus/2.1.0.RC3/multi/images/background.png b/spring-cloud-bus/2.1.0.RC3/multi/images/background.png new file mode 100644 index 00000000..15dca6fb Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/multi/images/background.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/multi/images/callouts/1.png b/spring-cloud-bus/2.1.0.RC3/multi/images/callouts/1.png new file mode 100644 index 00000000..7d473430 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/multi/images/callouts/1.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/multi/images/callouts/2.png b/spring-cloud-bus/2.1.0.RC3/multi/images/callouts/2.png new file mode 100644 index 00000000..5d09341b Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/multi/images/callouts/2.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/multi/images/callouts/3.png b/spring-cloud-bus/2.1.0.RC3/multi/images/callouts/3.png new file mode 100644 index 00000000..ef7b7004 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/multi/images/callouts/3.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/multi/images/caution.png b/spring-cloud-bus/2.1.0.RC3/multi/images/caution.png new file mode 100644 index 00000000..8a5e4fca Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/multi/images/caution.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/multi/images/important.png b/spring-cloud-bus/2.1.0.RC3/multi/images/important.png new file mode 100644 index 00000000..ec54df65 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/multi/images/important.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/multi/images/logo.png b/spring-cloud-bus/2.1.0.RC3/multi/images/logo.png new file mode 100644 index 00000000..ade2ce6e Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/multi/images/logo.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/multi/images/note.png b/spring-cloud-bus/2.1.0.RC3/multi/images/note.png new file mode 100644 index 00000000..88d997b1 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/multi/images/note.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/multi/images/tip.png b/spring-cloud-bus/2.1.0.RC3/multi/images/tip.png new file mode 100644 index 00000000..6530abb4 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/multi/images/tip.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/multi/images/warning.png b/spring-cloud-bus/2.1.0.RC3/multi/images/warning.png new file mode 100644 index 00000000..0d5b5244 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/multi/images/warning.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/multi/multi__addressing_all_instances_of_a_service.html b/spring-cloud-bus/2.1.0.RC3/multi/multi__addressing_all_instances_of_a_service.html new file mode 100644 index 00000000..63ba8424 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/multi/multi__addressing_all_instances_of_a_service.html @@ -0,0 +1,6 @@ + + + 4. Addressing All Instances of a Service

4. Addressing All Instances of a Service

The destination parameter is used in a Spring PathMatcher (with the path separator +as a colon — :) to determine if an instance processes the message. Using the example +from earlier, /bus-env/customers:** targets all instances of the +customers service regardless of the rest of the service ID.

\ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/multi/multi__addressing_an_instance.html b/spring-cloud-bus/2.1.0.RC3/multi/multi__addressing_an_instance.html new file mode 100644 index 00000000..5dfa9fe0 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/multi/multi__addressing_an_instance.html @@ -0,0 +1,12 @@ + + + 3. Addressing an Instance

3. Addressing an Instance

Each instance of the application has a service ID, whose value can be set with +spring.cloud.bus.id and whose value is expected to be a colon-separated list of +identifiers, in order from least specific to most specific. The default value is +constructed from the environment as a combination of the spring.application.name and +server.port (or spring.application.index, if set). The default value of the ID is +constructed in the form of app:index:id, where:

  • app is the vcap.application.name, if it exists, or spring.application.name
  • index is the vcap.application.instance_index, if it exists, +spring.application.index, local.server.port, server.port, or 0 (in that order).
  • id is the vcap.application.instance_id, if it exists, or a random value.

The HTTP endpoints accept a destination path parameter, such as +/bus-refresh/customers:9000, where destination is a service ID. If the ID +is owned by an instance on the bus, it processes the message, and all other instances +ignore it.

\ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/multi/multi__broadcasting_your_own_events.html b/spring-cloud-bus/2.1.0.RC3/multi/multi__broadcasting_your_own_events.html new file mode 100644 index 00000000..ce1eb982 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/multi/multi__broadcasting_your_own_events.html @@ -0,0 +1,34 @@ + + + 8. Broadcasting Your Own Events

8. Broadcasting Your Own Events

The Bus can carry any event of type RemoteApplicationEvent. The default transport is +JSON, and the deserializer needs to know which types are going to be used ahead of time. +To register a new type, you must put it in a subpackage of +org.springframework.cloud.bus.event.

To customise the event name, you can use @JsonTypeName on your custom class or rely on +the default strategy, which is to use the simple name of the class.

[Note]Note

Both the producer and the consumer need access to the class definition.

8.1 Registering events in custom packages

If you cannot or do not want to use a subpackage of org.springframework.cloud.bus.event +for your custom events, you must specify which packages to scan for events of type +RemoteApplicationEvent by using the @RemoteApplicationEventScan annotation. Packages +specified with @RemoteApplicationEventScan include subpackages.

For example, consider the following custom event, called MyEvent:

package com.acme;
+
+public class MyEvent extends RemoteApplicationEvent {
+    ...
+}

You can register that event with the deserializer in the following way:

package com.acme;
+
+@Configuration
+@RemoteApplicationEventScan
+public class BusConfiguration {
+    ...
+}

Without specifying a value, the package of the class where @RemoteApplicationEventScan +is used is registered. In this example, com.acme is registered by using the package of +BusConfiguration.

You can also explicitly specify the packages to scan by using the value, basePackages +or basePackageClasses properties on @RemoteApplicationEventScan, as shown in the +following example:

package com.acme;
+
+@Configuration
+//@RemoteApplicationEventScan({"com.acme", "foo.bar"})
+//@RemoteApplicationEventScan(basePackages = {"com.acme", "foo.bar", "fizz.buzz"})
+@RemoteApplicationEventScan(basePackageClasses = BusConfiguration.class)
+public class BusConfiguration {
+    ...
+}

All of the preceding examples of @RemoteApplicationEventScan are equivalent, in that the +com.acme package is registered by explicitly specifying the packages on +@RemoteApplicationEventScan.

[Note]Note

You can specify multiple base packages to scan.

\ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/multi/multi__bus_endpoints.html b/spring-cloud-bus/2.1.0.RC3/multi/multi__bus_endpoints.html new file mode 100644 index 00000000..5abc1564 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/multi/multi__bus_endpoints.html @@ -0,0 +1,13 @@ + + + 2. Bus Endpoints

2. Bus Endpoints

Spring Cloud Bus provides two endpoints, /actuator/bus-refresh and /actuator/bus-env +that correspond to individual actuator endpoints in Spring Cloud Commons, +/actuator/refresh and /actuator/env respectively.

2.1 Bus Refresh Endpoint

The /actuator/bus-refresh endpoint clears the RefreshScope cache and rebinds +@ConfigurationProperties. See the Refresh Scope documentation for +more information.

To expose the /actuator/bus-refresh endpoint, you need to add following configuration to your +application:

management.endpoints.web.exposure.include=bus-refresh

2.2 Bus Env Endpoint

The /actuator/bus-env endpoint updates each instances environment with the specified +key/value pair across multiple instances.

To expose the /actuator/bus-env endpoint, you need to add following configuration to your +application:

management.endpoints.web.exposure.include=bus-env

The /actuator/bus-env endpoint accepts POST requests with the following shape:

{
+	"name": "key1",
+	"value": "value1"
+}
\ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/multi/multi__customizing_the_message_broker.html b/spring-cloud-bus/2.1.0.RC3/multi/multi__customizing_the_message_broker.html new file mode 100644 index 00000000..3abf730e --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/multi/multi__customizing_the_message_broker.html @@ -0,0 +1,13 @@ + + + 6. Customizing the Message Broker

6. Customizing the Message Broker

Spring Cloud Bus uses Spring Cloud Stream to +broadcast the messages. So, to get messages to flow, you need only include the binder +implementation of your choice in the classpath. There are convenient starters for the bus +with AMQP (RabbitMQ) and Kafka (spring-cloud-starter-bus-[amqp|kafka]). Generally +speaking, Spring Cloud Stream relies on Spring Boot autoconfiguration conventions for +configuring middleware. For instance, the AMQP broker address can be changed with +spring.rabbitmq.* configuration properties. Spring Cloud Bus has a handful of +native configuration properties in spring.cloud.bus.* (for example, +spring.cloud.bus.destination is the name of the topic to use as the external +middleware). Normally, the defaults suffice.

To learn more about how to customize the message broker settings, consult the Spring Cloud +Stream documentation.

\ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/multi/multi__quick_start.html b/spring-cloud-bus/2.1.0.RC3/multi/multi__quick_start.html new file mode 100644 index 00000000..4c79f036 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/multi/multi__quick_start.html @@ -0,0 +1,23 @@ + + + 1. Quick Start

1. Quick Start

Spring Cloud Bus works by adding Spring Boot autconfiguration if it detects itself on the +classpath. To enable the bus, add spring-cloud-starter-bus-amqp or +spring-cloud-starter-bus-kafka to your dependency management. Spring Cloud takes care of +the rest. Make sure the broker (RabbitMQ or Kafka) is available and configured. When +running on localhost, you need not do anything. If you run remotely, use Spring Cloud +Connectors or Spring Boot conventions to define the broker credentials, as shown in the +following example for Rabbit:

application.yml.  +

spring:
+  rabbitmq:
+    host: mybroker.com
+    port: 5672
+    username: user
+    password: secret

+

The bus currently supports sending messages to all nodes listening or all nodes for a +particular service (as defined by Eureka). The /bus/* actuator namespace has some HTTP +endpoints. Currently, two are implemented. The first, /bus/env, sends key/value pairs to +update each node’s Spring Environment. The second, /bus/refresh, reloads each +application’s configuration, as though they had all been pinged on their /refresh +endpoint.

[Note]Note

The Spring Cloud Bus starters cover Rabbit and Kafka, because those are the two most +common implementations. However, Spring Cloud Stream is quite flexible, and the binder +works with spring-cloud-bus.

\ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/multi/multi__service_id_must_be_unique.html b/spring-cloud-bus/2.1.0.RC3/multi/multi__service_id_must_be_unique.html new file mode 100644 index 00000000..7cc955e5 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/multi/multi__service_id_must_be_unique.html @@ -0,0 +1,9 @@ + + + 5. Service ID Must Be Unique

5. Service ID Must Be Unique

The bus tries twice to eliminate processing an event — once from the original +ApplicationEvent and once from the queue. To do so, it checks the sending service ID +against the current service ID. If multiple instances of a service have the same ID, +events are not processed. When running on a local machine, each service is on a different +port, and that port is part of the ID. Cloud Foundry supplies an index to differentiate. +To ensure that the ID is unique outside Cloud Foundry, set spring.application.index to +something unique for each instance of a service.

\ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/multi/multi__tracing_bus_events.html b/spring-cloud-bus/2.1.0.RC3/multi/multi__tracing_bus_events.html new file mode 100644 index 00000000..6a0d5e87 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/multi/multi__tracing_bus_events.html @@ -0,0 +1,42 @@ + + + 7. Tracing Bus Events

7. Tracing Bus Events

Bus events (subclasses of RemoteApplicationEvent) can be traced by setting +spring.cloud.bus.trace.enabled=true. If you do so, the Spring Boot TraceRepository +(if it is present) shows each event sent and all the acks from each service instance. The +following example comes from the /trace endpoint:

{
+  "timestamp": "2015-11-26T10:24:44.411+0000",
+  "info": {
+    "signal": "spring.cloud.bus.ack",
+    "type": "RefreshRemoteApplicationEvent",
+    "id": "c4d374b7-58ea-4928-a312-31984def293b",
+    "origin": "stores:8081",
+    "destination": "*:**"
+  }
+  },
+  {
+  "timestamp": "2015-11-26T10:24:41.864+0000",
+  "info": {
+    "signal": "spring.cloud.bus.sent",
+    "type": "RefreshRemoteApplicationEvent",
+    "id": "c4d374b7-58ea-4928-a312-31984def293b",
+    "origin": "customers:9000",
+    "destination": "*:**"
+  }
+  },
+  {
+  "timestamp": "2015-11-26T10:24:41.862+0000",
+  "info": {
+    "signal": "spring.cloud.bus.ack",
+    "type": "RefreshRemoteApplicationEvent",
+    "id": "c4d374b7-58ea-4928-a312-31984def293b",
+    "origin": "customers:9000",
+    "destination": "*:**"
+  }
+}

The preceding trace shows that a RefreshRemoteApplicationEvent was sent from +customers:9000, broadcast to all services, and received (acked) by customers:9000 and +stores:8081.

To handle the ack signals yourself, you could add an @EventListener for the +AckRemoteApplicationEvent and SentApplicationEvent types to your app (and enable +tracing). Alternatively, you could tap into the TraceRepository and mine the data from +there.

[Note]Note

Any Bus application can trace acks. However, sometimes, it is +useful to do this in a central service that can do more complex +queries on the data or forward it to a specialized tracing service.

\ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/multi/multi_pr01.html b/spring-cloud-bus/2.1.0.RC3/multi/multi_pr01.html new file mode 100644 index 00000000..97d81984 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/multi/multi_pr01.html @@ -0,0 +1,8 @@ + + +

Spring Cloud Bus links the nodes of a distributed system with a lightweight message +broker. This broker can then be used to broadcast state changes (such as configuration +changes) or other management instructions. A key idea is that the bus is like a +distributed actuator for a Spring Boot application that is scaled out. However, it can +also be used as a communication channel between apps. This project provides starters for +either an AMQP broker or Kafka as the transport.

[Note]Note

Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at github.

\ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/multi/multi_spring-cloud-bus.html b/spring-cloud-bus/2.1.0.RC3/multi/multi_spring-cloud-bus.html new file mode 100644 index 00000000..888f42d5 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/multi/multi_spring-cloud-bus.html @@ -0,0 +1,3 @@ + + + Spring Cloud Bus \ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/single/css/highlight.css b/spring-cloud-bus/2.1.0.RC3/single/css/highlight.css new file mode 100644 index 00000000..ffefef72 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/single/css/highlight.css @@ -0,0 +1,35 @@ +/* + code highlight CSS resemblign the Eclipse IDE default color schema + @author Costin Leau +*/ + +.hl-keyword { + color: #7F0055; + font-weight: bold; +} + +.hl-comment { + color: #3F5F5F; + font-style: italic; +} + +.hl-multiline-comment { + color: #3F5FBF; + font-style: italic; +} + +.hl-tag { + color: #3F7F7F; +} + +.hl-attribute { + color: #7F007F; +} + +.hl-value { + color: #2A00FF; +} + +.hl-string { + color: #2A00FF; +} \ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/single/css/manual-multipage.css b/spring-cloud-bus/2.1.0.RC3/single/css/manual-multipage.css new file mode 100644 index 00000000..0c484531 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/single/css/manual-multipage.css @@ -0,0 +1,9 @@ +@IMPORT url("manual.css"); + +body.firstpage { + background: url("../images/background.png") no-repeat center top; +} + +div.part h1 { + border-top: none; +} diff --git a/spring-cloud-bus/2.1.0.RC3/single/css/manual-singlepage.css b/spring-cloud-bus/2.1.0.RC3/single/css/manual-singlepage.css new file mode 100644 index 00000000..4a7fd140 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/single/css/manual-singlepage.css @@ -0,0 +1,6 @@ +@IMPORT url("manual.css"); + +body { + background: url("../images/background.png") no-repeat center top; +} + diff --git a/spring-cloud-bus/2.1.0.RC3/single/css/manual.css b/spring-cloud-bus/2.1.0.RC3/single/css/manual.css new file mode 100644 index 00000000..0ecbe2e8 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/single/css/manual.css @@ -0,0 +1,344 @@ +@IMPORT url("highlight.css"); + +html { + padding: 0pt; + margin: 0pt; +} + +body { + color: #333333; + margin: 15px 30px; + font-family: Helvetica, Arial, Freesans, Clean, Sans-serif; + line-height: 1.6; + -webkit-font-smoothing: antialiased; +} + +code { + font-size: 16px; + font-family: Consolas, "Liberation Mono", Courier, monospace; +} + +:not(a)>code { + color: #6D180B; +} + +:not(pre)>code { + background-color: #F2F2F2; + border: 1px solid #CCCCCC; + border-radius: 4px; + padding: 1px 3px 0; + text-shadow: none; + white-space: nowrap; +} + +body>*:first-child { + margin-top: 0 !important; +} + +div { + margin: 0pt; +} + +hr { + border: 1px solid #CCCCCC; + background: #CCCCCC; +} + +h1,h2,h3,h4,h5,h6 { + color: #000000; + cursor: text; + font-weight: bold; + margin: 30px 0 10px; + padding: 0; +} + +h1,h2,h3 { + margin: 40px 0 10px; +} + +h1 { + margin: 70px 0 30px; + padding-top: 20px; +} + +div.part h1 { + border-top: 1px dotted #CCCCCC; +} + +h1,h1 code { + font-size: 32px; +} + +h2,h2 code { + font-size: 24px; +} + +h3,h3 code { + font-size: 20px; +} + +h4,h1 code,h5,h5 code,h6,h6 code { + font-size: 18px; +} + +div.book,div.chapter,div.appendix,div.part,div.preface { + min-width: 300px; + max-width: 1200px; + margin: 0 auto; +} + +p.releaseinfo { + font-weight: bold; + margin-bottom: 40px; + margin-top: 40px; +} + +div.authorgroup { + line-height: 1; +} + +p.copyright { + line-height: 1; + margin-bottom: -5px; +} + +.legalnotice p { + font-style: italic; + font-size: 14px; + line-height: 1; +} + +div.titlepage+p,div.titlepage+p { + margin-top: 0; +} + +pre { + line-height: 1.0; + color: black; +} + +a { + color: #4183C4; + text-decoration: none; +} + +p { + margin: 15px 0; + text-align: left; +} + +ul,ol { + padding-left: 30px; +} + +li p { + margin: 0; +} + +div.table { + margin: 1em; + padding: 0.5em; + text-align: center; +} + +div.table table,div.informaltable table { + display: table; + width: 100%; +} + +div.table td { + padding-left: 7px; + padding-right: 7px; +} + +.sidebar { + line-height: 1.4; + padding: 0 20px; + background-color: #F8F8F8; + border: 1px solid #CCCCCC; + border-radius: 3px 3px 3px 3px; +} + +.sidebar p.title { + color: #6D180B; +} + +pre.programlisting,pre.screen { + font-size: 15px; + padding: 6px 10px; + background-color: #F8F8F8; + border: 1px solid #CCCCCC; + border-radius: 3px 3px 3px 3px; + clear: both; + overflow: auto; + line-height: 1.4; + font-family: Consolas, "Liberation Mono", Courier, monospace; +} + +table { + border-collapse: collapse; + border-spacing: 0; + border: 1px solid #DDDDDD !important; + border-radius: 4px !important; + border-collapse: separate !important; + line-height: 1.6; +} + +table thead { + background: #F5F5F5; +} + +table tr { + border: none; + border-bottom: none; +} + +table th { + font-weight: bold; +} + +table th,table td { + border: none !important; + padding: 6px 13px; +} + +table tr:nth-child(2n) { + background-color: #F8F8F8; +} + +td p { + margin: 0 0 15px 0; +} + +div.table-contents td p { + margin: 0; +} + +div.important *,div.note *,div.tip *,div.warning *,div.navheader *,div.navfooter *,div.calloutlist * + { + border: none !important; + background: none !important; + margin: 0; +} + +div.important p,div.note p,div.tip p,div.warning p { + color: #6F6F6F; + line-height: 1.6; +} + +div.important code,div.note code,div.tip code,div.warning code { + background-color: #F2F2F2 !important; + border: 1px solid #CCCCCC !important; + border-radius: 4px !important; + padding: 1px 3px 0 !important; + text-shadow: none !important; + white-space: nowrap !important; +} + +.note th,.tip th,.warning th { + display: none; +} + +.note tr:first-child td,.tip tr:first-child td,.warning tr:first-child td + { + border-right: 1px solid #CCCCCC !important; + padding-top: 10px; +} + +div.calloutlist p,div.calloutlist td { + padding: 0; + margin: 0; +} + +div.calloutlist>table>tbody>tr>td:first-child { + padding-left: 10px; + width: 30px !important; +} + +div.important,div.note,div.tip,div.warning { + margin-left: 0px !important; + margin-right: 20px !important; + margin-top: 20px; + margin-bottom: 20px; + padding-top: 10px; + padding-bottom: 10px; +} + +div.toc { + line-height: 1.2; +} + +dl,dt { + margin-top: 1px; + margin-bottom: 0; +} + +div.toc>dl>dt { + font-size: 32px; + font-weight: bold; + margin: 30px 0 10px 0; + display: block; +} + +div.toc>dl>dd>dl>dt { + font-size: 24px; + font-weight: bold; + margin: 20px 0 10px 0; + display: block; +} + +div.toc>dl>dd>dl>dd>dl>dt { + font-weight: bold; + font-size: 20px; + margin: 10px 0 0 0; +} + +tbody.footnotes * { + border: none !important; +} + +div.footnote p { + margin: 0; + line-height: 1; +} + +div.footnote p sup { + margin-right: 6px; + vertical-align: middle; +} + +div.navheader { + border-bottom: 1px solid #CCCCCC; +} + +div.navfooter { + border-top: 1px solid #CCCCCC; +} + +.title { + margin-left: -1em; + padding-left: 1em; +} + +.title>a { + position: absolute; + visibility: hidden; + display: block; + font-size: 0.85em; + margin-top: 0.05em; + margin-left: -1em; + vertical-align: text-top; + color: black; +} + +.title>a:before { + content: "\00A7"; +} + +.title:hover>a,.title>a:hover,.title:hover>a:hover { + visibility: visible; +} + +.title:focus>a,.title>a:focus,.title:focus>a:focus { + outline: 0; +} diff --git a/spring-cloud-bus/2.1.0.RC3/single/images/background.png b/spring-cloud-bus/2.1.0.RC3/single/images/background.png new file mode 100644 index 00000000..15dca6fb Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/single/images/background.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/single/images/callouts/1.png b/spring-cloud-bus/2.1.0.RC3/single/images/callouts/1.png new file mode 100644 index 00000000..7d473430 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/single/images/callouts/1.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/single/images/callouts/2.png b/spring-cloud-bus/2.1.0.RC3/single/images/callouts/2.png new file mode 100644 index 00000000..5d09341b Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/single/images/callouts/2.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/single/images/callouts/3.png b/spring-cloud-bus/2.1.0.RC3/single/images/callouts/3.png new file mode 100644 index 00000000..ef7b7004 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/single/images/callouts/3.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/single/images/caution.png b/spring-cloud-bus/2.1.0.RC3/single/images/caution.png new file mode 100644 index 00000000..8a5e4fca Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/single/images/caution.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/single/images/important.png b/spring-cloud-bus/2.1.0.RC3/single/images/important.png new file mode 100644 index 00000000..ec54df65 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/single/images/important.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/single/images/logo.png b/spring-cloud-bus/2.1.0.RC3/single/images/logo.png new file mode 100644 index 00000000..ade2ce6e Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/single/images/logo.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/single/images/note.png b/spring-cloud-bus/2.1.0.RC3/single/images/note.png new file mode 100644 index 00000000..88d997b1 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/single/images/note.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/single/images/tip.png b/spring-cloud-bus/2.1.0.RC3/single/images/tip.png new file mode 100644 index 00000000..6530abb4 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/single/images/tip.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/single/images/warning.png b/spring-cloud-bus/2.1.0.RC3/single/images/warning.png new file mode 100644 index 00000000..0d5b5244 Binary files /dev/null and b/spring-cloud-bus/2.1.0.RC3/single/images/warning.png differ diff --git a/spring-cloud-bus/2.1.0.RC3/single/spring-cloud-bus.html b/spring-cloud-bus/2.1.0.RC3/single/spring-cloud-bus.html new file mode 100644 index 00000000..f9e18d99 --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/single/spring-cloud-bus.html @@ -0,0 +1,136 @@ + + + Spring Cloud Bus

Spring Cloud Bus


Spring Cloud Bus links the nodes of a distributed system with a lightweight message +broker. This broker can then be used to broadcast state changes (such as configuration +changes) or other management instructions. A key idea is that the bus is like a +distributed actuator for a Spring Boot application that is scaled out. However, it can +also be used as a communication channel between apps. This project provides starters for +either an AMQP broker or Kafka as the transport.

[Note]Note

Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at github.

1. Quick Start

Spring Cloud Bus works by adding Spring Boot autconfiguration if it detects itself on the +classpath. To enable the bus, add spring-cloud-starter-bus-amqp or +spring-cloud-starter-bus-kafka to your dependency management. Spring Cloud takes care of +the rest. Make sure the broker (RabbitMQ or Kafka) is available and configured. When +running on localhost, you need not do anything. If you run remotely, use Spring Cloud +Connectors or Spring Boot conventions to define the broker credentials, as shown in the +following example for Rabbit:

application.yml.  +

spring:
+  rabbitmq:
+    host: mybroker.com
+    port: 5672
+    username: user
+    password: secret

+

The bus currently supports sending messages to all nodes listening or all nodes for a +particular service (as defined by Eureka). The /bus/* actuator namespace has some HTTP +endpoints. Currently, two are implemented. The first, /bus/env, sends key/value pairs to +update each node’s Spring Environment. The second, /bus/refresh, reloads each +application’s configuration, as though they had all been pinged on their /refresh +endpoint.

[Note]Note

The Spring Cloud Bus starters cover Rabbit and Kafka, because those are the two most +common implementations. However, Spring Cloud Stream is quite flexible, and the binder +works with spring-cloud-bus.

2. Bus Endpoints

Spring Cloud Bus provides two endpoints, /actuator/bus-refresh and /actuator/bus-env +that correspond to individual actuator endpoints in Spring Cloud Commons, +/actuator/refresh and /actuator/env respectively.

2.1 Bus Refresh Endpoint

The /actuator/bus-refresh endpoint clears the RefreshScope cache and rebinds +@ConfigurationProperties. See the Refresh Scope documentation for +more information.

To expose the /actuator/bus-refresh endpoint, you need to add following configuration to your +application:

management.endpoints.web.exposure.include=bus-refresh

2.2 Bus Env Endpoint

The /actuator/bus-env endpoint updates each instances environment with the specified +key/value pair across multiple instances.

To expose the /actuator/bus-env endpoint, you need to add following configuration to your +application:

management.endpoints.web.exposure.include=bus-env

The /actuator/bus-env endpoint accepts POST requests with the following shape:

{
+	"name": "key1",
+	"value": "value1"
+}

3. Addressing an Instance

Each instance of the application has a service ID, whose value can be set with +spring.cloud.bus.id and whose value is expected to be a colon-separated list of +identifiers, in order from least specific to most specific. The default value is +constructed from the environment as a combination of the spring.application.name and +server.port (or spring.application.index, if set). The default value of the ID is +constructed in the form of app:index:id, where:

  • app is the vcap.application.name, if it exists, or spring.application.name
  • index is the vcap.application.instance_index, if it exists, +spring.application.index, local.server.port, server.port, or 0 (in that order).
  • id is the vcap.application.instance_id, if it exists, or a random value.

The HTTP endpoints accept a destination path parameter, such as +/bus-refresh/customers:9000, where destination is a service ID. If the ID +is owned by an instance on the bus, it processes the message, and all other instances +ignore it.

4. Addressing All Instances of a Service

The destination parameter is used in a Spring PathMatcher (with the path separator +as a colon — :) to determine if an instance processes the message. Using the example +from earlier, /bus-env/customers:** targets all instances of the +customers service regardless of the rest of the service ID.

5. Service ID Must Be Unique

The bus tries twice to eliminate processing an event — once from the original +ApplicationEvent and once from the queue. To do so, it checks the sending service ID +against the current service ID. If multiple instances of a service have the same ID, +events are not processed. When running on a local machine, each service is on a different +port, and that port is part of the ID. Cloud Foundry supplies an index to differentiate. +To ensure that the ID is unique outside Cloud Foundry, set spring.application.index to +something unique for each instance of a service.

6. Customizing the Message Broker

Spring Cloud Bus uses Spring Cloud Stream to +broadcast the messages. So, to get messages to flow, you need only include the binder +implementation of your choice in the classpath. There are convenient starters for the bus +with AMQP (RabbitMQ) and Kafka (spring-cloud-starter-bus-[amqp|kafka]). Generally +speaking, Spring Cloud Stream relies on Spring Boot autoconfiguration conventions for +configuring middleware. For instance, the AMQP broker address can be changed with +spring.rabbitmq.* configuration properties. Spring Cloud Bus has a handful of +native configuration properties in spring.cloud.bus.* (for example, +spring.cloud.bus.destination is the name of the topic to use as the external +middleware). Normally, the defaults suffice.

To learn more about how to customize the message broker settings, consult the Spring Cloud +Stream documentation.

7. Tracing Bus Events

Bus events (subclasses of RemoteApplicationEvent) can be traced by setting +spring.cloud.bus.trace.enabled=true. If you do so, the Spring Boot TraceRepository +(if it is present) shows each event sent and all the acks from each service instance. The +following example comes from the /trace endpoint:

{
+  "timestamp": "2015-11-26T10:24:44.411+0000",
+  "info": {
+    "signal": "spring.cloud.bus.ack",
+    "type": "RefreshRemoteApplicationEvent",
+    "id": "c4d374b7-58ea-4928-a312-31984def293b",
+    "origin": "stores:8081",
+    "destination": "*:**"
+  }
+  },
+  {
+  "timestamp": "2015-11-26T10:24:41.864+0000",
+  "info": {
+    "signal": "spring.cloud.bus.sent",
+    "type": "RefreshRemoteApplicationEvent",
+    "id": "c4d374b7-58ea-4928-a312-31984def293b",
+    "origin": "customers:9000",
+    "destination": "*:**"
+  }
+  },
+  {
+  "timestamp": "2015-11-26T10:24:41.862+0000",
+  "info": {
+    "signal": "spring.cloud.bus.ack",
+    "type": "RefreshRemoteApplicationEvent",
+    "id": "c4d374b7-58ea-4928-a312-31984def293b",
+    "origin": "customers:9000",
+    "destination": "*:**"
+  }
+}

The preceding trace shows that a RefreshRemoteApplicationEvent was sent from +customers:9000, broadcast to all services, and received (acked) by customers:9000 and +stores:8081.

To handle the ack signals yourself, you could add an @EventListener for the +AckRemoteApplicationEvent and SentApplicationEvent types to your app (and enable +tracing). Alternatively, you could tap into the TraceRepository and mine the data from +there.

[Note]Note

Any Bus application can trace acks. However, sometimes, it is +useful to do this in a central service that can do more complex +queries on the data or forward it to a specialized tracing service.

8. Broadcasting Your Own Events

The Bus can carry any event of type RemoteApplicationEvent. The default transport is +JSON, and the deserializer needs to know which types are going to be used ahead of time. +To register a new type, you must put it in a subpackage of +org.springframework.cloud.bus.event.

To customise the event name, you can use @JsonTypeName on your custom class or rely on +the default strategy, which is to use the simple name of the class.

[Note]Note

Both the producer and the consumer need access to the class definition.

8.1 Registering events in custom packages

If you cannot or do not want to use a subpackage of org.springframework.cloud.bus.event +for your custom events, you must specify which packages to scan for events of type +RemoteApplicationEvent by using the @RemoteApplicationEventScan annotation. Packages +specified with @RemoteApplicationEventScan include subpackages.

For example, consider the following custom event, called MyEvent:

package com.acme;
+
+public class MyEvent extends RemoteApplicationEvent {
+    ...
+}

You can register that event with the deserializer in the following way:

package com.acme;
+
+@Configuration
+@RemoteApplicationEventScan
+public class BusConfiguration {
+    ...
+}

Without specifying a value, the package of the class where @RemoteApplicationEventScan +is used is registered. In this example, com.acme is registered by using the package of +BusConfiguration.

You can also explicitly specify the packages to scan by using the value, basePackages +or basePackageClasses properties on @RemoteApplicationEventScan, as shown in the +following example:

package com.acme;
+
+@Configuration
+//@RemoteApplicationEventScan({"com.acme", "foo.bar"})
+//@RemoteApplicationEventScan(basePackages = {"com.acme", "foo.bar", "fizz.buzz"})
+@RemoteApplicationEventScan(basePackageClasses = BusConfiguration.class)
+public class BusConfiguration {
+    ...
+}

All of the preceding examples of @RemoteApplicationEventScan are equivalent, in that the +com.acme package is registered by explicitly specifying the packages on +@RemoteApplicationEventScan.

[Note]Note

You can specify multiple base packages to scan.

\ No newline at end of file diff --git a/spring-cloud-bus/2.1.0.RC3/spring-cloud-bus.xml b/spring-cloud-bus/2.1.0.RC3/spring-cloud-bus.xml new file mode 100644 index 00000000..818a0e4c --- /dev/null +++ b/spring-cloud-bus/2.1.0.RC3/spring-cloud-bus.xml @@ -0,0 +1,241 @@ + + + + + +Spring Cloud Bus +2018-12-20 + + + +Spring Cloud Bus links the nodes of a distributed system with a lightweight message +broker. This broker can then be used to broadcast state changes (such as configuration +changes) or other management instructions. A key idea is that the bus is like a +distributed actuator for a Spring Boot application that is scaled out. However, it can +also be used as a communication channel between apps. This project provides starters for +either an AMQP broker or Kafka as the transport. + +Spring Cloud is released under the non-restrictive Apache 2.0 license. If you would like to contribute to this section of the documentation or if you find an error, please find the source code and issue trackers in the project at github. + + + +Quick Start +Spring Cloud Bus works by adding Spring Boot autconfiguration if it detects itself on the +classpath. To enable the bus, add spring-cloud-starter-bus-amqp or +spring-cloud-starter-bus-kafka to your dependency management. Spring Cloud takes care of +the rest. Make sure the broker (RabbitMQ or Kafka) is available and configured. When +running on localhost, you need not do anything. If you run remotely, use Spring Cloud +Connectors or Spring Boot conventions to define the broker credentials, as shown in the +following example for Rabbit: + +application.yml + +spring: + rabbitmq: + host: mybroker.com + port: 5672 + username: user + password: secret + + +The bus currently supports sending messages to all nodes listening or all nodes for a +particular service (as defined by Eureka). The /bus/* actuator namespace has some HTTP +endpoints. Currently, two are implemented. The first, /bus/env, sends key/value pairs to +update each node’s Spring Environment. The second, /bus/refresh, reloads each +application’s configuration, as though they had all been pinged on their /refresh +endpoint. + +The Spring Cloud Bus starters cover Rabbit and Kafka, because those are the two most +common implementations. However, Spring Cloud Stream is quite flexible, and the binder +works with spring-cloud-bus. + + + +Bus Endpoints +Spring Cloud Bus provides two endpoints, /actuator/bus-refresh and /actuator/bus-env +that correspond to individual actuator endpoints in Spring Cloud Commons, +/actuator/refresh and /actuator/env respectively. +
+Bus Refresh Endpoint +The /actuator/bus-refresh endpoint clears the RefreshScope cache and rebinds +@ConfigurationProperties. See the Refresh Scope documentation for +more information. +To expose the /actuator/bus-refresh endpoint, you need to add following configuration to your +application: +management.endpoints.web.exposure.include=bus-refresh +
+
+Bus Env Endpoint +The /actuator/bus-env endpoint updates each instances environment with the specified +key/value pair across multiple instances. +To expose the /actuator/bus-env endpoint, you need to add following configuration to your +application: +management.endpoints.web.exposure.include=bus-env +The /actuator/bus-env endpoint accepts POST requests with the following shape: +{ + "name": "key1", + "value": "value1" +} +
+
+ +Addressing an Instance +Each instance of the application has a service ID, whose value can be set with +spring.cloud.bus.id and whose value is expected to be a colon-separated list of +identifiers, in order from least specific to most specific. The default value is +constructed from the environment as a combination of the spring.application.name and +server.port (or spring.application.index, if set). The default value of the ID is +constructed in the form of app:index:id, where: + + +app is the vcap.application.name, if it exists, or spring.application.name + + +index is the vcap.application.instance_index, if it exists, +spring.application.index, local.server.port, server.port, or 0 (in that order). + + +id is the vcap.application.instance_id, if it exists, or a random value. + + +The HTTP endpoints accept a destination path parameter, such as +/bus-refresh/customers:9000, where destination is a service ID. If the ID +is owned by an instance on the bus, it processes the message, and all other instances +ignore it. + + +Addressing All Instances of a Service +The destination parameter is used in a Spring PathMatcher (with the path separator +as a colon — :) to determine if an instance processes the message. Using the example +from earlier, /bus-env/customers:** targets all instances of the +customers service regardless of the rest of the service ID. + + +Service ID Must Be Unique +The bus tries twice to eliminate processing an event — once from the original +ApplicationEvent and once from the queue. To do so, it checks the sending service ID +against the current service ID. If multiple instances of a service have the same ID, +events are not processed. When running on a local machine, each service is on a different +port, and that port is part of the ID. Cloud Foundry supplies an index to differentiate. +To ensure that the ID is unique outside Cloud Foundry, set spring.application.index to +something unique for each instance of a service. + + +Customizing the Message Broker +Spring Cloud Bus uses Spring Cloud Stream to +broadcast the messages. So, to get messages to flow, you need only include the binder +implementation of your choice in the classpath. There are convenient starters for the bus +with AMQP (RabbitMQ) and Kafka (spring-cloud-starter-bus-[amqp|kafka]). Generally +speaking, Spring Cloud Stream relies on Spring Boot autoconfiguration conventions for +configuring middleware. For instance, the AMQP broker address can be changed with +spring.rabbitmq.* configuration properties. Spring Cloud Bus has a handful of +native configuration properties in spring.cloud.bus.* (for example, +spring.cloud.bus.destination is the name of the topic to use as the external +middleware). Normally, the defaults suffice. +To learn more about how to customize the message broker settings, consult the Spring Cloud +Stream documentation. + + +Tracing Bus Events +Bus events (subclasses of RemoteApplicationEvent) can be traced by setting +spring.cloud.bus.trace.enabled=true. If you do so, the Spring Boot TraceRepository +(if it is present) shows each event sent and all the acks from each service instance. The +following example comes from the /trace endpoint: +{ + "timestamp": "2015-11-26T10:24:44.411+0000", + "info": { + "signal": "spring.cloud.bus.ack", + "type": "RefreshRemoteApplicationEvent", + "id": "c4d374b7-58ea-4928-a312-31984def293b", + "origin": "stores:8081", + "destination": "*:**" + } + }, + { + "timestamp": "2015-11-26T10:24:41.864+0000", + "info": { + "signal": "spring.cloud.bus.sent", + "type": "RefreshRemoteApplicationEvent", + "id": "c4d374b7-58ea-4928-a312-31984def293b", + "origin": "customers:9000", + "destination": "*:**" + } + }, + { + "timestamp": "2015-11-26T10:24:41.862+0000", + "info": { + "signal": "spring.cloud.bus.ack", + "type": "RefreshRemoteApplicationEvent", + "id": "c4d374b7-58ea-4928-a312-31984def293b", + "origin": "customers:9000", + "destination": "*:**" + } +} +The preceding trace shows that a RefreshRemoteApplicationEvent was sent from +customers:9000, broadcast to all services, and received (acked) by customers:9000 and +stores:8081. +To handle the ack signals yourself, you could add an @EventListener for the +AckRemoteApplicationEvent and SentApplicationEvent types to your app (and enable +tracing). Alternatively, you could tap into the TraceRepository and mine the data from +there. + +Any Bus application can trace acks. However, sometimes, it is +useful to do this in a central service that can do more complex +queries on the data or forward it to a specialized tracing service. + + + +Broadcasting Your Own Events +The Bus can carry any event of type RemoteApplicationEvent. The default transport is +JSON, and the deserializer needs to know which types are going to be used ahead of time. +To register a new type, you must put it in a subpackage of +org.springframework.cloud.bus.event. +To customise the event name, you can use @JsonTypeName on your custom class or rely on +the default strategy, which is to use the simple name of the class. + +Both the producer and the consumer need access to the class definition. + +
+Registering events in custom packages +If you cannot or do not want to use a subpackage of org.springframework.cloud.bus.event +for your custom events, you must specify which packages to scan for events of type +RemoteApplicationEvent by using the @RemoteApplicationEventScan annotation. Packages +specified with @RemoteApplicationEventScan include subpackages. +For example, consider the following custom event, called MyEvent: +package com.acme; + +public class MyEvent extends RemoteApplicationEvent { + ... +} +You can register that event with the deserializer in the following way: +package com.acme; + +@Configuration +@RemoteApplicationEventScan +public class BusConfiguration { + ... +} +Without specifying a value, the package of the class where @RemoteApplicationEventScan +is used is registered. In this example, com.acme is registered by using the package of +BusConfiguration. +You can also explicitly specify the packages to scan by using the value, basePackages +or basePackageClasses properties on @RemoteApplicationEventScan, as shown in the +following example: +package com.acme; + +@Configuration +//@RemoteApplicationEventScan({"com.acme", "foo.bar"}) +//@RemoteApplicationEventScan(basePackages = {"com.acme", "foo.bar", "fizz.buzz"}) +@RemoteApplicationEventScan(basePackageClasses = BusConfiguration.class) +public class BusConfiguration { + ... +} +All of the preceding examples of @RemoteApplicationEventScan are equivalent, in that the +com.acme package is registered by explicitly specifying the packages on +@RemoteApplicationEventScan. + +You can specify multiple base packages to scan. + +
+
+
\ No newline at end of file