├── .editorconfig
├── .github
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE.md
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── dco.yml
├── dependabot.yml
└── workflows
│ ├── deploy-docs.yml
│ └── maven.yaml
├── .gitignore
├── .java-version
├── .mvn
├── jvm.config
├── maven.config
└── wrapper
│ ├── MavenWrapperDownloader.java
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── .sdkmanrc
├── .settings.xml
├── .springformat
├── Guardfile
├── LICENSE.txt
├── README.adoc
├── SECURITY.md
├── docs
├── .java-version
├── antora-playbook.yml
├── antora.yml
├── modules
│ └── ROOT
│ │ ├── nav.adoc
│ │ ├── pages
│ │ ├── _attributes.adoc
│ │ ├── appendix.adoc
│ │ ├── configprops.adoc
│ │ ├── index.adoc
│ │ ├── intro.adoc
│ │ ├── quickstart.adoc
│ │ ├── spring-cloud-bus.adoc
│ │ └── spring-cloud-bus
│ │ │ ├── addressing.adoc
│ │ │ ├── bus-endpoints.adoc
│ │ │ ├── configuration.adoc
│ │ │ └── custom-events.adoc
│ │ └── partials
│ │ └── _configprops.adoc
├── package.json
├── pom.xml
└── src
│ └── main
│ ├── antora
│ └── resources
│ │ └── antora-resources
│ │ └── antora.yml
│ └── asciidoc
│ ├── README.adoc
│ ├── ghpages.sh
│ └── sagan-index.adoc
├── mvnw
├── mvnw.cmd
├── pom.xml
├── spring-cloud-bus-dependencies
└── pom.xml
├── spring-cloud-bus-tests
├── pom.xml
└── src
│ └── test
│ └── java
│ └── org
│ └── springframework
│ └── cloud
│ └── bus
│ ├── BusAmqpIntegrationTests.java
│ ├── BusJmxEndpointTests.java
│ ├── ShutdownListenerIntegrationTests.java
│ └── jackson
│ └── BusJacksonIntegrationTests.java
├── spring-cloud-bus
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── org
│ │ │ └── springframework
│ │ │ └── cloud
│ │ │ └── bus
│ │ │ ├── BusAutoConfiguration.java
│ │ │ ├── BusBridge.java
│ │ │ ├── BusConstants.java
│ │ │ ├── BusConsumer.java
│ │ │ ├── BusEnvironmentPostProcessor.java
│ │ │ ├── BusPathMatcher.java
│ │ │ ├── BusProperties.java
│ │ │ ├── BusRefreshAutoConfiguration.java
│ │ │ ├── BusShutdownAutoConfiguration.java
│ │ │ ├── BusStreamAutoConfiguration.java
│ │ │ ├── ConditionalOnBusEnabled.java
│ │ │ ├── DefaultBusPathMatcher.java
│ │ │ ├── PathServiceMatcher.java
│ │ │ ├── PathServiceMatcherAutoConfiguration.java
│ │ │ ├── RemoteApplicationEventListener.java
│ │ │ ├── ServiceMatcher.java
│ │ │ ├── StreamBusBridge.java
│ │ │ ├── endpoint
│ │ │ ├── AbstractBusEndpoint.java
│ │ │ ├── EnvironmentBusEndpoint.java
│ │ │ ├── RefreshBusEndpoint.java
│ │ │ └── ShutdownBusEndpoint.java
│ │ │ ├── event
│ │ │ ├── AckRemoteApplicationEvent.java
│ │ │ ├── Destination.java
│ │ │ ├── EnvironmentChangeListener.java
│ │ │ ├── EnvironmentChangeRemoteApplicationEvent.java
│ │ │ ├── PathDestinationFactory.java
│ │ │ ├── RefreshListener.java
│ │ │ ├── RefreshRemoteApplicationEvent.java
│ │ │ ├── RemoteApplicationEvent.java
│ │ │ ├── SentApplicationEvent.java
│ │ │ ├── ShutdownListener.java
│ │ │ ├── ShutdownRemoteApplicationEvent.java
│ │ │ ├── TraceListener.java
│ │ │ └── UnknownRemoteApplicationEvent.java
│ │ │ └── jackson
│ │ │ ├── BusJacksonAutoConfiguration.java
│ │ │ ├── RemoteApplicationEventRegistrar.java
│ │ │ ├── RemoteApplicationEventScan.java
│ │ │ └── SubtypeModule.java
│ └── resources
│ │ └── META-INF
│ │ ├── additional-spring-configuration-metadata.json
│ │ ├── spring.factories
│ │ └── spring
│ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
│ └── test
│ ├── java
│ ├── org
│ │ └── springframework
│ │ │ └── cloud
│ │ │ └── bus
│ │ │ ├── BusAutoConfigurationClassPathTests.java
│ │ │ ├── BusAutoConfigurationTests.java
│ │ │ ├── BusEnvironmentPostProcessorTests.java
│ │ │ ├── ConditionalOnBusEnabledTests.java
│ │ │ ├── PathServiceMatcherTests.java
│ │ │ ├── PathServiceMatcherWithConfigNamesTests.java
│ │ │ ├── RefreshListenerIntegrationTests.java
│ │ │ ├── endpoint
│ │ │ └── RefreshBusEndpointTests.java
│ │ │ ├── event
│ │ │ └── test
│ │ │ │ ├── TestRemoteApplicationEvent.java
│ │ │ │ └── TypedRemoteApplicationEvent.java
│ │ │ └── jackson
│ │ │ ├── RemoteApplicationEventScanTests.java
│ │ │ ├── SerializationTests.java
│ │ │ └── SubtypeModuleTests.java
│ └── test
│ │ └── foo
│ │ └── bar
│ │ └── FooBarTestRemoteApplicationEvent.java
│ └── resources
│ └── application.properties
├── spring-cloud-starter-bus-amqp
└── pom.xml
├── spring-cloud-starter-bus-kafka
└── pom.xml
├── spring-cloud-starter-bus-stream
└── pom.xml
└── src
└── checkstyle
└── checkstyle-suppressions.xml
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: https://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | [*]
7 | indent_style = tab
8 | indent_size = 4
9 | end_of_line = lf
10 | insert_final_newline = true
11 |
12 | [*.yml]
13 | indent_style = space
14 | indent_size = 2
15 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 |
2 | # Contributing
3 |
4 | Spring Cloud is released under the non-restrictive Apache 2.0 license,
5 | and follows a very standard Github development process, using Github
6 | tracker for issues and merging pull requests into master. If you want
7 | to contribute even something trivial please do not hesitate, but
8 | follow the guidelines below.
9 |
10 | ## Sign the Contributor License Agreement
11 | Before we accept a non-trivial patch or pull request we will need you to sign the
12 | [Contributor License Agreement](https://cla.pivotal.io/sign/spring).
13 | Signing the contributor's agreement does not grant anyone commit rights to the main
14 | repository, but it does mean that we can accept your contributions, and you will get an
15 | author credit if we do. Active contributors might be asked to join the core team, and
16 | given the ability to merge pull requests.
17 |
18 | ## Code of Conduct
19 | This project adheres to the Contributor Covenant [code of
20 | conduct](https://github.com/spring-cloud/spring-cloud-build/blob/main/docs/modules/ROOT/partials/code-of-conduct.adoc). By participating, you are expected to uphold this code. Please report
21 | unacceptable behavior to spring-code-of-conduct@pivotal.io.
22 |
23 | ## Code Conventions and Housekeeping
24 | None of these is essential for a pull request, but they will all help. They can also be
25 | added after the original pull request but before a merge.
26 |
27 | * Use the Spring Framework code format conventions. If you use Eclipse
28 | you can import formatter settings using the
29 | `eclipse-code-formatter.xml` file from the
30 | [Spring Cloud Build](https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml) project. If using IntelliJ, you can use the
31 | [Eclipse Code Formatter Plugin](https://plugins.jetbrains.com/plugin/6546) to import the same file.
32 | * Make sure all new `.java` files to have a simple Javadoc class comment with at least an
33 | `@author` tag identifying you, and preferably at least a paragraph on what the class is
34 | for.
35 | * Add the ASF license header comment to all new `.java` files (copy from existing files
36 | in the project)
37 | * Add yourself as an `@author` to the .java files that you modify substantially (more
38 | than cosmetic changes).
39 | * Add some Javadocs and, if you change the namespace, some XSD doc elements.
40 | * A few unit tests would help a lot as well -- someone has to do it.
41 | * If no-one else is using your branch, please rebase it against the current master (or
42 | other target branch in the main project).
43 | * When writing a commit message please follow [these conventions](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html),
44 | if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit
45 | message (where XXXX is the issue number).
46 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | Please provide details of the problem, including the version of Spring Cloud that you
12 | are using.
13 |
14 | **Sample**
15 | If possible, please provide a test case or sample application that reproduces
16 | the problem. This makes it much easier for us to diagnose the problem and to verify that
17 | we have fixed it.
18 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/dco.yml:
--------------------------------------------------------------------------------
1 | require:
2 | members: false
3 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "github-actions"
9 | directory: "/"
10 | target-branch: "main"
11 | schedule:
12 | interval: "weekly"
13 | - package-ecosystem: maven
14 | directory: /
15 | schedule:
16 | interval: daily
17 | target-branch: main
18 | #ignore:
19 | # only upgrade by minor or patch
20 | #- dependency-name: "*"
21 | # update-types:
22 | # - version-update:semver-major
23 | - package-ecosystem: maven
24 | directory: /
25 | schedule:
26 | interval: daily
27 | target-branch: 4.3.x
28 | ignore:
29 | # only upgrade by minor or patch
30 | - dependency-name: "*"
31 | update-types:
32 | - version-update:semver-major
33 | - version-update:semver-minor
34 | - package-ecosystem: maven
35 | directory: /
36 | schedule:
37 | interval: daily
38 | target-branch: 4.2.x
39 | ignore:
40 | # only upgrade by minor or patch
41 | - dependency-name: "*"
42 | update-types:
43 | - version-update:semver-major
44 | - version-update:semver-minor
45 | - package-ecosystem: maven
46 | directory: /
47 | schedule:
48 | interval: daily
49 | target-branch: 4.1.x
50 | ignore:
51 | # only upgrade by minor or patch
52 | - dependency-name: "*"
53 | update-types:
54 | - version-update:semver-major
55 | - version-update:semver-minor
56 | - package-ecosystem: npm
57 | target-branch: docs-build
58 | directory: /
59 | schedule:
60 | interval: weekly
61 | - package-ecosystem: npm
62 | target-branch: main
63 | directory: /docs
64 | schedule:
65 | interval: weekly
66 | - package-ecosystem: npm
67 | target-branch: 4.2.x
68 | directory: /docs
69 | schedule:
70 | interval: weekly
71 | - package-ecosystem: npm
72 | target-branch: 4.2.x
73 | directory: /docs
74 | schedule:
75 | interval: weekly
76 | - package-ecosystem: npm
77 | target-branch: 4.1.x
78 | directory: /docs
79 | schedule:
80 | interval: weekly
81 |
--------------------------------------------------------------------------------
/.github/workflows/deploy-docs.yml:
--------------------------------------------------------------------------------
1 | name: Deploy Docs
2 | on:
3 | push:
4 | branches-ignore: [ gh-pages ]
5 | tags: '**'
6 | repository_dispatch:
7 | types: request-build-reference # legacy
8 | #schedule:
9 | #- cron: '0 10 * * *' # Once per day at 10am UTC
10 | workflow_dispatch:
11 | permissions:
12 | actions: write
13 | jobs:
14 | build:
15 | runs-on: ubuntu-latest
16 | # if: github.repository_owner == 'spring-cloud'
17 | steps:
18 | - name: Checkout
19 | uses: actions/checkout@v3
20 | with:
21 | ref: docs-build
22 | fetch-depth: 1
23 | - name: Dispatch (partial build)
24 | if: github.ref_type == 'branch'
25 | env:
26 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
27 | run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD) -f build-refname=${{ github.ref_name }}
28 | - name: Dispatch (full build)
29 | if: github.ref_type == 'tag'
30 | env:
31 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32 | run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD)
33 |
--------------------------------------------------------------------------------
/.github/workflows/maven.yaml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Maven
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
3 |
4 | name: Build
5 | on:
6 | push:
7 | branches: [ main, 4.1.x, 4.0.x, 3.1.x ]
8 | pull_request:
9 | branches: [ main, 4.1.x, 4.0.x, 3.1.x ]
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v4
15 | - name: Set up JDK
16 | uses: actions/setup-java@v4
17 | with:
18 | distribution: 'temurin'
19 | java-version: '17'
20 | - name: Cache local Maven repository
21 | uses: actions/cache@v4
22 | with:
23 | path: ~/.m2/repository
24 | key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
25 | restore-keys: |
26 | ${{ runner.os }}-maven-
27 | - name: Build with Maven
28 | run: ./mvnw -s .settings.xml clean org.jacoco:jacoco-maven-plugin:prepare-agent install -U -P sonar -nsu --batch-mode -Dmaven.test.redirectTestOutputToFile=true -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn
29 | - name: Publish Test Report
30 | uses: mikepenz/action-junit-report@v5
31 | if: always() # always run even if the previous step fails
32 | with:
33 | report_paths: '**/surefire-reports/TEST-*.xml'
34 | - name: Archive code coverage results
35 | uses: actions/upload-artifact@v4
36 | with:
37 | name: surefire-reports
38 | path: '**/surefire-reports/*'
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *~
2 | #*
3 | *#
4 | .#*
5 | .classpath
6 | .project
7 | .settings
8 | .springBeans
9 | .gradle
10 | build
11 | bin
12 | target/
13 | _site/
14 | *.swp
15 | .idea
16 | *.iml
17 | .factorypath
18 | .vscode/
19 | .flattened-pom.xml
20 |
21 |
22 | node
23 | node_modules
24 | build
25 | /package.json
26 | package-lock.json
27 |
--------------------------------------------------------------------------------
/.java-version:
--------------------------------------------------------------------------------
1 | 17
2 |
--------------------------------------------------------------------------------
/.mvn/jvm.config:
--------------------------------------------------------------------------------
1 | -Xmx1024m -XX:CICompilerCount=1 -XX:TieredStopAtLevel=1 -Djava.security.egd=file:/dev/./urandom
--------------------------------------------------------------------------------
/.mvn/maven.config:
--------------------------------------------------------------------------------
1 | -P spring
2 |
--------------------------------------------------------------------------------
/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2007-present the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.6";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spring-cloud/spring-cloud-bus/55688a3d381da01d3faff67e1d232f745dacd245/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/.sdkmanrc:
--------------------------------------------------------------------------------
1 | # Enable auto-env through the sdkman_auto_env config
2 | # Add key=value pairs of SDKs to use below
3 | java=17.0.1-tem
4 |
--------------------------------------------------------------------------------
/.settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | repo.spring.io
6 | ${env.CI_DEPLOY_USERNAME}
7 | ${env.CI_DEPLOY_PASSWORD}
8 |
9 |
10 |
11 |
12 |
18 | spring
19 |
20 | true
21 |
22 |
23 |
24 | spring-snapshots
25 | Spring Snapshots
26 | https://repo.spring.io/snapshot
27 |
28 | true
29 |
30 |
31 |
32 | spring-milestones
33 | Spring Milestones
34 | https://repo.spring.io/milestone
35 |
36 | false
37 |
38 |
39 |
40 | spring-releases
41 | Spring Releases
42 | https://repo.spring.io/release
43 |
44 | false
45 |
46 |
47 |
48 |
49 |
50 | spring-snapshots
51 | Spring Snapshots
52 | https://repo.spring.io/snapshot
53 |
54 | true
55 |
56 |
57 |
58 | spring-milestones
59 | Spring Milestones
60 | https://repo.spring.io/milestone
61 |
62 | false
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/.springformat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spring-cloud/spring-cloud-bus/55688a3d381da01d3faff67e1d232f745dacd245/.springformat
--------------------------------------------------------------------------------
/Guardfile:
--------------------------------------------------------------------------------
1 | require 'asciidoctor'
2 | require 'erb'
3 | require './src/main/ruby/readme.rb'
4 |
5 | options = {:mkdirs => true, :safe => :unsafe, :attributes => ['linkcss', 'allow-uri-read']}
6 |
7 | guard 'shell' do
8 | watch(/^src\/[A-Z-a-z][^#]*\.adoc$/) {|m|
9 | SpringCloud::Build.render_file('src/main/asciidoc/README.adoc', :to_file => './README.adoc')
10 | Asciidoctor.render_file('src/main/asciidoc/spring-cloud-bus.adoc', options.merge(:to_dir => 'target/generated-docs'))
11 | }
12 | end
13 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Reporting a Vulnerability
4 |
5 | To report security vulnerabilities, please go to https://pivotal.io/security.
6 |
--------------------------------------------------------------------------------
/docs/.java-version:
--------------------------------------------------------------------------------
1 | 17
2 |
--------------------------------------------------------------------------------
/docs/antora-playbook.yml:
--------------------------------------------------------------------------------
1 | antora:
2 | extensions:
3 | - require: '@springio/antora-extensions'
4 | root_component_name: 'cloud-bus'
5 | site:
6 | title: Spring Cloud Bus
7 | url: https://docs.spring.io/spring-cloud-bus/reference/
8 | content:
9 | sources:
10 | - url: ./..
11 | branches: HEAD
12 | start_path: docs
13 | worktrees: true
14 | asciidoc:
15 | attributes:
16 | page-stackoverflow-url: https://stackoverflow.com/tags/spring-cloud
17 | page-pagination: ''
18 | hide-uri-scheme: '@'
19 | tabs-sync-option: '@'
20 | chomp: 'all'
21 | extensions:
22 | - '@asciidoctor/tabs'
23 | - '@springio/asciidoctor-extensions'
24 | sourcemap: true
25 | urls:
26 | latest_version_segment: ''
27 | runtime:
28 | log:
29 | failure_level: warn
30 | format: pretty
31 | ui:
32 | bundle:
33 | url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.15/ui-bundle.zip
34 |
--------------------------------------------------------------------------------
/docs/antora.yml:
--------------------------------------------------------------------------------
1 | name: cloud-bus
2 | version: true
3 | title: spring-cloud-bus
4 | nav:
5 | - modules/ROOT/nav.adoc
6 | ext:
7 | collector:
8 | run:
9 | command: ./mvnw --no-transfer-progress -B process-resources -Pdocs -pl docs -Dantora-maven-plugin.phase=none -Dgenerate-docs.phase=none -Dgenerate-readme.phase=none -Dgenerate-cloud-resources.phase=none -Dmaven-dependency-plugin-for-docs.phase=none -Dmaven-dependency-plugin-for-docs-classes.phase=none -DskipTests -DdisableConfigurationProperties
10 | local: true
11 | scan:
12 | dir: ./target/classes/antora-resources/
13 |
--------------------------------------------------------------------------------
/docs/modules/ROOT/nav.adoc:
--------------------------------------------------------------------------------
1 | * xref:index.adoc[]
2 | * xref:quickstart.adoc[]
3 | * xref:spring-cloud-bus.adoc[]
4 | ** xref:spring-cloud-bus/bus-endpoints.adoc[]
5 | ** xref:spring-cloud-bus/addressing.adoc[]
6 | ** xref:spring-cloud-bus/configuration.adoc[]
7 | ** xref:spring-cloud-bus/custom-events.adoc[]
8 | * xref:appendix.adoc[]
9 |
--------------------------------------------------------------------------------
/docs/modules/ROOT/pages/_attributes.adoc:
--------------------------------------------------------------------------------
1 | :doctype: book
2 | :idprefix:
3 | :idseparator: -
4 | :tabsize: 4
5 | :numbered:
6 | :sectanchors:
7 | :sectnums:
8 | :icons: font
9 | :hide-uri-scheme:
10 | :docinfo: shared,private
11 |
12 | :sc-ext: java
13 | :project-full-name: Spring Cloud Bus
14 |
--------------------------------------------------------------------------------
/docs/modules/ROOT/pages/appendix.adoc:
--------------------------------------------------------------------------------
1 | :numbered!:
2 | [appendix]
3 | [[common-application-properties]]
4 | = Common application properties
5 | :page-section-summary-toc: 1
6 |
7 |
8 | Various properties can be specified inside your `application.properties` file, inside your `application.yml` file, or as command line switches.
9 | This appendix provides a list of common Spring Cloud Bus properties and references to the underlying classes that consume them.
10 |
11 | NOTE: Property contributions can come from additional jar files on your classpath, so you should not consider this an exhaustive list.
12 | Also, you can define your own properties.
13 |
14 | include::partial$_configprops.adoc[]
--------------------------------------------------------------------------------
/docs/modules/ROOT/pages/configprops.adoc:
--------------------------------------------------------------------------------
1 | [[configuration-properties]]
2 | = Configuration Properties
3 |
4 | Below you can find a list of configuration properties.
5 |
6 | include::partial$_configprops.adoc[]
7 |
--------------------------------------------------------------------------------
/docs/modules/ROOT/pages/index.adoc:
--------------------------------------------------------------------------------
1 | include::intro.adoc[]
--------------------------------------------------------------------------------
/docs/modules/ROOT/pages/intro.adoc:
--------------------------------------------------------------------------------
1 | [[spring-cloud-bus-intro]]
2 | = Introduction
3 |
4 | Spring Cloud Bus links the nodes of a distributed system with a lightweight message
5 | broker. This broker can then be used to broadcast state changes (such as configuration
6 | changes) or other management instructions. A key idea is that the bus is like a
7 | distributed actuator for a Spring Boot application that is scaled out. However, it can
8 | also be used as a communication channel between apps. This project provides starters for
9 | either an AMQP broker or Kafka as the transport.
10 |
--------------------------------------------------------------------------------
/docs/modules/ROOT/pages/quickstart.adoc:
--------------------------------------------------------------------------------
1 | [[spring-cloud-gateway-quickstart]]
2 | = Quickstart
3 |
4 | Spring Cloud Bus works by adding Spring Boot autconfiguration if it detects itself on the
5 | classpath. To enable the bus, add `spring-cloud-starter-bus-amqp` or
6 | `spring-cloud-starter-bus-kafka` to your dependency management. Spring Cloud takes care of
7 | the rest. Make sure the broker (RabbitMQ or Kafka) is available and configured. When
8 | running on localhost, you need not do anything. If you run remotely, use Spring Cloud
9 | Connectors or Spring Boot conventions to define the broker credentials, as shown in the
10 | following example for Rabbit:
11 |
12 | .application.yml
13 | ----
14 | spring:
15 | rabbitmq:
16 | host: mybroker.com
17 | port: 5672
18 | username: user
19 | password: secret
20 | ----
21 |
22 | The bus currently supports sending messages to all nodes listening or all nodes for a
23 | particular service (as defined by Eureka). The `/bus*` actuator namespace has some HTTP
24 | endpoints. Currently, three are implemented. The first, `/busenv`, sends key/value pairs to
25 | update each node's Spring Environment. The second, `/busrefresh`, reloads each
26 | application's configuration, as though they had all been pinged on their `/refresh`
27 | endpoint. The third `/busshutdown` sends a shutdown event to gracefully shutdown the application instance(s).
28 |
29 | NOTE: The Spring Cloud Bus starters cover Rabbit and Kafka, because those are the two most
30 | common implementations. However, Spring Cloud Stream is quite flexible, and the binder
31 | works with `spring-cloud-bus`.
32 |
--------------------------------------------------------------------------------
/docs/modules/ROOT/pages/spring-cloud-bus.adoc:
--------------------------------------------------------------------------------
1 | [[spring-cloud-bus]]
2 | = Spring Cloud Bus
3 | :page-section-summary-toc: 1
4 |
5 | *{spring-cloud-version}*
6 |
--------------------------------------------------------------------------------
/docs/modules/ROOT/pages/spring-cloud-bus/addressing.adoc:
--------------------------------------------------------------------------------
1 | [[addressing]]
2 | = Addressing Instances
3 | :page-section-summary-toc: 1
4 |
5 | [[addressing-an-instance]]
6 | == Addressing an Instance
7 |
8 | Each instance of the application has a service ID, whose value can be set with
9 | `spring.cloud.bus.id` and whose value is expected to be a colon-separated list of
10 | identifiers, in order from least specific to most specific. The default value is
11 | constructed from the environment as a combination of the `spring.application.name` and
12 | `server.port` (or `spring.application.index`, if set). The default value of the ID is
13 | constructed in the form of `app:index:id`, where:
14 |
15 | * `app` is the `vcap.application.name`, if it exists, or `spring.application.name`
16 | * `index` is the `vcap.application.instance_index`, if it exists,
17 | `spring.application.index`, `local.server.port`, `server.port`, or `0` (in that order).
18 | * `id` is the `vcap.application.instance_id`, if it exists, or a random value.
19 |
20 | The HTTP endpoints accept a "`destination`" path parameter, such as
21 | `/busrefresh/customers:9000`, where `destination` is a service ID. If the ID
22 | is owned by an instance on the bus, it processes the message, and all other instances
23 | ignore it.
24 |
25 | [[addressing-all-instances-of-a-service]]
26 | == Addressing All Instances of a Service
27 |
28 | The "`destination`" parameter is used in a Spring `PathMatcher` (with the path separator
29 | as a colon -- `:`) to determine if an instance processes the message. Using the example
30 | from earlier, `/busenv/customers:**` targets all instances of the
31 | "`customers`" service regardless of the rest of the service ID.
32 |
33 | [[service-id-must-be-unique]]
34 | == Service ID Must Be Unique
35 |
36 | The bus tries twice to eliminate processing an event -- once from the original
37 | `ApplicationEvent` and once from the queue. To do so, it checks the sending service ID
38 | against the current service ID. If multiple instances of a service have the same ID,
39 | events are not processed. When running on a local machine, each service is on a different
40 | port, and that port is part of the ID. Cloud Foundry supplies an index to differentiate.
41 | To ensure that the ID is unique outside Cloud Foundry, set `spring.application.index` to
42 | something unique for each instance of a service.
43 |
44 |
--------------------------------------------------------------------------------
/docs/modules/ROOT/pages/spring-cloud-bus/bus-endpoints.adoc:
--------------------------------------------------------------------------------
1 | [[bus-endpoints]]
2 | = Bus Endpoints
3 | :page-section-summary-toc: 1
4 |
5 | Spring Cloud Bus provides three endpoints, `/actuator/busrefresh`, `/actutator/busshutdown` and `/actuator/busenv`
6 | that correspond to individual actuator endpoints in Spring Cloud Commons,
7 | `/actuator/refresh`, `/actuator/shutdown`, and `/actuator/env` respectively.
8 |
9 | [[bus-refresh-endpoint]]
10 | == Bus Refresh Endpoint
11 | The `/actuator/busrefresh` endpoint clears the `RefreshScope` cache and rebinds
12 | `@ConfigurationProperties`. See the <> documentation for
13 | more information.
14 |
15 | To expose the `/actuator/busrefresh` endpoint, you need to add following configuration to your
16 | application:
17 |
18 | [source,properties]
19 | ----
20 | management.endpoints.web.exposure.include=busrefresh
21 | ----
22 |
23 | [[bus-env-endpoint]]
24 | == Bus Env Endpoint
25 | The `/actuator/busenv` endpoint updates each instances environment with the specified
26 | key/value pair across multiple instances.
27 |
28 | To expose the `/actuator/busenv` endpoint, you need to add following configuration to your
29 | application:
30 |
31 | [source,properties]
32 | ----
33 | management.endpoints.web.exposure.include=busenv
34 | ----
35 |
36 | The `/actuator/busenv` endpoint accepts `POST` requests with the following shape:
37 |
38 | [source,json]
39 | ----
40 | {
41 | "name": "key1",
42 | "value": "value1"
43 | }
44 | ----
45 |
46 | [[bus-shutdown-endpoint]]
47 | == Bus Shutdown Endpoint
48 | The `/actuator/busshutdown` shuts down the application https://docs.spring.io/spring-boot/reference/web/graceful-shutdown.html[gracefully].
49 |
50 | To expose the `/actuator/busshutdown` endpoint, you need to add following configuration to your
51 | application:
52 |
53 | [source,properties]
54 | ----
55 | management.endpoints.web.exposure.include=busshutdown
56 | ----
57 |
58 | You can make a request to the `busshutdown` endpoint by issuing a `POST` request.
59 |
60 | If you would like to target a specific application you can issue a `POST` request to `/busshutdown` and optionally
61 | specify the bus id:
62 |
63 | [source,bash]
64 | ----
65 | $ curl -X POST http://localhost:8080/actuator/busshutdown
66 | ----
67 |
68 | You can also target a specific application instance by specifying the bus id:
69 |
70 | [source,bash]
71 | ----
72 | $ curl -X POST http://localhost:8080/actuator/busshutdown/busid:123
73 | ----
74 |
--------------------------------------------------------------------------------
/docs/modules/ROOT/pages/spring-cloud-bus/configuration.adoc:
--------------------------------------------------------------------------------
1 | [[configuration]]
2 | = Configuration
3 | :page-section-summary-toc: 1
4 |
5 | [[customizing-the-message-broker]]
6 | == Customizing the Message Broker
7 |
8 | Spring Cloud Bus uses https://cloud.spring.io/spring-cloud-stream[Spring Cloud Stream] to
9 | broadcast the messages. So, to get messages to flow, you need only include the binder
10 | implementation of your choice in the classpath. There are convenient starters for the bus
11 | with AMQP (RabbitMQ) and Kafka (`spring-cloud-starter-bus-[amqp|kafka]`). Generally
12 | speaking, Spring Cloud Stream relies on Spring Boot autoconfiguration conventions for
13 | configuring middleware. For instance, the AMQP broker address can be changed with
14 | `spring.rabbitmq.{asterisk}` configuration properties. Spring Cloud Bus has a handful of
15 | native configuration properties in `spring.cloud.bus.{asterisk}` (for example,
16 | `spring.cloud.bus.destination` is the name of the topic to use as the external
17 | middleware). Normally, the defaults suffice.
18 |
19 | To learn more about how to customize the message broker settings, consult the Spring Cloud
20 | Stream documentation.
21 |
22 | [[tracing-bus-events]]
23 | == Tracing Bus Events
24 |
25 | Bus events (subclasses of `RemoteApplicationEvent`) can be traced by setting
26 | `spring.cloud.bus.trace.enabled=true`. If you do so, the Spring Boot `TraceRepository`
27 | (if it is present) shows each event sent and all the acks from each service instance. The
28 | following example comes from the `/trace` endpoint:
29 |
30 | [source,json]
31 | ----
32 | {
33 | "timestamp": "2015-11-26T10:24:44.411+0000",
34 | "info": {
35 | "signal": "spring.cloud.bus.ack",
36 | "type": "RefreshRemoteApplicationEvent",
37 | "id": "c4d374b7-58ea-4928-a312-31984def293b",
38 | "origin": "stores:8081",
39 | "destination": "*:**"
40 | }
41 | },
42 | {
43 | "timestamp": "2015-11-26T10:24:41.864+0000",
44 | "info": {
45 | "signal": "spring.cloud.bus.sent",
46 | "type": "RefreshRemoteApplicationEvent",
47 | "id": "c4d374b7-58ea-4928-a312-31984def293b",
48 | "origin": "customers:9000",
49 | "destination": "*:**"
50 | }
51 | },
52 | {
53 | "timestamp": "2015-11-26T10:24:41.862+0000",
54 | "info": {
55 | "signal": "spring.cloud.bus.ack",
56 | "type": "RefreshRemoteApplicationEvent",
57 | "id": "c4d374b7-58ea-4928-a312-31984def293b",
58 | "origin": "customers:9000",
59 | "destination": "*:**"
60 | }
61 | }
62 | ----
63 |
64 | The preceding trace shows that a `RefreshRemoteApplicationEvent` was sent from
65 | `customers:9000`, broadcast to all services, and received (acked) by `customers:9000` and
66 | `stores:8081`.
67 |
68 | To handle the ack signals yourself, you could add an `@EventListener` for the
69 | `AckRemoteApplicationEvent` and `SentApplicationEvent` types to your app (and enable
70 | tracing). Alternatively, you could tap into the `TraceRepository` and mine the data from
71 | there.
72 |
73 | NOTE: Any Bus application can trace acks. However, sometimes, it is
74 | useful to do this in a central service that can do more complex
75 | queries on the data or forward it to a specialized tracing service.
76 |
77 |
--------------------------------------------------------------------------------
/docs/modules/ROOT/pages/spring-cloud-bus/custom-events.adoc:
--------------------------------------------------------------------------------
1 | [[custom-events]]
2 | = Custom Events
3 | :page-section-summary-toc: 1
4 |
5 | [[broadcasting-your-own-events]]
6 | == Broadcasting Your Own Events
7 |
8 | The Bus can carry any event of type `RemoteApplicationEvent`. The default transport is
9 | JSON, and the deserializer needs to know which types are going to be used ahead of time.
10 | To register a new type, you must put it in a subpackage of
11 | `org.springframework.cloud.bus.event`.
12 |
13 | To customise the event name, you can use `@JsonTypeName` on your custom class or rely on
14 | the default strategy, which is to use the simple name of the class.
15 |
16 | NOTE: Both the producer and the consumer need access to the class definition.
17 |
18 | [[registering-events-in-custom-packages]]
19 | === Registering events in custom packages
20 |
21 | If you cannot or do not want to use a subpackage of `org.springframework.cloud.bus.event`
22 | for your custom events, you must specify which packages to scan for events of type
23 | `RemoteApplicationEvent` by using the `@RemoteApplicationEventScan` annotation. Packages
24 | specified with `@RemoteApplicationEventScan` include subpackages.
25 |
26 | For example, consider the following custom event, called `MyEvent`:
27 |
28 | [source,java]
29 | ----
30 | package com.acme;
31 |
32 | public class MyEvent extends RemoteApplicationEvent {
33 | ...
34 | }
35 | ----
36 |
37 | You can register that event with the deserializer in the following way:
38 |
39 | [source,java]
40 | ----
41 | package com.acme;
42 |
43 | @Configuration
44 | @RemoteApplicationEventScan
45 | public class BusConfiguration {
46 | ...
47 | }
48 | ----
49 |
50 | Without specifying a value, the package of the class where `@RemoteApplicationEventScan`
51 | is used is registered. In this example, `com.acme` is registered by using the package of
52 | `BusConfiguration`.
53 |
54 | You can also explicitly specify the packages to scan by using the `value`, `basePackages`
55 | or `basePackageClasses` properties on `@RemoteApplicationEventScan`, as shown in the
56 | following example:
57 |
58 | [source,java]
59 | ----
60 | package com.acme;
61 |
62 | @Configuration
63 | //@RemoteApplicationEventScan({"com.acme", "foo.bar"})
64 | //@RemoteApplicationEventScan(basePackages = {"com.acme", "foo.bar", "fizz.buzz"})
65 | @RemoteApplicationEventScan(basePackageClasses = BusConfiguration.class)
66 | public class BusConfiguration {
67 | ...
68 | }
69 | ----
70 |
71 | All of the preceding examples of `@RemoteApplicationEventScan` are equivalent, in that the
72 | `com.acme` package is registered by explicitly specifying the packages on
73 | `@RemoteApplicationEventScan`.
74 |
75 | NOTE: You can specify multiple base packages to scan.
76 |
77 |
--------------------------------------------------------------------------------
/docs/modules/ROOT/partials/_configprops.adoc:
--------------------------------------------------------------------------------
1 | |===
2 | |Name | Default | Description
3 |
4 | |spring.cloud.bus.ack.destination-service | | Service that wants to listen to acks. By default null (meaning all services).
5 | |spring.cloud.bus.ack.enabled | `+++true+++` | Flag to switch off acks (default on).
6 | |spring.cloud.bus.content-type | | The bus mime-type.
7 | |spring.cloud.bus.destination | | Name of Spring Cloud Stream destination for messages.
8 | |spring.cloud.bus.enabled | `+++true+++` | Flag to indicate that the bus is enabled.
9 | |spring.cloud.bus.env.enabled | `+++true+++` | Flag to switch off environment change events (default on).
10 | |spring.cloud.bus.id | `+++application+++` | The identifier for this application instance.
11 | |spring.cloud.bus.refresh.enabled | `+++true+++` | Flag to switch off refresh events (default on).
12 | |spring.cloud.bus.shutdown.enabled | `+++true+++` | Flag to switch off shutdown events (default on).
13 | |spring.cloud.bus.trace.enabled | `+++false+++` | Flag to switch on tracing of acks (default off).
14 |
15 | |===
--------------------------------------------------------------------------------
/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "antora": "3.2.0-alpha.4",
4 | "@antora/atlas-extension": "1.0.0-alpha.2",
5 | "@antora/collector-extension": "1.0.0-alpha.3",
6 | "@asciidoctor/tabs": "1.0.0-beta.6",
7 | "@springio/antora-extensions": "1.11.1",
8 | "@springio/asciidoctor-extensions": "1.0.0-alpha.10"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/docs/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 | org.springframework.cloud
7 | spring-cloud-bus-docs
8 |
9 | org.springframework.cloud
10 | spring-cloud-bus-parent
11 | 5.0.0-SNAPSHOT
12 |
13 | jar
14 | Spring Cloud Bus Docs
15 | Spring Cloud Bus Docs
16 |
17 | spring-cloud-bus
18 | ${basedir}/..
19 | spring.cloud.bus.*
20 |
21 | none
22 |
23 |
24 | src/main/asciidoc
25 |
26 |
27 |
28 | enable-configuration-properties
29 |
30 |
31 | !disableConfigurationProperties
32 |
33 |
34 |
35 |
36 | ${project.groupId}
37 | spring-cloud-starter-bus-amqp
38 |
39 |
40 | ${project.groupId}
41 | spring-cloud-starter-bus-kafka
42 |
43 |
44 |
45 |
46 | docs
47 |
48 |
49 |
50 | src/main/antora/resources/antora-resources
51 | true
52 |
53 |
54 |
55 |
56 | pl.project13.maven
57 | git-commit-id-plugin
58 |
59 |
60 | org.apache.maven.plugins
61 | maven-dependency-plugin
62 |
63 |
64 | org.codehaus.mojo
65 | exec-maven-plugin
66 |
67 |
68 | io.spring.maven.antora
69 | antora-component-version-maven-plugin
70 |
71 |
72 | org.antora
73 | antora-maven-plugin
74 |
75 |
76 | org.apache.maven.plugins
77 | maven-antrun-plugin
78 |
79 |
80 | maven-deploy-plugin
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/docs/src/main/antora/resources/antora-resources/antora.yml:
--------------------------------------------------------------------------------
1 | version: @antora-component.version@
2 | prerelease: @antora-component.prerelease@
3 |
4 | asciidoc:
5 | attributes:
6 | attribute-missing: 'warn'
7 | chomp: 'all'
8 | project-root: @maven.multiModuleProjectDirectory@
9 | github-repo: @docs.main@
10 | github-raw: https://raw.githubusercontent.com/spring-cloud/@docs.main@/@github-tag@
11 | github-code: https://github.com/spring-cloud/@docs.main@/tree/@github-tag@
12 | github-issues: https://github.com/spring-cloud/@docs.main@/issues/
13 | github-wiki: https://github.com/spring-cloud/@docs.main@/wiki
14 | spring-cloud-version: @project.version@
15 | github-tag: @github-tag@
16 | version-type: @version-type@
17 | docs-url: https://docs.spring.io/@docs.main@/docs/@project.version@
18 | raw-docs-url: https://raw.githubusercontent.com/spring-cloud/@docs.main@/@github-tag@
19 | project-version: @project.version@
20 | project-name: @docs.main@
21 |
--------------------------------------------------------------------------------
/docs/src/main/asciidoc/README.adoc:
--------------------------------------------------------------------------------
1 | [[spring-cloud-bus]]
2 | = Spring Cloud Bus
3 | :page-section-summary-toc: 1
4 |
5 |
6 | [[quick-start]]
7 | == Quick Start
8 |
9 |
10 | [[building]]
11 | == Building
12 |
13 | include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/main/docs/modules/ROOT/partials/building.adoc[]
14 |
15 | [[contributing]]
16 | == Contributing
17 |
18 | include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/main/docs/modules/ROOT/partials/contributing.adoc[]
19 |
--------------------------------------------------------------------------------
/docs/src/main/asciidoc/sagan-index.adoc:
--------------------------------------------------------------------------------
1 |
2 | Spring Cloud Bus links nodes of a distributed system with a lightweight message broker. This can then be used to broadcast state changes (e.g. configuration changes) or other management instructions. AMQP and Kafka broker implementations are included with the project. Alternatively, any link:https://spring.io/projects/spring-cloud-stream[Spring Cloud Stream] binder found on the classpath will work out of the box as a transport.
3 |
4 | ## Getting Started
5 | As long as Spring Cloud Bus AMQP and RabbitMQ are on the
6 | classpath any Spring Boot application will try to contact a RabbitMQ
7 | server on `localhost:5672` (the default value of
8 | `spring.rabbitmq.addresses`):
9 |
10 | ```java
11 | @Configuration
12 | @EnableAutoConfiguration
13 | @RestController
14 | public class Application {
15 |
16 | @RequestMapping("/")
17 | public String home() {
18 | return "Hello World";
19 | }
20 |
21 | public static void main(String[] args) {
22 | SpringApplication.run(Application.class, args);
23 | }
24 |
25 | }
26 | ```
27 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | spring-cloud-bus-parent
8 | 5.0.0-SNAPSHOT
9 | pom
10 |
11 | spring-cloud-bus-parent
12 | Spring Cloud Bus Parent
13 |
14 |
15 | org.springframework.cloud
16 | spring-cloud-build
17 | 5.0.0-SNAPSHOT
18 |
19 |
20 |
21 |
22 | spring-cloud-bus-dependencies
23 | spring-cloud-bus
24 | spring-cloud-bus-tests
25 | spring-cloud-starter-bus-amqp
26 | spring-cloud-starter-bus-kafka
27 | spring-cloud-starter-bus-stream
28 | docs
29 |
30 |
31 |
32 | 5.0.0-SNAPSHOT
33 | 4.3.1-SNAPSHOT
34 | 4.3.1-SNAPSHOT
35 | bus
36 |
37 |
38 |
39 |
40 |
41 | org.codehaus.mojo
42 | flatten-maven-plugin
43 |
44 |
45 | org.apache.maven.plugins
46 | maven-checkstyle-plugin
47 |
48 |
49 | io.spring.javaformat
50 | spring-javaformat-maven-plugin
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | org.apache.maven.plugins
59 | maven-checkstyle-plugin
60 |
61 |
62 |
63 |
64 |
65 |
66 | spring
67 |
68 |
69 | spring-snapshots
70 | Spring Snapshots
71 | https://repo.spring.io/snapshot
72 |
73 | true
74 |
75 |
76 | false
77 |
78 |
79 |
80 | spring-milestones
81 | Spring Milestones
82 | https://repo.spring.io/milestone
83 |
84 | false
85 |
86 |
87 |
88 | spring-releases
89 | Spring Releases
90 | https://repo.spring.io/release
91 |
92 | false
93 |
94 |
95 |
96 |
97 |
98 | spring-snapshots
99 | Spring Snapshots
100 | https://repo.spring.io/snapshot
101 |
102 | true
103 |
104 |
105 | false
106 |
107 |
108 |
109 | spring-milestones
110 | Spring Milestones
111 | https://repo.spring.io/milestone
112 |
113 | false
114 |
115 |
116 |
117 | spring-releases
118 | Spring Releases
119 | https://repo.spring.io/release
120 |
121 | false
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | org.springframework.cloud
131 | spring-cloud-bus-dependencies
132 | ${project.version}
133 | pom
134 | import
135 |
136 |
137 | org.springframework.cloud
138 | spring-cloud-commons-dependencies
139 | ${spring-cloud-commons.version}
140 | pom
141 | import
142 |
143 |
144 | org.springframework.cloud
145 | spring-cloud-test-support
146 | ${spring-cloud-commons.version}
147 |
148 |
149 | org.springframework.cloud
150 | spring-cloud-stream
151 | ${spring-cloud-stream.version}
152 |
153 |
154 | org.springframework.cloud
155 | spring-cloud-stream-dependencies
156 | ${spring-cloud-stream.version}
157 | pom
158 | import
159 |
160 |
161 | org.springframework.cloud
162 | spring-cloud-function-dependencies
163 | ${spring-cloud-function.version}
164 | pom
165 | import
166 |
167 |
168 | org.springframework.cloud
169 | spring-cloud-function-rsocket
170 | ${spring-cloud-function.version}
171 |
172 |
173 |
174 |
175 |
176 | https://github.com/spring-cloud/spring-cloud-bus
177 | scm:git:git://github.com/spring-cloud/spring-cloud-bus.git
178 |
179 |
180 | scm:git:ssh://git@github.com/spring-cloud/spring-cloud-bus.git
181 |
182 | HEAD
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/spring-cloud-bus-dependencies/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | spring-cloud-dependencies-parent
8 | org.springframework.cloud
9 | 5.0.0-SNAPSHOT
10 |
11 |
12 | spring-cloud-bus-dependencies
13 | 5.0.0-SNAPSHOT
14 | pom
15 | spring-cloud-bus-dependencies
16 | Spring Cloud Bus Dependencies
17 |
18 |
19 |
20 | org.springframework.cloud
21 | spring-cloud-starter-bus-amqp
22 | ${project.version}
23 |
24 |
25 | org.springframework.cloud
26 | spring-cloud-starter-bus-kafka
27 | ${project.version}
28 |
29 |
30 | org.springframework.cloud
31 | spring-cloud-starter-bus-stream
32 | ${project.version}
33 |
34 |
35 | org.springframework.cloud
36 | spring-cloud-bus
37 | ${project.version}
38 |
39 |
40 |
41 |
42 |
43 | spring
44 |
45 |
46 | spring-snapshots
47 | Spring Snapshots
48 | https://repo.spring.io/snapshot
49 |
50 | true
51 |
52 |
53 | false
54 |
55 |
56 |
57 | spring-milestones
58 | Spring Milestones
59 | https://repo.spring.io/milestone
60 |
61 | false
62 |
63 |
64 |
65 | spring-releases
66 | Spring Releases
67 | https://repo.spring.io/release
68 |
69 | false
70 |
71 |
72 |
73 |
74 |
75 | spring-snapshots
76 | Spring Snapshots
77 | https://repo.spring.io/snapshot
78 |
79 | true
80 |
81 |
82 | false
83 |
84 |
85 |
86 | spring-milestones
87 | Spring Milestones
88 | https://repo.spring.io/milestone
89 |
90 | false
91 |
92 |
93 |
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/spring-cloud-bus-tests/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | spring-cloud-bus-tests
8 | jar
9 |
10 | spring-cloud-bus-tests
11 | Spring Cloud Bus Tests
12 |
13 |
14 | org.springframework.cloud
15 | spring-cloud-bus-parent
16 | 5.0.0-SNAPSHOT
17 | ..
18 |
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-web
24 | test
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-webflux
29 | test
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-actuator
34 | test
35 |
36 |
37 | org.springframework.cloud
38 | spring-cloud-starter-bus-amqp
39 | test
40 |
41 |
42 | org.springframework.boot
43 | spring-boot-starter-test
44 | test
45 |
46 |
47 | org.springframework.boot
48 | spring-boot-testcontainers
49 | test
50 |
51 |
52 | org.testcontainers
53 | junit-jupiter
54 | test
55 |
56 |
57 | org.testcontainers
58 | rabbitmq
59 | test
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/spring-cloud-bus-tests/src/test/java/org/springframework/cloud/bus/BusAmqpIntegrationTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015-2020 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import java.util.HashMap;
20 | import java.util.concurrent.CountDownLatch;
21 | import java.util.concurrent.TimeUnit;
22 |
23 | import org.junit.jupiter.api.AfterAll;
24 | import org.junit.jupiter.api.BeforeAll;
25 | import org.junit.jupiter.api.Test;
26 | import org.testcontainers.containers.RabbitMQContainer;
27 | import org.testcontainers.junit.jupiter.Container;
28 | import org.testcontainers.junit.jupiter.Testcontainers;
29 |
30 | import org.springframework.beans.factory.annotation.Autowired;
31 | import org.springframework.boot.SpringBootConfiguration;
32 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
33 | import org.springframework.boot.builder.SpringApplicationBuilder;
34 | import org.springframework.boot.test.context.SpringBootTest;
35 | import org.springframework.cloud.bus.event.EnvironmentChangeRemoteApplicationEvent;
36 | import org.springframework.cloud.stream.binder.ProducerProperties;
37 | import org.springframework.cloud.stream.config.BindingServiceProperties;
38 | import org.springframework.context.ApplicationListener;
39 | import org.springframework.context.ConfigurableApplicationContext;
40 | import org.springframework.test.context.DynamicPropertyRegistry;
41 | import org.springframework.test.context.DynamicPropertySource;
42 | import org.springframework.test.web.reactive.server.WebTestClient;
43 |
44 | import static org.assertj.core.api.Assertions.assertThat;
45 | import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
46 |
47 | @SpringBootTest(webEnvironment = RANDOM_PORT, properties = { "management.endpoints.web.exposure.include=*",
48 | "spring.cloud.stream.bindings.springCloudBusOutput.producer.errorChannelEnabled=true",
49 | "logging.level.org.springframework.cloud.bus=TRACE", "spring.cloud.bus.id=app:1",
50 | "spring.autoconfigure.exclude=org.springframework.cloud.stream.test.binder.TestSupportBinderAutoConfiguration" })
51 | @Testcontainers
52 | public class BusAmqpIntegrationTests {
53 |
54 | @Container
55 | private static final RabbitMQContainer rabbitMQContainer = new RabbitMQContainer(
56 | "rabbitmq:3.7.25-management-alpine");
57 |
58 | private static ConfigurableApplicationContext context;
59 |
60 | @Autowired
61 | private BindingServiceProperties bindingServiceProperties;
62 |
63 | @DynamicPropertySource
64 | static void properties(DynamicPropertyRegistry registry) {
65 | registry.add("spring.rabbitmq.host", rabbitMQContainer::getHost);
66 | registry.add("spring.rabbitmq.port", rabbitMQContainer::getAmqpPort);
67 | }
68 |
69 | @BeforeAll
70 | static void before() {
71 | context = new SpringApplicationBuilder(TestConfig.class).properties("server.port=0",
72 | "spring.rabbitmq.host=" + rabbitMQContainer.getHost(),
73 | "spring.rabbitmq.port=" + rabbitMQContainer.getAmqpPort(),
74 | "management.endpoints.web.exposure.include=*", "spring.cloud.bus.id=app:2",
75 | "spring.autoconfigure.exclude=org.springframework.cloud.stream.test.binder.TestSupportBinderAutoConfiguration")
76 | .run();
77 | }
78 |
79 | @AfterAll
80 | static void after() {
81 | if (context != null) {
82 | context.close();
83 | }
84 | }
85 |
86 | @Test
87 | void remoteEventsAreSentViaAmqp(@Autowired WebTestClient client, @Autowired TestConfig testConfig)
88 | throws InterruptedException {
89 | assertThat(rabbitMQContainer.isRunning());
90 | HashMap map = new HashMap<>();
91 | map.put("name", "foo");
92 | map.put("value", "bar");
93 | client.post().uri("/actuator/busenv").bodyValue(map).exchange().expectStatus().is2xxSuccessful();
94 | TestConfig remoteTestConfig = context.getBean(TestConfig.class);
95 | assertThat(remoteTestConfig.latch.await(5, TimeUnit.SECONDS)).isTrue();
96 | assertThat(testConfig.latch.await(5, TimeUnit.SECONDS)).isTrue();
97 | ProducerProperties producerProperties = bindingServiceProperties.getProducerProperties(BusConstants.OUTPUT);
98 | assertThat(producerProperties.isErrorChannelEnabled()).isTrue();
99 | }
100 |
101 | @SpringBootConfiguration
102 | @EnableAutoConfiguration
103 | static class TestConfig implements ApplicationListener {
104 |
105 | CountDownLatch latch = new CountDownLatch(1);
106 |
107 | @Override
108 | public void onApplicationEvent(EnvironmentChangeRemoteApplicationEvent event) {
109 | latch.countDown();
110 | }
111 |
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/spring-cloud-bus-tests/src/test/java/org/springframework/cloud/bus/BusJmxEndpointTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.junit.jupiter.api.Test;
20 |
21 | import org.springframework.beans.factory.annotation.Autowired;
22 | import org.springframework.boot.SpringBootConfiguration;
23 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
24 | import org.springframework.boot.test.context.SpringBootTest;
25 | import org.springframework.cloud.bus.endpoint.EnvironmentBusEndpoint;
26 | import org.springframework.cloud.bus.endpoint.RefreshBusEndpoint;
27 |
28 | import static org.assertj.core.api.Assertions.assertThat;
29 |
30 | @SpringBootTest(properties = { "spring.jmx.enabled=true", "endpoints.default.jmx.enabled=true",
31 | "management.endpoints..jmx.exposure.include=busrefresh,busenv", "debug=true" })
32 | public class BusJmxEndpointTests {
33 |
34 | @Autowired(required = false)
35 | private RefreshBusEndpoint refreshBusEndpoint;
36 |
37 | @Autowired(required = false)
38 | private EnvironmentBusEndpoint environmentBusEndpoint;
39 |
40 | @Test
41 | public void contextLoads() {
42 | assertThat(this.refreshBusEndpoint).isNotNull();
43 | assertThat(this.environmentBusEndpoint).isNotNull();
44 | }
45 |
46 | @SpringBootConfiguration
47 | @EnableAutoConfiguration
48 | protected static class TestConfig {
49 |
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/spring-cloud-bus-tests/src/test/java/org/springframework/cloud/bus/ShutdownListenerIntegrationTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2024 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import java.util.concurrent.CountDownLatch;
20 |
21 | import org.junit.jupiter.api.AfterAll;
22 | import org.junit.jupiter.api.BeforeAll;
23 | import org.junit.jupiter.api.Test;
24 | import org.testcontainers.containers.RabbitMQContainer;
25 | import org.testcontainers.junit.jupiter.Container;
26 | import org.testcontainers.junit.jupiter.Testcontainers;
27 |
28 | import org.springframework.beans.factory.annotation.Autowired;
29 | import org.springframework.boot.SpringBootConfiguration;
30 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
31 | import org.springframework.boot.builder.SpringApplicationBuilder;
32 | import org.springframework.boot.test.context.SpringBootTest;
33 | import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
34 | import org.springframework.cloud.bus.event.EnvironmentChangeRemoteApplicationEvent;
35 | import org.springframework.context.ApplicationListener;
36 | import org.springframework.context.ConfigurableApplicationContext;
37 | import org.springframework.test.web.reactive.server.WebTestClient;
38 |
39 | import static org.assertj.core.api.Assertions.assertThat;
40 | import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
41 |
42 | /**
43 | * @author Ryan Baxter
44 | */
45 | @SpringBootTest(webEnvironment = RANDOM_PORT,
46 | properties = { "management.endpoints.web.exposure.include=*",
47 | "spring.cloud.stream.bindings.springCloudBusOutput.producer.errorChannelEnabled=true",
48 | "logging.level.org.springframework.cloud.bus=TRACE", "spring.cloud.bus.id=app:1" })
49 | @Testcontainers
50 | public class ShutdownListenerIntegrationTests {
51 |
52 | private static ConfigurableApplicationContext context;
53 |
54 | @Container
55 | @ServiceConnection
56 | private static final RabbitMQContainer rabbitMQContainer = new RabbitMQContainer("rabbitmq:4.0-management");
57 |
58 | @BeforeAll
59 | static void before() {
60 | context = new SpringApplicationBuilder(TestConfig.class)
61 | .properties("server.port=0", "spring.rabbitmq.host=" + rabbitMQContainer.getHost(),
62 | "spring.rabbitmq.port=" + rabbitMQContainer.getAmqpPort(),
63 | "management.endpoints.web.exposure.include=*", "spring.cloud.bus.id=app:2", "debug=true")
64 | .run();
65 | }
66 |
67 | @AfterAll
68 | static void after() {
69 | if (context != null) {
70 | context.close();
71 | }
72 | }
73 |
74 | @Test
75 | void testShutdown(@Autowired WebTestClient client) {
76 | assertThat(rabbitMQContainer.isRunning());
77 | client.post().uri("/actuator/busshutdown/app:2").exchange().expectStatus().is2xxSuccessful();
78 | assertThat(context.isClosed());
79 | }
80 |
81 | @SpringBootConfiguration
82 | @EnableAutoConfiguration
83 | static class TestConfig implements ApplicationListener {
84 |
85 | CountDownLatch latch = new CountDownLatch(1);
86 |
87 | @Override
88 | public void onApplicationEvent(EnvironmentChangeRemoteApplicationEvent event) {
89 | latch.countDown();
90 | }
91 |
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/spring-cloud-bus-tests/src/test/java/org/springframework/cloud/bus/jackson/BusJacksonIntegrationTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.jackson;
18 |
19 | import java.util.Collection;
20 | import java.util.Date;
21 | import java.util.HashMap;
22 | import java.util.List;
23 | import java.util.Map;
24 | import java.util.Set;
25 | import java.util.concurrent.ConcurrentHashMap;
26 |
27 | import com.fasterxml.jackson.databind.SerializationFeature;
28 | import org.junit.jupiter.api.Test;
29 |
30 | import org.springframework.beans.factory.annotation.Autowired;
31 | import org.springframework.boot.SpringBootConfiguration;
32 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
33 | import org.springframework.boot.test.context.SpringBootTest;
34 | import org.springframework.boot.test.web.client.TestRestTemplate;
35 | import org.springframework.boot.test.web.server.LocalServerPort;
36 | import org.springframework.cloud.bus.ServiceMatcher;
37 | import org.springframework.cloud.bus.event.RemoteApplicationEvent;
38 | import org.springframework.context.ApplicationEventPublisher;
39 | import org.springframework.context.event.EventListener;
40 | import org.springframework.http.HttpStatus;
41 | import org.springframework.http.ResponseEntity;
42 | import org.springframework.test.annotation.DirtiesContext;
43 | import org.springframework.web.bind.annotation.GetMapping;
44 | import org.springframework.web.bind.annotation.PathVariable;
45 | import org.springframework.web.bind.annotation.PutMapping;
46 | import org.springframework.web.bind.annotation.RestController;
47 |
48 | import static org.assertj.core.api.Assertions.assertThat;
49 | import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
50 |
51 | @SpringBootTest(properties = "spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS:true",
52 | webEnvironment = RANDOM_PORT)
53 | @DirtiesContext
54 | public class BusJacksonIntegrationTests {
55 |
56 | @LocalServerPort
57 | private int port;
58 |
59 | @Autowired
60 | private TestRestTemplate rest;
61 |
62 | @Autowired
63 | private BusJacksonMessageConverter converter;
64 |
65 | @Test
66 | @SuppressWarnings("unchecked")
67 | public void testCustomEventSerializes() {
68 | assertThat(this.converter.isMapperCreated()).isFalse();
69 |
70 | // set by configuration
71 | assertThat(this.converter.getMapper()
72 | .getSerializationConfig()
73 | .isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)).isTrue();
74 |
75 | Map map = this.rest.getForObject("http://localhost:" + this.port + "/date", Map.class);
76 | assertThat(map).containsOnlyKeys("date");
77 | assertThat(map.get("date")).isInstanceOf(Long.class);
78 |
79 | this.rest.put("http://localhost:" + this.port + "/names" + "/foo", null);
80 | this.rest.put("http://localhost:" + this.port + "/names" + "/bar", null);
81 |
82 | ResponseEntity response = this.rest.getForEntity("http://localhost:" + this.port + "/names", List.class);
83 | assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
84 | assertThat(response.getBody()).contains("foo", "bar");
85 | }
86 |
87 | public static class NameEvent extends RemoteApplicationEvent {
88 |
89 | private String name;
90 |
91 | protected NameEvent() {
92 | }
93 |
94 | public NameEvent(Object source, String originService, String name) {
95 | super(source, originService);
96 | this.name = name;
97 | }
98 |
99 | public String getName() {
100 | return this.name;
101 | }
102 |
103 | public void setName(String name) {
104 | this.name = name;
105 | }
106 |
107 | }
108 |
109 | @RestController
110 | @EnableAutoConfiguration
111 | @SpringBootConfiguration
112 | @RemoteApplicationEventScan
113 | protected static class Config {
114 |
115 | final private Set names = ConcurrentHashMap.newKeySet();
116 |
117 | @Autowired
118 | private ServiceMatcher busServiceMatcher;
119 |
120 | @Autowired
121 | private ApplicationEventPublisher publisher;
122 |
123 | @GetMapping("/names")
124 | public Collection names() {
125 | return this.names;
126 | }
127 |
128 | @PutMapping("/names/{name}")
129 | public void sayName(@PathVariable String name) {
130 | this.names.add(name);
131 | this.publisher.publishEvent(new NameEvent(this, this.busServiceMatcher.getBusId(), name));
132 | }
133 |
134 | @GetMapping("/date")
135 | public Map testTimeJsonSerialization() {
136 | Map map = new HashMap<>();
137 | map.put("date", new Date());
138 | return map;
139 | }
140 |
141 | @EventListener
142 | public void handleNameSaid(NameEvent event) {
143 | this.names.add(event.getName());
144 | }
145 |
146 | }
147 |
148 | }
149 |
--------------------------------------------------------------------------------
/spring-cloud-bus/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | spring-cloud-bus
8 | jar
9 |
10 | spring-cloud-bus
11 | Spring Cloud Bus
12 |
13 |
14 | org.springframework.cloud
15 | spring-cloud-bus-parent
16 | 5.0.0-SNAPSHOT
17 | ..
18 |
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-configuration-processor
24 | true
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-actuator
29 | true
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-web
34 | true
35 |
36 |
37 | org.springframework.cloud
38 | spring-cloud-starter
39 |
40 |
41 | org.springframework.cloud
42 | spring-cloud-stream
43 | true
44 |
45 |
46 | org.springframework.integration
47 | spring-integration-core
48 |
49 |
50 | com.fasterxml.jackson.dataformat
51 | jackson-dataformat-cbor
52 | true
53 |
54 |
55 | org.springframework.boot
56 | spring-boot-autoconfigure-processor
57 | true
58 |
59 |
60 | org.springframework.boot
61 | spring-boot-starter-test
62 | test
63 |
64 |
65 | org.junit.vintage
66 | junit-vintage-engine
67 | test
68 |
69 |
70 | org.springframework.cloud
71 | spring-cloud-test-support
72 | test
73 |
74 |
75 | org.springframework.cloud
76 | spring-cloud-stream-test-binder
77 | ${spring-cloud-stream.version}
78 | test
79 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/BusAutoConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.springframework.beans.factory.ObjectProvider;
20 | import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
21 | import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
22 | import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
23 | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
24 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
25 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
26 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
27 | import org.springframework.boot.context.properties.EnableConfigurationProperties;
28 | import org.springframework.cloud.bus.endpoint.EnvironmentBusEndpoint;
29 | import org.springframework.cloud.bus.event.Destination;
30 | import org.springframework.cloud.bus.event.EnvironmentChangeListener;
31 | import org.springframework.cloud.bus.event.PathDestinationFactory;
32 | import org.springframework.cloud.bus.event.TraceListener;
33 | import org.springframework.cloud.context.environment.EnvironmentManager;
34 | import org.springframework.context.ApplicationEventPublisher;
35 | import org.springframework.context.annotation.Bean;
36 | import org.springframework.context.annotation.Configuration;
37 |
38 | import static org.springframework.cloud.bus.BusConstants.BUS_CONSUMER;
39 |
40 | /**
41 | * @author Spencer Gibb
42 | * @author Dave Syer
43 | */
44 | @Configuration(proxyBeanMethods = false)
45 | @ConditionalOnBusEnabled
46 | @EnableConfigurationProperties(BusProperties.class)
47 | public class BusAutoConfiguration {
48 |
49 | @Bean
50 | @ConditionalOnMissingBean(Destination.Factory.class)
51 | public PathDestinationFactory pathDestinationFactory() {
52 | return new PathDestinationFactory();
53 | }
54 |
55 | @Bean
56 | @ConditionalOnMissingBean
57 | public RemoteApplicationEventListener busRemoteApplicationEventListener(ServiceMatcher serviceMatcher,
58 | BusBridge busBridge) {
59 | return new RemoteApplicationEventListener(serviceMatcher, busBridge);
60 | }
61 |
62 | @Bean
63 | @ConditionalOnMissingBean(name = BUS_CONSUMER)
64 | public BusConsumer busConsumer(ApplicationEventPublisher applicationEventPublisher, ServiceMatcher serviceMatcher,
65 | ObjectProvider busBridge, BusProperties properties, Destination.Factory destinationFactory) {
66 | return new BusConsumer(applicationEventPublisher, serviceMatcher, busBridge, properties, destinationFactory);
67 | }
68 |
69 | @Configuration(proxyBeanMethods = false)
70 | @ConditionalOnClass({ Endpoint.class })
71 | @ConditionalOnBean(HttpExchangeRepository.class)
72 | @ConditionalOnProperty(BusProperties.PREFIX + ".trace.enabled")
73 | protected static class BusAckTraceConfiguration {
74 |
75 | @Bean
76 | @ConditionalOnMissingBean
77 | public TraceListener ackTraceListener(HttpExchangeRepository repository) {
78 | return new TraceListener(repository);
79 | }
80 |
81 | }
82 |
83 | @Configuration(proxyBeanMethods = false)
84 | @ConditionalOnClass(EnvironmentManager.class)
85 | @ConditionalOnBean(EnvironmentManager.class)
86 | protected static class BusEnvironmentConfiguration {
87 |
88 | @Bean
89 | @ConditionalOnProperty(value = "spring.cloud.bus.env.enabled", matchIfMissing = true)
90 | public EnvironmentChangeListener environmentChangeListener() {
91 | return new EnvironmentChangeListener();
92 | }
93 |
94 | @Configuration(proxyBeanMethods = false)
95 | @ConditionalOnClass(Endpoint.class)
96 | protected static class EnvironmentBusEndpointConfiguration {
97 |
98 | @Bean
99 | @ConditionalOnAvailableEndpoint
100 | public EnvironmentBusEndpoint environmentBusEndpoint(ApplicationEventPublisher publisher, BusProperties bus,
101 | Destination.Factory destinationFactory) {
102 | return new EnvironmentBusEndpoint(publisher, bus.getId(), destinationFactory);
103 | }
104 |
105 | }
106 |
107 | }
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/BusBridge.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015-2020 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.springframework.cloud.bus.event.RemoteApplicationEvent;
20 |
21 | public interface BusBridge {
22 |
23 | void send(RemoteApplicationEvent event);
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/BusConstants.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | /**
20 | * @author Dave Syer
21 | *
22 | */
23 | public abstract class BusConstants {
24 |
25 | /**
26 | * Name of the input channel for Spring Cloud Bus.
27 | */
28 | public static final String INPUT = "springCloudBusInput";
29 |
30 | /**
31 | * Name of the output channel for Spring Cloud Bus.
32 | */
33 | public static final String OUTPUT = "springCloudBusOutput";
34 |
35 | /**
36 | * Name of the binding destination for Spring Cloud Bus.
37 | */
38 | public static final String DESTINATION = "springCloudBus";
39 |
40 | /**
41 | * Name of the Spring Cloud Bus function.
42 | */
43 | public static final String BUS_CONSUMER = "busConsumer";
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/BusConsumer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015-2020 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import java.util.function.Consumer;
20 |
21 | import org.apache.commons.logging.Log;
22 | import org.apache.commons.logging.LogFactory;
23 |
24 | import org.springframework.beans.factory.ObjectProvider;
25 | import org.springframework.cloud.bus.event.AckRemoteApplicationEvent;
26 | import org.springframework.cloud.bus.event.Destination;
27 | import org.springframework.cloud.bus.event.RemoteApplicationEvent;
28 | import org.springframework.cloud.bus.event.SentApplicationEvent;
29 | import org.springframework.context.ApplicationEventPublisher;
30 |
31 | public class BusConsumer implements Consumer {
32 |
33 | private final Log log = LogFactory.getLog(getClass());
34 |
35 | private final ApplicationEventPublisher publisher;
36 |
37 | private final ServiceMatcher serviceMatcher;
38 |
39 | private final ObjectProvider busBridge;
40 |
41 | private final BusProperties properties;
42 |
43 | private final Destination.Factory destinationFactory;
44 |
45 | public BusConsumer(ApplicationEventPublisher publisher, ServiceMatcher serviceMatcher,
46 | ObjectProvider busBridge, BusProperties properties, Destination.Factory destinationFactory) {
47 | this.publisher = publisher;
48 | this.serviceMatcher = serviceMatcher;
49 | this.busBridge = busBridge;
50 | this.properties = properties;
51 | this.destinationFactory = destinationFactory;
52 | }
53 |
54 | @Override
55 | public void accept(RemoteApplicationEvent event) {
56 | if (event instanceof AckRemoteApplicationEvent) {
57 | if (this.properties.getTrace().isEnabled() && !this.serviceMatcher.isFromSelf(event)
58 | && this.publisher != null) {
59 | this.publisher.publishEvent(event);
60 | }
61 | // If it's an ACK we are finished processing at this point
62 | return;
63 | }
64 |
65 | if (log.isDebugEnabled()) {
66 | log.debug("Received remote event from bus: " + event);
67 | }
68 |
69 | if (this.serviceMatcher.isForSelf(event) && this.publisher != null) {
70 | if (!this.serviceMatcher.isFromSelf(event)) {
71 | this.publisher.publishEvent(event);
72 | }
73 | if (this.properties.getAck().isEnabled()) {
74 | AckRemoteApplicationEvent ack = new AckRemoteApplicationEvent(this, this.serviceMatcher.getBusId(),
75 | destinationFactory.getDestination(this.properties.getAck().getDestinationService()),
76 | event.getDestinationService(), event.getId(), event.getClass());
77 | this.busBridge.ifAvailable(bridge -> bridge.send(ack));
78 | this.publisher.publishEvent(ack);
79 | }
80 | }
81 | if (this.properties.getTrace().isEnabled() && this.publisher != null) {
82 | // We are set to register sent events so publish it for local consumption,
83 | // irrespective of the origin
84 | this.publisher.publishEvent(new SentApplicationEvent(this, event.getOriginService(),
85 | event.getDestinationService(), event.getId(), event.getClass()));
86 | }
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/BusEnvironmentPostProcessor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2022 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import java.util.HashMap;
20 | import java.util.Map;
21 |
22 | import org.springframework.boot.SpringApplication;
23 | import org.springframework.boot.env.EnvironmentPostProcessor;
24 | import org.springframework.cloud.commons.util.IdUtils;
25 | import org.springframework.cloud.function.context.FunctionProperties;
26 | import org.springframework.core.env.ConfigurableEnvironment;
27 | import org.springframework.core.env.MapPropertySource;
28 | import org.springframework.core.env.MutablePropertySources;
29 | import org.springframework.core.env.PropertySource;
30 | import org.springframework.util.StringUtils;
31 |
32 | import static org.springframework.cloud.bus.BusProperties.PREFIX;
33 |
34 | /**
35 | * {@link EnvironmentPostProcessor} that sets the default properties for the Bus.
36 | *
37 | * @author Dave Syer
38 | * @since 1.0.0
39 | */
40 | public class BusEnvironmentPostProcessor implements EnvironmentPostProcessor {
41 |
42 | static final String DEFAULTS_PROPERTY_SOURCE_NAME = "springCloudBusDefaultProperties";
43 |
44 | static final String OVERRIDES_PROPERTY_SOURCE_NAME = "springCloudBusOverridesProperties";
45 |
46 | private static final String FN_DEF_PROP = FunctionProperties.PREFIX + ".definition";
47 |
48 | @Override
49 | public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
50 | if (environment.containsProperty(ConditionalOnBusEnabled.SPRING_CLOUD_BUS_ENABLED)) {
51 | if (Boolean.FALSE.toString()
52 | .equalsIgnoreCase(environment.getProperty(ConditionalOnBusEnabled.SPRING_CLOUD_BUS_ENABLED))) {
53 | return;
54 | }
55 | }
56 | Map overrides = new HashMap<>();
57 | String definition = BusConstants.BUS_CONSUMER;
58 | if (environment.containsProperty(FN_DEF_PROP)) {
59 | String property = environment.getProperty(FN_DEF_PROP);
60 | if (property != null && property.contains(BusConstants.BUS_CONSUMER)) {
61 | // in the case that EnvironmentPostProcessor are run more than once.
62 | return;
63 | }
64 | definition = property + ";" + definition;
65 | }
66 | overrides.put(FN_DEF_PROP, definition);
67 | addOrReplace(environment.getPropertySources(), overrides, OVERRIDES_PROPERTY_SOURCE_NAME, true);
68 |
69 | Map defaults = new HashMap<>();
70 | defaults.put("spring.cloud.stream.function.bindings." + BusConstants.BUS_CONSUMER + "-in-0",
71 | BusConstants.INPUT);
72 | String destination = environment.getProperty(PREFIX + ".destination", BusConstants.DESTINATION);
73 | defaults.put("spring.cloud.stream.bindings." + BusConstants.INPUT + ".destination", destination);
74 | defaults.put("spring.cloud.stream.bindings." + BusConstants.OUTPUT + ".destination", destination);
75 | if (!environment.containsProperty(PREFIX + ".id")) {
76 | String unresolvedServiceId = IdUtils.getUnresolvedServiceId();
77 | if (StringUtils.hasText(environment.getProperty("spring.profiles.active"))) {
78 | unresolvedServiceId = IdUtils.getUnresolvedServiceIdWithActiveProfiles();
79 | }
80 | defaults.put(PREFIX + ".id", unresolvedServiceId);
81 | }
82 | addOrReplace(environment.getPropertySources(), defaults, DEFAULTS_PROPERTY_SOURCE_NAME, false);
83 | }
84 |
85 | public static void addOrReplace(MutablePropertySources propertySources, Map map,
86 | String propertySourceName, boolean first) {
87 | MapPropertySource target = null;
88 | if (propertySources.contains(propertySourceName)) {
89 | PropertySource> source = propertySources.get(propertySourceName);
90 | if (source instanceof MapPropertySource) {
91 | target = (MapPropertySource) source;
92 | for (String key : map.keySet()) {
93 | if (!target.containsProperty(key)) {
94 | target.getSource().put(key, map.get(key));
95 | }
96 | }
97 | }
98 | }
99 | if (target == null) {
100 | target = new MapPropertySource(propertySourceName, map);
101 | }
102 | if (!propertySources.contains(propertySourceName)) {
103 | if (first) {
104 | propertySources.addFirst(target);
105 | }
106 | else {
107 | propertySources.addLast(target);
108 | }
109 | }
110 | }
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/BusPathMatcher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import java.lang.annotation.Documented;
20 | import java.lang.annotation.ElementType;
21 | import java.lang.annotation.Inherited;
22 | import java.lang.annotation.Retention;
23 | import java.lang.annotation.RetentionPolicy;
24 | import java.lang.annotation.Target;
25 |
26 | import org.springframework.beans.factory.annotation.Qualifier;
27 |
28 | /**
29 | * Qualifier annotation for components to do with matching paths in the bus.
30 | *
31 | * @author Dave Syer
32 | *
33 | */
34 | @Qualifier
35 | @Target({ ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.PARAMETER })
36 | @Retention(RetentionPolicy.RUNTIME)
37 | @Inherited
38 | @Documented
39 | public @interface BusPathMatcher {
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/BusProperties.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.springframework.boot.context.properties.ConfigurationProperties;
20 | import org.springframework.core.style.ToStringCreator;
21 | import org.springframework.util.MimeType;
22 | import org.springframework.util.MimeTypeUtils;
23 |
24 | /**
25 | * @author Dave Syer
26 | *
27 | */
28 | @ConfigurationProperties(BusProperties.PREFIX)
29 | public class BusProperties {
30 |
31 | /**
32 | * Configuration prefix for spring cloud bus.
33 | */
34 | public static final String PREFIX = "spring.cloud.bus";
35 |
36 | /**
37 | * Properties related to acks.
38 | */
39 | private final Ack ack = new Ack();
40 |
41 | /**
42 | * Properties related to tracing of acks.
43 | */
44 | private final Trace trace = new Trace();
45 |
46 | /**
47 | * Name of Spring Cloud Stream destination for messages.
48 | */
49 | private String destination = BusConstants.DESTINATION;
50 |
51 | /**
52 | * The identifier for this application instance.
53 | */
54 | private String id = "application";
55 |
56 | /**
57 | * The bus mime-type.
58 | */
59 | private MimeType contentType = MimeTypeUtils.APPLICATION_JSON;
60 |
61 | /**
62 | * Flag to indicate that the bus is enabled.
63 | */
64 | private boolean enabled = true;
65 |
66 | public Ack getAck() {
67 | return this.ack;
68 | }
69 |
70 | public Trace getTrace() {
71 | return this.trace;
72 | }
73 |
74 | public String getDestination() {
75 | return this.destination;
76 | }
77 |
78 | public void setDestination(String destination) {
79 | this.destination = destination;
80 | }
81 |
82 | public boolean isEnabled() {
83 | return this.enabled;
84 | }
85 |
86 | public void setEnabled(boolean enabled) {
87 | this.enabled = enabled;
88 | }
89 |
90 | public String getId() {
91 | return this.id;
92 | }
93 |
94 | public void setId(String id) {
95 | this.id = id;
96 | }
97 |
98 | public MimeType getContentType() {
99 | return this.contentType;
100 | }
101 |
102 | public void setContentType(MimeType contentType) {
103 | this.contentType = contentType;
104 | }
105 |
106 | @Override
107 | public String toString() {
108 | return new ToStringCreator(this).append("ack", ack)
109 | .append("trace", trace)
110 | .append("destination", destination)
111 | .append("id", id)
112 | .append("contentType", contentType)
113 | .append("enabled", enabled)
114 | .toString();
115 |
116 | }
117 |
118 | /**
119 | * Spring Cloud Bus properties related to acknowledgments.
120 | */
121 | public static class Ack {
122 |
123 | /**
124 | * Flag to switch off acks (default on).
125 | */
126 | private boolean enabled = true;
127 |
128 | /**
129 | * Service that wants to listen to acks. By default null (meaning all services).
130 | */
131 | private String destinationService;
132 |
133 | public boolean isEnabled() {
134 | return this.enabled;
135 | }
136 |
137 | public void setEnabled(boolean enabled) {
138 | this.enabled = enabled;
139 | }
140 |
141 | public String getDestinationService() {
142 | return this.destinationService;
143 | }
144 |
145 | public void setDestinationService(String destinationService) {
146 | this.destinationService = destinationService;
147 | }
148 |
149 | @Override
150 | public String toString() {
151 | return new ToStringCreator(this).append("enabled", enabled)
152 | .append("destinationService", destinationService)
153 | .toString();
154 | }
155 |
156 | }
157 |
158 | /**
159 | * Spring Cloud Bus trace properties.
160 | */
161 | public static class Trace {
162 |
163 | /**
164 | * Flag to switch on tracing of acks (default off).
165 | */
166 | private boolean enabled = false;
167 |
168 | public boolean isEnabled() {
169 | return this.enabled;
170 | }
171 |
172 | public void setEnabled(boolean enabled) {
173 | this.enabled = enabled;
174 | }
175 |
176 | @Override
177 | public String toString() {
178 | return new ToStringCreator(this).append("enabled", enabled).toString();
179 | }
180 |
181 | }
182 |
183 | }
184 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/BusRefreshAutoConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
20 | import org.springframework.boot.autoconfigure.AutoConfigureAfter;
21 | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
22 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
23 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
24 | import org.springframework.cloud.bus.endpoint.RefreshBusEndpoint;
25 | import org.springframework.cloud.bus.event.Destination;
26 | import org.springframework.cloud.bus.event.RefreshListener;
27 | import org.springframework.cloud.context.refresh.ContextRefresher;
28 | import org.springframework.context.ApplicationEventPublisher;
29 | import org.springframework.context.annotation.Bean;
30 | import org.springframework.context.annotation.Configuration;
31 |
32 | /**
33 | * @author Ryan Baxter
34 | */
35 | @Configuration(proxyBeanMethods = false)
36 | @ConditionalOnBusEnabled
37 | @AutoConfigureAfter(name = { "org.springframework.cloud.autoconfigure.RefreshAutoConfiguration" })
38 | public class BusRefreshAutoConfiguration {
39 |
40 | @Bean
41 | @ConditionalOnProperty(value = "spring.cloud.bus.refresh.enabled", matchIfMissing = true)
42 | @ConditionalOnBean(ContextRefresher.class)
43 | public RefreshListener refreshListener(ContextRefresher contextRefresher, ServiceMatcher serviceMatcher) {
44 | return new RefreshListener(contextRefresher, serviceMatcher);
45 | }
46 |
47 | @Configuration(proxyBeanMethods = false)
48 | @ConditionalOnClass(name = { "org.springframework.boot.actuate.endpoint.annotation.Endpoint",
49 | "org.springframework.cloud.context.scope.refresh.RefreshScope" })
50 | protected static class BusRefreshEndpointConfiguration {
51 |
52 | @Bean
53 | @ConditionalOnAvailableEndpoint
54 | public RefreshBusEndpoint refreshBusEndpoint(ApplicationEventPublisher publisher, BusProperties bus,
55 | Destination.Factory destinationFactory) {
56 | return new RefreshBusEndpoint(publisher, bus.getId(), destinationFactory);
57 | }
58 |
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/BusShutdownAutoConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2024 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
20 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
21 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
22 | import org.springframework.cloud.bus.endpoint.ShutdownBusEndpoint;
23 | import org.springframework.cloud.bus.event.Destination;
24 | import org.springframework.cloud.bus.event.ShutdownListener;
25 | import org.springframework.context.ApplicationEventPublisher;
26 | import org.springframework.context.annotation.Bean;
27 | import org.springframework.context.annotation.Configuration;
28 |
29 | /**
30 | * @author Ryan Baxter
31 | */
32 | @Configuration(proxyBeanMethods = false)
33 | @ConditionalOnBusEnabled
34 | public class BusShutdownAutoConfiguration {
35 |
36 | @Bean
37 | @ConditionalOnProperty(value = "spring.cloud.bus.shutdown.enabled", matchIfMissing = true)
38 | @ConditionalOnMissingBean
39 | public ShutdownListener shutdownListener(ServiceMatcher serviceMatcher) {
40 | return new ShutdownListener(serviceMatcher);
41 | }
42 |
43 | @Configuration(proxyBeanMethods = false)
44 | @ConditionalOnClass(name = { "org.springframework.boot.actuate.endpoint.annotation.Endpoint" })
45 | protected static class BusShutdownEndpointConfiguration {
46 |
47 | @Bean
48 | public ShutdownBusEndpoint shutdownBusEndpoint(ApplicationEventPublisher publisher, BusProperties bus,
49 | Destination.Factory destinationFactory) {
50 | return new ShutdownBusEndpoint(publisher, bus.getId(), destinationFactory);
51 | }
52 |
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/BusStreamAutoConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015-2020 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.springframework.boot.autoconfigure.AutoConfigureAfter;
20 | import org.springframework.boot.autoconfigure.AutoConfigureBefore;
21 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
22 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
23 | import org.springframework.boot.context.properties.EnableConfigurationProperties;
24 | import org.springframework.cloud.autoconfigure.LifecycleMvcEndpointAutoConfiguration;
25 | import org.springframework.cloud.stream.config.BindingServiceConfiguration;
26 | import org.springframework.cloud.stream.function.StreamBridge;
27 | import org.springframework.context.annotation.Bean;
28 | import org.springframework.context.annotation.Configuration;
29 |
30 | @Configuration(proxyBeanMethods = false)
31 | @ConditionalOnBusEnabled
32 | @ConditionalOnClass({ StreamBridge.class, BindingServiceConfiguration.class })
33 | @EnableConfigurationProperties(BusProperties.class)
34 | @AutoConfigureBefore({ BindingServiceConfiguration.class, BusAutoConfiguration.class })
35 | // so stream bindings work properly
36 | @AutoConfigureAfter({ LifecycleMvcEndpointAutoConfiguration.class, PathServiceMatcherAutoConfiguration.class })
37 | public class BusStreamAutoConfiguration {
38 |
39 | @Bean
40 | @ConditionalOnMissingBean(BusBridge.class)
41 | public StreamBusBridge streamBusBridge(StreamBridge streamBridge, BusProperties properties) {
42 | return new StreamBusBridge(streamBridge, properties);
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/ConditionalOnBusEnabled.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import java.lang.annotation.ElementType;
20 | import java.lang.annotation.Retention;
21 | import java.lang.annotation.RetentionPolicy;
22 | import java.lang.annotation.Target;
23 |
24 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
25 |
26 | /**
27 | * @author Spencer Gibb
28 | */
29 | @ConditionalOnProperty(value = ConditionalOnBusEnabled.SPRING_CLOUD_BUS_ENABLED, matchIfMissing = true)
30 | @Retention(RetentionPolicy.RUNTIME)
31 | @Target({ ElementType.TYPE, ElementType.METHOD })
32 | public @interface ConditionalOnBusEnabled {
33 |
34 | /**
35 | * Property name to enable / disable Spring Cloud Bus.
36 | */
37 | String SPRING_CLOUD_BUS_ENABLED = "spring.cloud.bus.enabled";
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/DefaultBusPathMatcher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import java.util.Comparator;
20 | import java.util.Map;
21 |
22 | import org.apache.commons.logging.Log;
23 | import org.apache.commons.logging.LogFactory;
24 |
25 | import org.springframework.util.PathMatcher;
26 | import org.springframework.util.StringUtils;
27 |
28 | import static org.springframework.util.StringUtils.tokenizeToStringArray;
29 |
30 | /**
31 | * {@link BusPathMatcher} that matches application context ids with multiple,
32 | * comma-separated, profiles. Original
33 | * https://gist.github.com/kelapure/61d3f948acf478cc95225ff1d7d239c4
34 | *
35 | * See https://github.com/spring-cloud/spring-cloud-config/issues/678
36 | *
37 | * @author Rohit Kelapure
38 | * @author Spencer Gibb
39 | */
40 | public class DefaultBusPathMatcher implements PathMatcher {
41 |
42 | private static final Log log = LogFactory.getLog(DefaultBusPathMatcher.class);
43 |
44 | private final PathMatcher delagateMatcher;
45 |
46 | public DefaultBusPathMatcher(PathMatcher delagateMatcher) {
47 | this.delagateMatcher = delagateMatcher;
48 | }
49 |
50 | protected boolean matchMultiProfile(String pattern, String idToMatch) {
51 |
52 | if (log.isDebugEnabled()) {
53 | log.debug("matchMultiProfile : " + pattern + ", " + idToMatch);
54 | }
55 |
56 | // parse the id
57 | String[] tokens = tokenizeToStringArray(idToMatch, ":");
58 | if (tokens.length <= 1) {
59 | // no parts, default to delegate which already returned false;
60 | return false;
61 | }
62 | String selfProfiles = tokens[1];
63 |
64 | // short circuit if possible
65 | String[] profiles = tokenizeToStringArray(selfProfiles, ",");
66 |
67 | if (profiles.length == 1) {
68 | // there aren't multiple profiles to check, the delegate match was
69 | // originally false so return what delegate determined
70 | return false;
71 | }
72 |
73 | // gather candidate ids with a single profile rather than a comma separated list
74 | String[] idsWithSingleProfile = new String[profiles.length];
75 |
76 | for (int i = 0; i < profiles.length; i++) {
77 | // replace comma separated profiles with single profile
78 | String profile = profiles[i];
79 | String[] newTokens = new String[tokens.length];
80 | System.arraycopy(tokens, 0, newTokens, 0, tokens.length);
81 | newTokens[1] = profile;
82 | idsWithSingleProfile[i] = StringUtils.arrayToDelimitedString(newTokens, ":");
83 | }
84 |
85 | for (String id : idsWithSingleProfile) {
86 | if (this.delagateMatcher.match(pattern, id)) {
87 | if (log.isDebugEnabled()) {
88 | log.debug("matched true");
89 | }
90 | return true;
91 | }
92 | }
93 |
94 | if (log.isDebugEnabled()) {
95 | log.debug("matched false");
96 | }
97 | return false;
98 | }
99 |
100 | @Override
101 | public boolean isPattern(String path) {
102 | return this.delagateMatcher.isPattern(path);
103 | }
104 |
105 | @Override
106 | public boolean match(String pattern, String path) {
107 | if (log.isDebugEnabled()) {
108 | log.debug("In match: " + pattern + ", " + path);
109 | }
110 | if (!this.delagateMatcher.match(pattern, path)) {
111 | return matchMultiProfile(pattern, path);
112 | }
113 | return true;
114 | }
115 |
116 | @Override
117 | public boolean matchStart(String pattern, String path) {
118 | return this.delagateMatcher.matchStart(pattern, path);
119 | }
120 |
121 | @Override
122 | public String extractPathWithinPattern(String pattern, String path) {
123 | return this.delagateMatcher.extractPathWithinPattern(pattern, path);
124 | }
125 |
126 | @Override
127 | public Map extractUriTemplateVariables(String pattern, String path) {
128 | return this.delagateMatcher.extractUriTemplateVariables(pattern, path);
129 | }
130 |
131 | @Override
132 | public Comparator getPatternComparator(String path) {
133 | return this.delagateMatcher.getPatternComparator(path);
134 | }
135 |
136 | @Override
137 | public String combine(String pattern1, String pattern2) {
138 | return this.delagateMatcher.combine(pattern1, pattern2);
139 | }
140 |
141 | }
142 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/PathServiceMatcher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.springframework.cloud.bus.event.RemoteApplicationEvent;
20 | import org.springframework.util.PathMatcher;
21 |
22 | /**
23 | * @author Spencer Gibb
24 | */
25 | public class PathServiceMatcher implements ServiceMatcher {
26 |
27 | private final PathMatcher matcher;
28 |
29 | private final String id;
30 |
31 | private String[] configNames = new String[] {};
32 |
33 | public PathServiceMatcher(PathMatcher matcher, String id) {
34 | this.matcher = matcher;
35 | this.id = id;
36 | }
37 |
38 | public PathServiceMatcher(PathMatcher matcher, String id, String[] configNames) {
39 | this(matcher, id);
40 |
41 | int colonIndex = id.indexOf(":");
42 | if (colonIndex >= 0) {
43 | // if the id contains profiles and port, append them to the config names
44 | String profilesAndPort = id.substring(colonIndex);
45 | for (int i = 0; i < configNames.length; i++) {
46 | configNames[i] = configNames[i] + profilesAndPort;
47 | }
48 | }
49 | this.configNames = configNames;
50 | }
51 |
52 | public boolean isFromSelf(RemoteApplicationEvent event) {
53 | String originService = event.getOriginService();
54 | String serviceId = getBusId();
55 | return this.matcher.match(originService, serviceId);
56 | }
57 |
58 | public boolean isForSelf(RemoteApplicationEvent event) {
59 | String destinationService = event.getDestinationService();
60 | if (destinationService == null || destinationService.trim().isEmpty()
61 | || this.matcher.match(destinationService, getBusId())) {
62 | return true;
63 | }
64 |
65 | // Check all potential config names instead of service name
66 | for (String configName : this.configNames) {
67 | if (this.matcher.match(destinationService, configName)) {
68 | return true;
69 | }
70 | }
71 |
72 | return false;
73 | }
74 |
75 | public String getBusId() {
76 | return this.id;
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/PathServiceMatcherAutoConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2020 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
20 | import org.springframework.boot.context.properties.EnableConfigurationProperties;
21 | import org.springframework.context.annotation.Bean;
22 | import org.springframework.context.annotation.Configuration;
23 | import org.springframework.core.env.Environment;
24 | import org.springframework.util.AntPathMatcher;
25 | import org.springframework.util.PathMatcher;
26 |
27 | /**
28 | * @author Ryan Baxter
29 | */
30 | @Configuration(proxyBeanMethods = false)
31 | @ConditionalOnBusEnabled
32 | @EnableConfigurationProperties(BusProperties.class)
33 | public class PathServiceMatcherAutoConfiguration {
34 |
35 | /**
36 | * Name of the Bus path matcher.
37 | */
38 | public static final String BUS_PATH_MATCHER_NAME = "busPathMatcher";
39 |
40 | /**
41 | * Name of the Spring Cloud Config property.
42 | */
43 | public static final String CLOUD_CONFIG_NAME_PROPERTY = "spring.cloud.config.name";
44 |
45 | @BusPathMatcher
46 | // There is a @Bean of type PathMatcher coming from Spring MVC
47 | @ConditionalOnMissingBean(name = BUS_PATH_MATCHER_NAME)
48 | @Bean(name = BUS_PATH_MATCHER_NAME)
49 | public PathMatcher busPathMatcher() {
50 | return new DefaultBusPathMatcher(new AntPathMatcher(":"));
51 | }
52 |
53 | @Bean
54 | @ConditionalOnMissingBean(ServiceMatcher.class)
55 | public PathServiceMatcher pathServiceMatcher(@BusPathMatcher PathMatcher pathMatcher, BusProperties properties,
56 | Environment environment) {
57 | String[] configNames = environment.getProperty(CLOUD_CONFIG_NAME_PROPERTY, String[].class, new String[] {});
58 | return new PathServiceMatcher(pathMatcher, properties.getId(), configNames);
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/RemoteApplicationEventListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015-2020 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.apache.commons.logging.Log;
20 | import org.apache.commons.logging.LogFactory;
21 |
22 | import org.springframework.cloud.bus.event.AckRemoteApplicationEvent;
23 | import org.springframework.cloud.bus.event.RemoteApplicationEvent;
24 | import org.springframework.context.ApplicationListener;
25 |
26 | public class RemoteApplicationEventListener implements ApplicationListener {
27 |
28 | private final Log log = LogFactory.getLog(getClass());
29 |
30 | private final ServiceMatcher serviceMatcher;
31 |
32 | private final BusBridge busBridge;
33 |
34 | public RemoteApplicationEventListener(ServiceMatcher serviceMatcher, BusBridge busBridge) {
35 | this.serviceMatcher = serviceMatcher;
36 | this.busBridge = busBridge;
37 | }
38 |
39 | @Override
40 | public void onApplicationEvent(RemoteApplicationEvent event) {
41 | if (this.serviceMatcher.isFromSelf(event) && !(event instanceof AckRemoteApplicationEvent)) {
42 | if (log.isDebugEnabled()) {
43 | log.debug("Sending remote event on bus: " + event);
44 | }
45 | // TODO: configurable mimetype?
46 | this.busBridge.send(event);
47 | }
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/ServiceMatcher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.springframework.cloud.bus.event.RemoteApplicationEvent;
20 |
21 | /**
22 | * @author Spencer Gibb
23 | */
24 | public interface ServiceMatcher {
25 |
26 | boolean isFromSelf(RemoteApplicationEvent event);
27 |
28 | boolean isForSelf(RemoteApplicationEvent event);
29 |
30 | String getBusId();
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/StreamBusBridge.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015-2020 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.springframework.cloud.bus.event.RemoteApplicationEvent;
20 | import org.springframework.cloud.stream.function.StreamBridge;
21 | import org.springframework.messaging.support.MessageBuilder;
22 |
23 | public class StreamBusBridge implements BusBridge {
24 |
25 | private final StreamBridge streamBridge;
26 |
27 | private final BusProperties properties;
28 |
29 | public StreamBusBridge(StreamBridge streamBridge, BusProperties properties) {
30 | this.streamBridge = streamBridge;
31 | this.properties = properties;
32 | }
33 |
34 | public void send(RemoteApplicationEvent event) {
35 | // TODO: configurable mimetype?
36 | this.streamBridge.send(BusConstants.OUTPUT, MessageBuilder.withPayload(event).build());
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/endpoint/AbstractBusEndpoint.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.endpoint;
18 |
19 | import org.springframework.cloud.bus.event.Destination;
20 | import org.springframework.context.ApplicationEvent;
21 | import org.springframework.context.ApplicationEventPublisher;
22 |
23 | /**
24 | * @author Spencer Gibb
25 | */
26 | public class AbstractBusEndpoint {
27 |
28 | private ApplicationEventPublisher publisher;
29 |
30 | private String appId;
31 |
32 | private final Destination.Factory destinationFactory;
33 |
34 | public AbstractBusEndpoint(ApplicationEventPublisher publisher, String appId,
35 | Destination.Factory destinationFactory) {
36 | this.publisher = publisher;
37 | this.appId = appId;
38 | this.destinationFactory = destinationFactory;
39 | }
40 |
41 | protected String getInstanceId() {
42 | return this.appId;
43 | }
44 |
45 | protected Destination.Factory getDestinationFactory() {
46 | return this.destinationFactory;
47 | }
48 |
49 | protected Destination getDestination(String original) {
50 | return destinationFactory.getDestination(original);
51 | }
52 |
53 | protected void publish(ApplicationEvent event) {
54 | this.publisher.publishEvent(event);
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/endpoint/EnvironmentBusEndpoint.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.endpoint;
18 |
19 | import java.util.Collections;
20 | import java.util.Map;
21 |
22 | import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
23 | import org.springframework.boot.actuate.endpoint.annotation.Selector;
24 | import org.springframework.boot.actuate.endpoint.annotation.Selector.Match;
25 | import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
26 | import org.springframework.cloud.bus.event.Destination;
27 | import org.springframework.cloud.bus.event.EnvironmentChangeRemoteApplicationEvent;
28 | import org.springframework.context.ApplicationEventPublisher;
29 | import org.springframework.util.StringUtils;
30 |
31 | /**
32 | * @author Spencer Gibb
33 | */
34 | @Endpoint(id = "busenv") // TODO: document
35 | public class EnvironmentBusEndpoint extends AbstractBusEndpoint {
36 |
37 | public EnvironmentBusEndpoint(ApplicationEventPublisher publisher, String id,
38 | Destination.Factory destinationFactory) {
39 | super(publisher, id, destinationFactory);
40 | }
41 |
42 | @WriteOperation
43 | // TODO: document params
44 | public void busEnvWithDestination(String name, String value,
45 | @Selector(match = Match.ALL_REMAINING) String[] destinations) {
46 | Map params = Collections.singletonMap(name, value);
47 | String destination = StringUtils.arrayToDelimitedString(destinations, ":");
48 | publish(new EnvironmentChangeRemoteApplicationEvent(this, getInstanceId(), getDestination(destination),
49 | params));
50 | }
51 |
52 | @WriteOperation
53 | public void busEnv(String name, String value) { // TODO: document params
54 | Map params = Collections.singletonMap(name, value);
55 | publish(new EnvironmentChangeRemoteApplicationEvent(this, getInstanceId(), getDestination(null), params));
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/endpoint/RefreshBusEndpoint.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.endpoint;
18 |
19 | import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
20 | import org.springframework.boot.actuate.endpoint.annotation.Selector;
21 | import org.springframework.boot.actuate.endpoint.annotation.Selector.Match;
22 | import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
23 | import org.springframework.cloud.bus.event.Destination;
24 | import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
25 | import org.springframework.context.ApplicationEventPublisher;
26 | import org.springframework.util.StringUtils;
27 |
28 | /**
29 | * @author Spencer Gibb
30 | */
31 | @Endpoint(id = "busrefresh") // TODO: document new id
32 | public class RefreshBusEndpoint extends AbstractBusEndpoint {
33 |
34 | public RefreshBusEndpoint(ApplicationEventPublisher publisher, String id, Destination.Factory destinationFactory) {
35 | super(publisher, id, destinationFactory);
36 | }
37 |
38 | @WriteOperation
39 | public void busRefreshWithDestination(@Selector(match = Match.ALL_REMAINING) String[] destinations) {
40 | String destination = StringUtils.arrayToDelimitedString(destinations, ":");
41 | publish(new RefreshRemoteApplicationEvent(this, getInstanceId(), getDestination(destination)));
42 | }
43 |
44 | @WriteOperation
45 | public void busRefresh() {
46 | publish(new RefreshRemoteApplicationEvent(this, getInstanceId(), getDestination(null)));
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/endpoint/ShutdownBusEndpoint.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2024 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.endpoint;
18 |
19 | import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
20 | import org.springframework.boot.actuate.endpoint.annotation.Selector;
21 | import org.springframework.boot.actuate.endpoint.annotation.WriteOperation;
22 | import org.springframework.cloud.bus.event.Destination;
23 | import org.springframework.cloud.bus.event.ShutdownRemoteApplicationEvent;
24 | import org.springframework.context.ApplicationEventPublisher;
25 | import org.springframework.util.StringUtils;
26 |
27 | /**
28 | * @author Ryan Baxter
29 | */
30 | @Endpoint(id = "busshutdown")
31 | public class ShutdownBusEndpoint extends AbstractBusEndpoint {
32 |
33 | public ShutdownBusEndpoint(ApplicationEventPublisher publisher, String id, Destination.Factory destinationFactory) {
34 | super(publisher, id, destinationFactory);
35 | }
36 |
37 | @WriteOperation
38 | public void busShutdownWithDestination(@Selector(match = Selector.Match.ALL_REMAINING) String[] destinations) {
39 | String destination = StringUtils.arrayToDelimitedString(destinations, ":");
40 | publish(new ShutdownRemoteApplicationEvent(this, getInstanceId(), getDestination(destination)));
41 | }
42 |
43 | @WriteOperation
44 | public void busShutdown() {
45 | publish(new ShutdownRemoteApplicationEvent(this, getInstanceId(), getDestination(null)));
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/event/AckRemoteApplicationEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event;
18 |
19 | import com.fasterxml.jackson.annotation.JsonProperty;
20 |
21 | /**
22 | * An event that signals an ack of a specific {@link RemoteApplicationEvent}. These events
23 | * can be monitored by any applications that want to audit the responses to bus events.
24 | * They behave like normal remote application events, in the sense that if the destination
25 | * service matches the local service ID the application fires the event in its context.
26 | *
27 | * @author Dave Syer
28 | *
29 | */
30 | @SuppressWarnings("serial")
31 | public class AckRemoteApplicationEvent extends RemoteApplicationEvent {
32 |
33 | private final String ackId;
34 |
35 | private final String ackDestinationService;
36 |
37 | private Class extends RemoteApplicationEvent> event;
38 |
39 | @SuppressWarnings("unused")
40 | private AckRemoteApplicationEvent() {
41 | super();
42 | this.ackDestinationService = null;
43 | this.ackId = null;
44 | this.event = null;
45 | }
46 |
47 | public AckRemoteApplicationEvent(Object source, String originService, Destination destination,
48 | String ackDestinationService, String ackId, Class extends RemoteApplicationEvent> type) {
49 | super(source, originService, destination);
50 | this.ackDestinationService = ackDestinationService;
51 | this.ackId = ackId;
52 | this.event = type;
53 | }
54 |
55 | public String getAckId() {
56 | return this.ackId;
57 | }
58 |
59 | public String getAckDestinationService() {
60 | return this.ackDestinationService;
61 | }
62 |
63 | public Class extends RemoteApplicationEvent> getEvent() {
64 | return this.event;
65 | }
66 |
67 | /**
68 | * Used by Jackson to set the remote class name of the event implementation. If the
69 | * implementing class is unknown to this app, set the event to
70 | * {@link UnknownRemoteApplicationEvent}.
71 | * @param eventName the fq class name of the event implementation, not null
72 | */
73 | @JsonProperty("event")
74 | @SuppressWarnings("unchecked")
75 | public void setEventName(String eventName) {
76 | try {
77 | this.event = (Class extends RemoteApplicationEvent>) Class.forName(eventName);
78 | }
79 | catch (ClassNotFoundException e) {
80 | this.event = UnknownRemoteApplicationEvent.class;
81 | }
82 | }
83 |
84 | @Override
85 | public int hashCode() {
86 | final int prime = 31;
87 | int result = super.hashCode();
88 | result = prime * result + ((this.ackDestinationService == null) ? 0 : this.ackDestinationService.hashCode());
89 | result = prime * result + ((this.ackId == null) ? 0 : this.ackId.hashCode());
90 | result = prime * result + ((this.event == null) ? 0 : this.event.hashCode());
91 | return result;
92 | }
93 |
94 | @Override
95 | public boolean equals(Object obj) {
96 | if (this == obj) {
97 | return true;
98 | }
99 | if (!super.equals(obj)) {
100 | return false;
101 | }
102 | if (getClass() != obj.getClass()) {
103 | return false;
104 | }
105 | AckRemoteApplicationEvent other = (AckRemoteApplicationEvent) obj;
106 | if (this.ackDestinationService == null) {
107 | if (other.ackDestinationService != null) {
108 | return false;
109 | }
110 | }
111 | else if (!this.ackDestinationService.equals(other.ackDestinationService)) {
112 | return false;
113 | }
114 | if (this.ackId == null) {
115 | if (other.ackId != null) {
116 | return false;
117 | }
118 | }
119 | else if (!this.ackId.equals(other.ackId)) {
120 | return false;
121 | }
122 | if (this.event == null) {
123 | if (other.event != null) {
124 | return false;
125 | }
126 | }
127 | else if (!this.event.equals(other.event)) {
128 | return false;
129 | }
130 | return true;
131 | }
132 |
133 | }
134 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/event/Destination.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015-2020 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event;
18 |
19 | public interface Destination {
20 |
21 | String getDestinationAsString();
22 |
23 | @FunctionalInterface
24 | interface Factory {
25 |
26 | Destination getDestination(String originalDestination);
27 |
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/event/EnvironmentChangeListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event;
18 |
19 | import java.util.Map;
20 |
21 | import org.apache.commons.logging.Log;
22 | import org.apache.commons.logging.LogFactory;
23 |
24 | import org.springframework.beans.factory.annotation.Autowired;
25 | import org.springframework.cloud.context.environment.EnvironmentManager;
26 | import org.springframework.context.ApplicationListener;
27 |
28 | /**
29 | * @author Spencer Gibb
30 | */
31 | public class EnvironmentChangeListener implements ApplicationListener {
32 |
33 | private static Log log = LogFactory.getLog(EnvironmentChangeListener.class);
34 |
35 | @Autowired
36 | private EnvironmentManager env;
37 |
38 | @Override
39 | public void onApplicationEvent(EnvironmentChangeRemoteApplicationEvent event) {
40 | Map values = event.getValues();
41 | log.info("Received remote environment change request. Keys/values to update " + values);
42 | for (Map.Entry entry : values.entrySet()) {
43 | this.env.setProperty(entry.getKey(), entry.getValue());
44 | }
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/event/EnvironmentChangeRemoteApplicationEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event;
18 |
19 | import java.util.Map;
20 |
21 | import org.springframework.core.style.ToStringCreator;
22 | import org.springframework.util.Assert;
23 |
24 | /**
25 | * @author Spencer Gibb
26 | */
27 | @SuppressWarnings("serial")
28 | public class EnvironmentChangeRemoteApplicationEvent extends RemoteApplicationEvent {
29 |
30 | private final Map values;
31 |
32 | @SuppressWarnings("unused")
33 | private EnvironmentChangeRemoteApplicationEvent() {
34 | // for serializers
35 | this.values = null;
36 | }
37 |
38 | @Deprecated
39 | public EnvironmentChangeRemoteApplicationEvent(Object source, String originService, String destinationService,
40 | Map values) {
41 | this(source, originService, new PathDestinationFactory().getDestination(destinationService), values);
42 | }
43 |
44 | public EnvironmentChangeRemoteApplicationEvent(Object source, String originService, Destination destination,
45 | Map values) {
46 | super(source, originService, destination);
47 | Assert.notNull(values, "values may not be null");
48 | this.values = values;
49 | }
50 |
51 | public Map getValues() {
52 | return this.values;
53 | }
54 |
55 | @Override
56 | public int hashCode() {
57 | final int prime = 31;
58 | int result = super.hashCode();
59 | result = prime * result + ((this.values == null) ? 0 : this.values.hashCode());
60 | return result;
61 | }
62 |
63 | @Override
64 | public boolean equals(Object obj) {
65 | if (this == obj) {
66 | return true;
67 | }
68 | if (!super.equals(obj)) {
69 | return false;
70 | }
71 | if (getClass() != obj.getClass()) {
72 | return false;
73 | }
74 | EnvironmentChangeRemoteApplicationEvent other = (EnvironmentChangeRemoteApplicationEvent) obj;
75 | if (this.values == null) {
76 | if (other.values != null) {
77 | return false;
78 | }
79 | }
80 | else if (!this.values.equals(other.values)) {
81 | return false;
82 | }
83 | return true;
84 | }
85 |
86 | @Override
87 | public String toString() {
88 | return new ToStringCreator(this).append("id", getId())
89 | .append("originService", getOriginService())
90 | .append("destinationService", getDestinationService())
91 | .append("values", values)
92 | .toString();
93 |
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/event/PathDestinationFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015-2020 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event;
18 |
19 | import org.springframework.util.StringUtils;
20 |
21 | public class PathDestinationFactory implements Destination.Factory {
22 |
23 | public Destination getDestination(String originalDestination) {
24 | String path = originalDestination;
25 | if (path == null) {
26 | path = "**";
27 | }
28 | // If the path is not already a wildcard, match everything that
29 | // follows if there at most two path elements, and last element is not a global
30 | // wildcard already
31 | if (!"**".equals(path)) {
32 | if (StringUtils.countOccurrencesOf(path, ":") <= 1 && !StringUtils.endsWithIgnoreCase(path, ":**")) {
33 | // All instances of the destination unless specifically requested
34 | path = path + ":**";
35 | }
36 | }
37 |
38 | final String finalPath = path;
39 | return () -> finalPath;
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/event/RefreshListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event;
18 |
19 | import java.util.Set;
20 |
21 | import org.apache.commons.logging.Log;
22 | import org.apache.commons.logging.LogFactory;
23 |
24 | import org.springframework.cloud.bus.ServiceMatcher;
25 | import org.springframework.cloud.context.refresh.ContextRefresher;
26 | import org.springframework.context.ApplicationListener;
27 |
28 | /**
29 | * @author Spencer Gibb
30 | * @author Ryan Baxter
31 | */
32 | public class RefreshListener implements ApplicationListener {
33 |
34 | private static Log log = LogFactory.getLog(RefreshListener.class);
35 |
36 | private ContextRefresher contextRefresher;
37 |
38 | private ServiceMatcher serviceMatcher;
39 |
40 | public RefreshListener(ContextRefresher contextRefresher, ServiceMatcher serviceMatcher) {
41 | this.contextRefresher = contextRefresher;
42 | this.serviceMatcher = serviceMatcher;
43 | }
44 |
45 | @Override
46 | public void onApplicationEvent(RefreshRemoteApplicationEvent event) {
47 | log.info("Received remote refresh request.");
48 | if (serviceMatcher.isForSelf(event)) {
49 | Set keys = this.contextRefresher.refresh();
50 | log.info("Keys refreshed " + keys);
51 | }
52 | else {
53 | log.info("Refresh not performed, the event was targeting " + event.getDestinationService());
54 | }
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/event/RefreshRemoteApplicationEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event;
18 |
19 | /**
20 | * @author Spencer Gibb
21 | */
22 | @SuppressWarnings("serial")
23 | public class RefreshRemoteApplicationEvent extends RemoteApplicationEvent {
24 |
25 | @SuppressWarnings("unused")
26 | private RefreshRemoteApplicationEvent() {
27 | // for serializers
28 | }
29 |
30 | @Deprecated
31 | public RefreshRemoteApplicationEvent(Object source, String originService, String destination) {
32 | this(source, originService, new PathDestinationFactory().getDestination(destination));
33 | }
34 |
35 | public RefreshRemoteApplicationEvent(Object source, String originService, Destination destination) {
36 | super(source, originService, destination);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/event/RemoteApplicationEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event;
18 |
19 | import java.util.UUID;
20 |
21 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
22 | import com.fasterxml.jackson.annotation.JsonTypeInfo;
23 |
24 | import org.springframework.context.ApplicationEvent;
25 | import org.springframework.core.style.ToStringCreator;
26 | import org.springframework.util.Assert;
27 |
28 | /**
29 | * @author Spencer Gibb
30 | */
31 | @SuppressWarnings("serial")
32 | @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
33 | @JsonIgnoreProperties("source")
34 | public abstract class RemoteApplicationEvent extends ApplicationEvent {
35 |
36 | private static final Object TRANSIENT_SOURCE = new Object();
37 |
38 | private static final String TRANSIENT_ORIGIN = "____transient_origin_service___";
39 |
40 | private static final String TRANSIENT_DESTINATION = "____transient_destination___";
41 |
42 | protected static final PathDestinationFactory DEFAULT_DESTINATION_FACTORY = new PathDestinationFactory();
43 |
44 | private final String originService;
45 |
46 | private final String destinationService;
47 |
48 | private final String id;
49 |
50 | protected RemoteApplicationEvent() {
51 | // for serialization libs like jackson
52 | this(TRANSIENT_SOURCE, TRANSIENT_ORIGIN, DEFAULT_DESTINATION_FACTORY.getDestination(TRANSIENT_DESTINATION));
53 | }
54 |
55 | @Deprecated
56 | protected RemoteApplicationEvent(Object source, String originService, String destinationService) {
57 | this(source, originService, DEFAULT_DESTINATION_FACTORY.getDestination(destinationService));
58 | }
59 |
60 | protected RemoteApplicationEvent(Object source, String originService, Destination destination) {
61 | super(source);
62 | if (!originService.equals(TRANSIENT_ORIGIN)) {
63 | Assert.notNull(originService, "originService may not be null");
64 | this.originService = originService;
65 | }
66 | else {
67 | this.originService = null;
68 | }
69 | Assert.notNull(destination, "destination may not be null");
70 | this.destinationService = destination.getDestinationAsString();
71 | Assert.hasText(destinationService, "destinationService may not be empty");
72 | this.id = UUID.randomUUID().toString();
73 | }
74 |
75 | @Deprecated
76 | protected RemoteApplicationEvent(Object source, String originService) {
77 | this(source, originService, DEFAULT_DESTINATION_FACTORY.getDestination(null));
78 | }
79 |
80 | public String getOriginService() {
81 | return this.originService;
82 | }
83 |
84 | public String getDestinationService() {
85 | return this.destinationService;
86 | }
87 |
88 | public String getId() {
89 | return this.id;
90 | }
91 |
92 | @Override
93 | public int hashCode() {
94 | final int prime = 31;
95 | int result = 1;
96 | result = prime * result + ((this.destinationService == null) ? 0 : this.destinationService.hashCode());
97 | result = prime * result + ((this.id == null) ? 0 : this.id.hashCode());
98 | result = prime * result + ((this.originService == null) ? 0 : this.originService.hashCode());
99 | return result;
100 | }
101 |
102 | @Override
103 | public boolean equals(Object obj) {
104 | if (this == obj) {
105 | return true;
106 | }
107 | if (obj == null) {
108 | return false;
109 | }
110 | if (getClass() != obj.getClass()) {
111 | return false;
112 | }
113 | RemoteApplicationEvent other = (RemoteApplicationEvent) obj;
114 | if (this.destinationService == null) {
115 | if (other.destinationService != null) {
116 | return false;
117 | }
118 | }
119 | else if (!this.destinationService.equals(other.destinationService)) {
120 | return false;
121 | }
122 | if (this.id == null) {
123 | if (other.id != null) {
124 | return false;
125 | }
126 | }
127 | else if (!this.id.equals(other.id)) {
128 | return false;
129 | }
130 | if (this.originService == null) {
131 | if (other.originService != null) {
132 | return false;
133 | }
134 | }
135 | else if (!this.originService.equals(other.originService)) {
136 | return false;
137 | }
138 | return true;
139 | }
140 |
141 | @Override
142 | public String toString() {
143 | return new ToStringCreator(this).append("id", id)
144 | .append("originService", originService)
145 | .append("destinationService", destinationService)
146 | .toString();
147 |
148 | }
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/event/SentApplicationEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event;
18 |
19 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
20 | import com.fasterxml.jackson.annotation.JsonTypeInfo;
21 |
22 | import org.springframework.context.ApplicationEvent;
23 |
24 | /**
25 | * An event signalling that a remote event was sent somewhere in the system. This is not
26 | * itself a {@link RemoteApplicationEvent}, so it isn't sent over the bus, instead it is
27 | * generated locally (possibly in response to a remote event). Applications that want to
28 | * audit remote events can listen for this one and the {@link AckRemoteApplicationEvent}
29 | * from all the consumers (the {@link #getId() id} of this event is the
30 | * {@link AckRemoteApplicationEvent#getAckId() ackId} of the corresponding ACK.
31 | *
32 | * @author Dave Syer
33 | */
34 | @SuppressWarnings("serial")
35 | @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
36 | @JsonIgnoreProperties("source")
37 | public class SentApplicationEvent extends ApplicationEvent {
38 |
39 | private static final Object TRANSIENT_SOURCE = new Object();
40 |
41 | private final String originService;
42 |
43 | private final String destinationService;
44 |
45 | private final String id;
46 |
47 | private Class extends RemoteApplicationEvent> type;
48 |
49 | protected SentApplicationEvent() {
50 | // for serialization libs like jackson
51 | this(TRANSIENT_SOURCE, null, null, null, RemoteApplicationEvent.class);
52 | }
53 |
54 | public SentApplicationEvent(Object source, String originService, String destinationService, String id,
55 | Class extends RemoteApplicationEvent> type) {
56 | super(source);
57 | this.originService = originService;
58 | this.type = type;
59 | if (destinationService == null) {
60 | destinationService = "*";
61 | }
62 | if (!destinationService.contains(":")) {
63 | // All instances of the destination unless specifically requested
64 | destinationService = destinationService + ":**";
65 | }
66 | this.destinationService = destinationService;
67 | this.id = id;
68 | }
69 |
70 | public Class extends RemoteApplicationEvent> getType() {
71 | return this.type;
72 | }
73 |
74 | public void setType(Class extends RemoteApplicationEvent> type) {
75 | this.type = type;
76 | }
77 |
78 | public String getOriginService() {
79 | return this.originService;
80 | }
81 |
82 | public String getDestinationService() {
83 | return this.destinationService;
84 | }
85 |
86 | public String getId() {
87 | return this.id;
88 | }
89 |
90 | @Override
91 | public int hashCode() {
92 | final int prime = 31;
93 | int result = 1;
94 | result = prime * result + ((this.destinationService == null) ? 0 : this.destinationService.hashCode());
95 | result = prime * result + ((this.id == null) ? 0 : this.id.hashCode());
96 | result = prime * result + ((this.originService == null) ? 0 : this.originService.hashCode());
97 | result = prime * result + ((this.type == null) ? 0 : this.type.hashCode());
98 | return result;
99 | }
100 |
101 | @Override
102 | public boolean equals(Object obj) {
103 | if (this == obj) {
104 | return true;
105 | }
106 | if (obj == null) {
107 | return false;
108 | }
109 | if (getClass() != obj.getClass()) {
110 | return false;
111 | }
112 | SentApplicationEvent other = (SentApplicationEvent) obj;
113 | if (this.destinationService == null) {
114 | if (other.destinationService != null) {
115 | return false;
116 | }
117 | }
118 | else if (!this.destinationService.equals(other.destinationService)) {
119 | return false;
120 | }
121 | if (this.id == null) {
122 | if (other.id != null) {
123 | return false;
124 | }
125 | }
126 | else if (!this.id.equals(other.id)) {
127 | return false;
128 | }
129 | if (this.originService == null) {
130 | if (other.originService != null) {
131 | return false;
132 | }
133 | }
134 | else if (!this.originService.equals(other.originService)) {
135 | return false;
136 | }
137 | if (this.type == null) {
138 | if (other.type != null) {
139 | return false;
140 | }
141 | }
142 | else if (!this.type.equals(other.type)) {
143 | return false;
144 | }
145 | return true;
146 | }
147 |
148 | }
149 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/event/ShutdownListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2024 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event;
18 |
19 | import org.apache.commons.logging.Log;
20 | import org.apache.commons.logging.LogFactory;
21 |
22 | import org.springframework.beans.BeansException;
23 | import org.springframework.boot.SpringApplication;
24 | import org.springframework.cloud.bus.ServiceMatcher;
25 | import org.springframework.context.ApplicationContext;
26 | import org.springframework.context.ApplicationContextAware;
27 | import org.springframework.context.ApplicationListener;
28 |
29 | /**
30 | * @author Ryan Baxter
31 | */
32 | public class ShutdownListener implements ApplicationListener, ApplicationContextAware {
33 |
34 | private static final Log LOG = LogFactory.getLog(ShutdownListener.class);
35 |
36 | private ApplicationContext context;
37 |
38 | private ServiceMatcher serviceMatcher;
39 |
40 | public ShutdownListener(ServiceMatcher serviceMatcher) {
41 | this.serviceMatcher = serviceMatcher;
42 | }
43 |
44 | @Override
45 | public void onApplicationEvent(ShutdownRemoteApplicationEvent event) {
46 | if (serviceMatcher.isForSelf(event)) {
47 | LOG.warn("Received remote shutdown request from " + event.getOriginService() + ". Shutting down.");
48 | shutdown();
49 | }
50 | else {
51 | LOG.info("Shutdown not performed, the event was targeting " + event.getDestinationService());
52 | }
53 |
54 | }
55 |
56 | protected int shutdown() {
57 | return SpringApplication.exit(context, () -> 0);
58 | }
59 |
60 | @Override
61 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
62 | this.context = applicationContext;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/event/ShutdownRemoteApplicationEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2024 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event;
18 |
19 | /**
20 | * Event which indicates the application should be shutdown.
21 | *
22 | * @author Ryan Baxter
23 | */
24 | public class ShutdownRemoteApplicationEvent extends RemoteApplicationEvent {
25 |
26 | @SuppressWarnings("unused")
27 | private ShutdownRemoteApplicationEvent() {
28 | // for serializers
29 | }
30 |
31 | public ShutdownRemoteApplicationEvent(Object source, String originService, Destination destination) {
32 | super(source, originService, destination);
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/event/TraceListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event;
18 |
19 | import java.util.LinkedHashMap;
20 | import java.util.Map;
21 |
22 | import org.apache.commons.logging.Log;
23 | import org.apache.commons.logging.LogFactory;
24 |
25 | import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
26 | import org.springframework.context.event.EventListener;
27 |
28 | /**
29 | * A listener for sends and acks of remote application events. Inserts a record for each
30 | * signal in the {@link HttpExchangeRepository}.
31 | *
32 | * @author Dave Syer
33 | */
34 | public class TraceListener {
35 |
36 | private static Log log = LogFactory.getLog(TraceListener.class);
37 |
38 | private HttpExchangeRepository repository;
39 |
40 | public TraceListener(HttpExchangeRepository repository) {
41 | this.repository = repository;
42 | }
43 |
44 | @EventListener
45 | public void onAck(AckRemoteApplicationEvent event) {
46 | Map trace = getReceivedTrace(event);
47 | // FIXME boot 2 this.repository.add(trace);
48 | }
49 |
50 | @EventListener
51 | public void onSend(SentApplicationEvent event) {
52 | Map trace = getSentTrace(event);
53 | // FIXME boot 2 this.repository.add(trace);
54 | }
55 |
56 | protected Map getSentTrace(SentApplicationEvent event) {
57 | Map map = new LinkedHashMap();
58 | map.put("signal", "spring.cloud.bus.sent");
59 | map.put("type", event.getType().getSimpleName());
60 | map.put("id", event.getId());
61 | map.put("origin", event.getOriginService());
62 | map.put("destination", event.getDestinationService());
63 | if (log.isDebugEnabled()) {
64 | log.debug(map);
65 | }
66 | return map;
67 | }
68 |
69 | protected Map getReceivedTrace(AckRemoteApplicationEvent event) {
70 | Map map = new LinkedHashMap();
71 | map.put("signal", "spring.cloud.bus.ack");
72 | map.put("event", event.getEvent().getSimpleName());
73 | map.put("id", event.getAckId());
74 | map.put("origin", event.getOriginService());
75 | map.put("destination", event.getAckDestinationService());
76 | if (log.isDebugEnabled()) {
77 | log.debug(map);
78 | }
79 | return map;
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/event/UnknownRemoteApplicationEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event;
18 |
19 | import org.springframework.core.style.ToStringCreator;
20 |
21 | /**
22 | * @author Stefan Pfeiffer
23 | */
24 | public class UnknownRemoteApplicationEvent extends RemoteApplicationEvent {
25 |
26 | protected String typeInfo;
27 |
28 | protected byte[] payload;
29 |
30 | @SuppressWarnings("unused")
31 | private UnknownRemoteApplicationEvent() {
32 | super();
33 | this.typeInfo = null;
34 | this.payload = null;
35 | }
36 |
37 | public UnknownRemoteApplicationEvent(Object source, String typeInfo, byte[] payload) {
38 | // Initialize originService with an empty String, to avoid NullPointer in
39 | // AntPathMatcher.
40 | super(source, "", () -> "unknown");
41 | this.typeInfo = typeInfo;
42 | this.payload = payload;
43 | }
44 |
45 | public String getTypeInfo() {
46 | return this.typeInfo;
47 | }
48 |
49 | public byte[] getPayload() {
50 | return this.payload;
51 | }
52 |
53 | public String getPayloadAsString() {
54 | if (this.payload != null) {
55 | return new String(this.payload);
56 | }
57 | return null;
58 | }
59 |
60 | @Override
61 | public String toString() {
62 | return new ToStringCreator(this).append("id", getId())
63 | .append("originService", getOriginService())
64 | .append("destinationService", getDestinationService())
65 | .append("typeInfo", typeInfo)
66 | .append("payload", getPayloadAsString())
67 | .toString();
68 |
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/jackson/RemoteApplicationEventRegistrar.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.jackson;
18 |
19 | import java.util.Arrays;
20 | import java.util.HashSet;
21 | import java.util.Map;
22 | import java.util.Set;
23 |
24 | import org.springframework.beans.factory.config.BeanDefinitionHolder;
25 | import org.springframework.beans.factory.support.AbstractBeanDefinition;
26 | import org.springframework.beans.factory.support.BeanDefinitionBuilder;
27 | import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
28 | import org.springframework.beans.factory.support.BeanDefinitionRegistry;
29 | import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
30 | import org.springframework.core.type.AnnotationMetadata;
31 | import org.springframework.util.ClassUtils;
32 | import org.springframework.util.StringUtils;
33 |
34 | /**
35 | * @author Donovan Muller
36 | */
37 | public class RemoteApplicationEventRegistrar implements ImportBeanDefinitionRegistrar {
38 |
39 | private static final String PACKAGES_TO_SCAN = "packagesToScan";
40 |
41 | private static final String BUS_JSON_CONVERTER = "busJsonConverter";
42 |
43 | // patterned after Spring Integration IntegrationComponentScanRegistrar
44 |
45 | @Override
46 | public void registerBeanDefinitions(final AnnotationMetadata importingClassMetadata,
47 | final BeanDefinitionRegistry registry) {
48 |
49 | Map componentScan = importingClassMetadata
50 | .getAnnotationAttributes(RemoteApplicationEventScan.class.getName(), false);
51 |
52 | Set basePackages = new HashSet<>();
53 | for (String pkg : (String[]) componentScan.get("value")) {
54 | if (StringUtils.hasText(pkg)) {
55 | basePackages.add(pkg);
56 | }
57 | }
58 | for (String pkg : (String[]) componentScan.get("basePackages")) {
59 | if (StringUtils.hasText(pkg)) {
60 | basePackages.add(pkg);
61 | }
62 | }
63 | for (Class> clazz : (Class[]) componentScan.get("basePackageClasses")) {
64 | basePackages.add(ClassUtils.getPackageName(clazz));
65 | }
66 |
67 | if (basePackages.isEmpty()) {
68 | basePackages.add(ClassUtils.getPackageName(importingClassMetadata.getClassName()));
69 | }
70 |
71 | if (!registry.containsBeanDefinition(BUS_JSON_CONVERTER)) {
72 | BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
73 | .genericBeanDefinition(BusJacksonMessageConverter.class);
74 | beanDefinitionBuilder.addPropertyValue(PACKAGES_TO_SCAN,
75 | basePackages.toArray(new String[basePackages.size()]));
76 | AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
77 |
78 | BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, BUS_JSON_CONVERTER);
79 | BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
80 | }
81 | else {
82 | basePackages.addAll(getEarlierPackagesToScan(registry));
83 | registry.getBeanDefinition(BUS_JSON_CONVERTER)
84 | .getPropertyValues()
85 | .addPropertyValue(PACKAGES_TO_SCAN, basePackages.toArray(new String[basePackages.size()]));
86 | }
87 | }
88 |
89 | private Set getEarlierPackagesToScan(final BeanDefinitionRegistry registry) {
90 | if (registry.containsBeanDefinition(BUS_JSON_CONVERTER)
91 | && registry.getBeanDefinition(BUS_JSON_CONVERTER).getPropertyValues().get(PACKAGES_TO_SCAN) != null) {
92 | String[] earlierValues = (String[]) registry.getBeanDefinition(BUS_JSON_CONVERTER)
93 | .getPropertyValues()
94 | .get(PACKAGES_TO_SCAN);
95 | return new HashSet<>(Arrays.asList(earlierValues));
96 | }
97 |
98 | return new HashSet<>();
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/jackson/RemoteApplicationEventScan.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.jackson;
18 |
19 | import java.lang.annotation.Documented;
20 | import java.lang.annotation.ElementType;
21 | import java.lang.annotation.Retention;
22 | import java.lang.annotation.RetentionPolicy;
23 | import java.lang.annotation.Target;
24 |
25 | import org.springframework.context.annotation.Import;
26 |
27 | /**
28 | * @author Donovan Muller
29 | */
30 | @Retention(RetentionPolicy.RUNTIME)
31 | @Target(ElementType.TYPE)
32 | @Documented
33 | @Import(RemoteApplicationEventRegistrar.class)
34 | public @interface RemoteApplicationEventScan {
35 |
36 | String[] value() default {};
37 |
38 | String[] basePackages() default {};
39 |
40 | Class>[] basePackageClasses() default {};
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/java/org/springframework/cloud/bus/jackson/SubtypeModule.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.jackson;
18 |
19 | import com.fasterxml.jackson.databind.module.SimpleModule;
20 |
21 | /**
22 | * @author Spencer Gibb
23 | */
24 | @SuppressWarnings("serial")
25 | public class SubtypeModule extends SimpleModule {
26 |
27 | private Class>[] subtypes;
28 |
29 | public SubtypeModule(Class>... subtypes) {
30 | this.subtypes = subtypes;
31 | }
32 |
33 | @Override
34 | public void setupModule(SetupContext context) {
35 | context.registerSubtypes(this.subtypes);
36 | super.setupModule(context);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/resources/META-INF/additional-spring-configuration-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "properties": [
3 | {
4 | "name": "spring.cloud.bus.env.enabled",
5 | "type": "java.lang.Boolean",
6 | "description": "Flag to switch off environment change events (default on).",
7 | "defaultValue": true
8 | },
9 | {
10 | "name": "spring.cloud.bus.refresh.enabled",
11 | "type": "java.lang.Boolean",
12 | "description": "Flag to switch off refresh events (default on).",
13 | "defaultValue": true
14 | },
15 | {
16 | "name": "spring.cloud.bus.shutdown.enabled",
17 | "type": "java.lang.Boolean",
18 | "description": "Flag to switch off shutdown events (default on).",
19 | "defaultValue": true
20 | },
21 | {
22 | "name": "spring.cloud.bus.trace.enabled",
23 | "type": "java.lang.Boolean",
24 | "description": "Flag to switch on tracing of acks (default off).",
25 | "defaultValue": false
26 | }
27 | ]
28 | }
29 |
30 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/resources/META-INF/spring.factories:
--------------------------------------------------------------------------------
1 | # Environment Post Processor
2 | org.springframework.boot.env.EnvironmentPostProcessor=\
3 | org.springframework.cloud.bus.BusEnvironmentPostProcessor
4 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:
--------------------------------------------------------------------------------
1 | org.springframework.cloud.bus.PathServiceMatcherAutoConfiguration
2 | org.springframework.cloud.bus.BusAutoConfiguration
3 | org.springframework.cloud.bus.BusRefreshAutoConfiguration
4 | org.springframework.cloud.bus.BusShutdownAutoConfiguration
5 | org.springframework.cloud.bus.BusStreamAutoConfiguration
6 | org.springframework.cloud.bus.jackson.BusJacksonAutoConfiguration
7 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/test/java/org/springframework/cloud/bus/BusAutoConfigurationClassPathTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.junit.Test;
20 |
21 | import org.springframework.boot.autoconfigure.AutoConfigurations;
22 | import org.springframework.boot.test.context.FilteredClassLoader;
23 | import org.springframework.boot.test.context.runner.ApplicationContextRunner;
24 | import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
25 | import org.springframework.cloud.bus.endpoint.RefreshBusEndpoint;
26 | import org.springframework.cloud.bus.event.RefreshListener;
27 |
28 | import static org.assertj.core.api.Assertions.assertThat;
29 |
30 | public class BusAutoConfigurationClassPathTests {
31 |
32 | @Test
33 | public void refreshListenerCreatedWithoutActuator() {
34 | new ApplicationContextRunner().withClassLoader(new FilteredClassLoader("org.springframework.boot.actuate"))
35 | .withConfiguration(AutoConfigurations.of(RefreshAutoConfiguration.class,
36 | PathServiceMatcherAutoConfiguration.class, BusRefreshAutoConfiguration.class))
37 | .run(context -> assertThat(context).hasSingleBean(RefreshListener.class)
38 | .doesNotHaveBean(RefreshBusEndpoint.class));
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/test/java/org/springframework/cloud/bus/BusEnvironmentPostProcessorTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015-2022 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.junit.jupiter.api.Test;
20 |
21 | import org.springframework.boot.SpringApplication;
22 | import org.springframework.cloud.function.context.FunctionProperties;
23 | import org.springframework.mock.env.MockEnvironment;
24 |
25 | import static org.assertj.core.api.Assertions.assertThat;
26 | import static org.mockito.Mockito.mock;
27 | import static org.springframework.cloud.bus.BusConstants.BUS_CONSUMER;
28 | import static org.springframework.cloud.bus.BusConstants.DESTINATION;
29 | import static org.springframework.cloud.bus.BusConstants.INPUT;
30 | import static org.springframework.cloud.bus.BusConstants.OUTPUT;
31 | import static org.springframework.cloud.bus.BusEnvironmentPostProcessor.DEFAULTS_PROPERTY_SOURCE_NAME;
32 | import static org.springframework.cloud.bus.BusEnvironmentPostProcessor.OVERRIDES_PROPERTY_SOURCE_NAME;
33 |
34 | public class BusEnvironmentPostProcessorTests {
35 |
36 | @Test
37 | void testDefaults() {
38 | MockEnvironment env = new MockEnvironment().withProperty("cachedrandom.application.value", "123");
39 | new BusEnvironmentPostProcessor().postProcessEnvironment(env, mock(SpringApplication.class));
40 | assertThat(env.getProperty(FunctionProperties.PREFIX + ".definition")).isEqualTo(BUS_CONSUMER);
41 | assertThat(env.getProperty("spring.cloud.stream.function.bindings." + BUS_CONSUMER + "-in-0")).isEqualTo(INPUT);
42 | assertThat(env.getProperty("spring.cloud.stream.bindings." + INPUT + ".destination")).isEqualTo(DESTINATION);
43 | assertThat(env.getProperty("spring.cloud.stream.bindings." + OUTPUT + ".destination")).isEqualTo(DESTINATION);
44 | assertThat(env.getProperty(BusProperties.PREFIX + ".id")).isEqualTo("application:8080:123");
45 | assertThat(env.getPropertySources().contains(OVERRIDES_PROPERTY_SOURCE_NAME));
46 | assertThat(env.getPropertySources().contains(DEFAULTS_PROPERTY_SOURCE_NAME));
47 | }
48 |
49 | @Test
50 | void testWithActiveProfile() {
51 | MockEnvironment env = new MockEnvironment().withProperty("cachedrandom.application.value", "123")
52 | .withProperty("spring.profiles.active", "dev");
53 | new BusEnvironmentPostProcessor().postProcessEnvironment(env, mock(SpringApplication.class));
54 | assertThat(env.getProperty(FunctionProperties.PREFIX + ".definition")).isEqualTo(BUS_CONSUMER);
55 | assertThat(env.getProperty("spring.cloud.stream.function.bindings." + BUS_CONSUMER + "-in-0")).isEqualTo(INPUT);
56 | assertThat(env.getProperty("spring.cloud.stream.bindings." + INPUT + ".destination")).isEqualTo(DESTINATION);
57 | assertThat(env.getProperty("spring.cloud.stream.bindings." + OUTPUT + ".destination")).isEqualTo(DESTINATION);
58 | assertThat(env.getProperty(BusProperties.PREFIX + ".id")).isEqualTo("application:dev:8080:123");
59 | assertThat(env.getPropertySources().contains(OVERRIDES_PROPERTY_SOURCE_NAME));
60 | assertThat(env.getPropertySources().contains(DEFAULTS_PROPERTY_SOURCE_NAME));
61 | }
62 |
63 | @Test
64 | void testOverrides() {
65 | String fnDefKey = FunctionProperties.PREFIX + ".definition";
66 | String idKey = BusProperties.PREFIX + ".id";
67 | MockEnvironment env = new MockEnvironment().withProperty("cachedrandom.application.value", "123")
68 | .withProperty(BusProperties.PREFIX + ".destination", "mydestination")
69 | .withProperty(idKey, "app:1")
70 | .withProperty(fnDefKey, "uppercase");
71 | new BusEnvironmentPostProcessor().postProcessEnvironment(env, mock(SpringApplication.class));
72 | assertThat(env.getProperty(fnDefKey)).isEqualTo("uppercase;" + BUS_CONSUMER);
73 | assertThat(env.getProperty("spring.cloud.stream.function.bindings." + BUS_CONSUMER + "-in-0")).isEqualTo(INPUT);
74 | assertThat(env.getProperty("spring.cloud.stream.bindings." + INPUT + ".destination"))
75 | .isEqualTo("mydestination");
76 | assertThat(env.getProperty("spring.cloud.stream.bindings." + OUTPUT + ".destination"))
77 | .isEqualTo("mydestination");
78 | assertThat(env.getProperty(idKey)).isEqualTo("app:1");
79 | assertThat(env.getPropertySources().contains(OVERRIDES_PROPERTY_SOURCE_NAME));
80 | assertThat(env.getPropertySources().contains(DEFAULTS_PROPERTY_SOURCE_NAME));
81 | }
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/test/java/org/springframework/cloud/bus/ConditionalOnBusEnabledTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import org.junit.After;
20 | import org.junit.Rule;
21 | import org.junit.Test;
22 | import org.junit.rules.ExpectedException;
23 |
24 | import org.springframework.boot.test.util.TestPropertyValues;
25 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
26 | import org.springframework.context.annotation.Bean;
27 | import org.springframework.context.annotation.Configuration;
28 |
29 | import static org.assertj.core.api.Assertions.assertThat;
30 |
31 | /**
32 | * @author Spencer Gibb
33 | */
34 | public class ConditionalOnBusEnabledTests {
35 |
36 | /**
37 | * {@link ExpectedException} rule for verifying thrown exceptions.
38 | */
39 | @Rule
40 | public ExpectedException thrown = ExpectedException.none();
41 |
42 | private AnnotationConfigApplicationContext context;
43 |
44 | @After
45 | public void tearDown() {
46 | if (this.context != null) {
47 | this.context.close();
48 | }
49 | }
50 |
51 | @Test
52 | public void busEnabledTrue() {
53 | load(MyBusEnabledConfig.class, ConditionalOnBusEnabled.SPRING_CLOUD_BUS_ENABLED + ":true");
54 | assertThat(this.context.containsBean("foo")).as("missing bean from @ConditionalOnBusEnabled config").isTrue();
55 | }
56 |
57 | @Test
58 | public void busEnabledMissing() {
59 | load(MyBusEnabledConfig.class);
60 | assertThat(this.context.containsBean("foo")).as("missing bean from @ConditionalOnBusEnabled config").isTrue();
61 | }
62 |
63 | @Test
64 | public void busDisabled() {
65 | load(MyBusEnabledConfig.class, ConditionalOnBusEnabled.SPRING_CLOUD_BUS_ENABLED + ":false");
66 | assertThat(this.context.containsBean("foo")).as("bean exists from disabled @ConditionalOnBusEnabled config")
67 | .isFalse();
68 | }
69 |
70 | private void load(Class> config, String... environment) {
71 | this.context = new AnnotationConfigApplicationContext();
72 | TestPropertyValues.of(environment).applyTo(this.context);
73 | this.context.register(config);
74 | this.context.refresh();
75 | }
76 |
77 | @Configuration(proxyBeanMethods = false)
78 | @ConditionalOnBusEnabled
79 | protected static class MyBusEnabledConfig {
80 |
81 | @Bean
82 | public String foo() {
83 | return "foo";
84 | }
85 |
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/test/java/org/springframework/cloud/bus/PathServiceMatcherTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import java.util.Collections;
20 | import java.util.Map;
21 |
22 | import org.junit.Before;
23 | import org.junit.Test;
24 |
25 | import org.springframework.cloud.bus.event.EnvironmentChangeRemoteApplicationEvent;
26 | import org.springframework.util.AntPathMatcher;
27 |
28 | import static org.assertj.core.api.Assertions.assertThat;
29 |
30 | /**
31 | * @author Dave Syer
32 | *
33 | */
34 | public class PathServiceMatcherTests {
35 |
36 | private static final Map EMPTY_MAP = Collections.emptyMap();
37 |
38 | private ServiceMatcher matcher;
39 |
40 | @Before
41 | public void init() {
42 | initMatcher("one:two:8888");
43 | }
44 |
45 | private void initMatcher(String id) {
46 | BusProperties properties = new BusProperties();
47 | properties.setId(id);
48 | DefaultBusPathMatcher pathMatcher = new DefaultBusPathMatcher(new AntPathMatcher(":"));
49 | this.matcher = new PathServiceMatcher(pathMatcher, properties.getId());
50 | }
51 |
52 | @Test
53 | public void fromSelf() {
54 | assertThat(this.matcher
55 | .isFromSelf(new EnvironmentChangeRemoteApplicationEvent(this, "one:two:8888", "foo:bar:spam", EMPTY_MAP)))
56 | .isTrue();
57 | }
58 |
59 | @Test
60 | public void forSelf() {
61 | assertThat(this.matcher
62 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "one:two:8888", EMPTY_MAP)))
63 | .isTrue();
64 | }
65 |
66 | @Test
67 | public void forSelfWithWildcard() {
68 | assertThat(this.matcher
69 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "one:two:*", EMPTY_MAP)))
70 | .isTrue();
71 | }
72 |
73 | @Test
74 | public void forSelfWithGlobalWildcard() {
75 | assertThat(this.matcher
76 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "**", EMPTY_MAP))).isTrue();
77 | }
78 |
79 | @Test
80 | public void forSelfWithWildcardName() {
81 | assertThat(this.matcher
82 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "o*", EMPTY_MAP))).isTrue();
83 | }
84 |
85 | @Test
86 | public void forSelfWithWildcardNameAndProfile() {
87 | assertThat(this.matcher
88 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "o*:t*", EMPTY_MAP))).isTrue();
89 | }
90 |
91 | @Test
92 | public void forSelfWithWildcardString() {
93 | assertThat(this.matcher
94 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "o*", EMPTY_MAP))).isTrue();
95 | }
96 |
97 | @Test
98 | public void notForSelfWithWildCardNameAndMismatchingProfile() {
99 | assertThat(this.matcher
100 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "o*:f*", EMPTY_MAP)))
101 | .isFalse();
102 | }
103 |
104 | @Test
105 | public void forSelfWithDoubleWildcard() {
106 | assertThat(this.matcher
107 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "one:**", EMPTY_MAP)))
108 | .isTrue();
109 | }
110 |
111 | @Test
112 | public void forSelfWithNoWildcard() {
113 | assertThat(this.matcher
114 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "one", EMPTY_MAP))).isTrue();
115 | }
116 |
117 | @Test
118 | public void forSelfWithProfileNoWildcard() {
119 | assertThat(this.matcher
120 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "one:two", EMPTY_MAP)))
121 | .isTrue();
122 | }
123 |
124 | @Test
125 | public void notForSelf() {
126 | assertThat(this.matcher
127 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "one:two:9999", EMPTY_MAP)))
128 | .isFalse();
129 | }
130 |
131 | @Test
132 | public void notFromSelf() {
133 | assertThat(this.matcher
134 | .isFromSelf(new EnvironmentChangeRemoteApplicationEvent(this, "one:two:9999", "foo:bar:spam", EMPTY_MAP)))
135 | .isFalse();
136 | }
137 |
138 | /**
139 | * see gh-678.
140 | */
141 | @Test
142 | public void forSelfWithMultipleProfiles() {
143 | initMatcher("customerportal:dev,cloud:80");
144 | assertThat(this.matcher.isForSelf(
145 | new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "customerportal:cloud:*", EMPTY_MAP)))
146 | .isTrue();
147 | }
148 |
149 | /**
150 | * see gh-678.
151 | */
152 | @Test
153 | public void notForSelfWithMultipleProfiles() {
154 | initMatcher("customerportal:dev,cloud:80");
155 | assertThat(this.matcher
156 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "bar:cloud:*", EMPTY_MAP)))
157 | .isFalse();
158 | }
159 |
160 | /**
161 | * see gh-678.
162 | */
163 | @Test
164 | public void notForSelfWithMultipleProfilesDifferentPort() {
165 | initMatcher("customerportal:dev,cloud:80");
166 | assertThat(this.matcher.isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam",
167 | "customerportal:cloud:8008", EMPTY_MAP)))
168 | .isFalse();
169 | }
170 |
171 | }
172 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/test/java/org/springframework/cloud/bus/PathServiceMatcherWithConfigNamesTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import java.util.Collections;
20 | import java.util.Map;
21 |
22 | import org.junit.Before;
23 | import org.junit.Test;
24 |
25 | import org.springframework.cloud.bus.event.EnvironmentChangeRemoteApplicationEvent;
26 | import org.springframework.util.AntPathMatcher;
27 |
28 | import static org.assertj.core.api.Assertions.assertThat;
29 |
30 | /**
31 | * @author Stefan Pfeiffer
32 | *
33 | */
34 | public class PathServiceMatcherWithConfigNamesTests {
35 |
36 | private static final Map EMPTY_MAP = Collections.emptyMap();
37 |
38 | private ServiceMatcher matcher;
39 |
40 | @Before
41 | public void init() {
42 | initMatcher("otherid:two:8888", new String[] { "one", "three" });
43 | }
44 |
45 | private void initMatcher(String id, String[] configNames) {
46 | BusProperties properties = new BusProperties();
47 | properties.setId(id);
48 | DefaultBusPathMatcher pathMatcher = new DefaultBusPathMatcher(new AntPathMatcher(":"));
49 | this.matcher = new PathServiceMatcher(pathMatcher, properties.getId(), configNames);
50 | }
51 |
52 | @Test
53 | public void forSelfWithWildcard() {
54 | assertThat(this.matcher
55 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "one:two:*", EMPTY_MAP)))
56 | .isTrue();
57 | }
58 |
59 | @Test
60 | public void forSelfWithWildcardAndOtherConfigName() {
61 | assertThat(this.matcher
62 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "three:two:*", EMPTY_MAP)))
63 | .isTrue();
64 | }
65 |
66 | @Test
67 | public void forSelfWithGlobalWildcard() {
68 | assertThat(this.matcher
69 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "**", EMPTY_MAP))).isTrue();
70 | }
71 |
72 | @Test
73 | public void forSelfWithWildcardName() {
74 | assertThat(this.matcher
75 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "o*", EMPTY_MAP))).isTrue();
76 | }
77 |
78 | @Test
79 | public void forSelfWithWildcardNameAndProfile() {
80 | assertThat(this.matcher
81 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "o*:t*", EMPTY_MAP))).isTrue();
82 | }
83 |
84 | @Test
85 | public void forSelfWithWildcardString() {
86 | assertThat(this.matcher
87 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "o*", EMPTY_MAP))).isTrue();
88 | }
89 |
90 | @Test
91 | public void notForSelfWithWildCardNameAndMismatchingProfile() {
92 | assertThat(this.matcher
93 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "o*:f*", EMPTY_MAP)))
94 | .isFalse();
95 | }
96 |
97 | @Test
98 | public void forSelfWithDoubleWildcard() {
99 | assertThat(this.matcher
100 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "one:**", EMPTY_MAP)))
101 | .isTrue();
102 | }
103 |
104 | @Test
105 | public void forSelfWithNoWildcard() {
106 | assertThat(this.matcher
107 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "one", EMPTY_MAP))).isTrue();
108 | }
109 |
110 | @Test
111 | public void forSelfWithProfileNoWildcard() {
112 | assertThat(this.matcher
113 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "one:two", EMPTY_MAP)))
114 | .isTrue();
115 | }
116 |
117 | @Test
118 | public void notForSelf() {
119 | assertThat(this.matcher
120 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "one:two:9999", EMPTY_MAP)))
121 | .isFalse();
122 | }
123 |
124 | @Test
125 | public void forSelfWithMultipleProfiles() {
126 | initMatcher("customerportal:dev,cloud:80", new String[] { "one", "three" });
127 | assertThat(this.matcher
128 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "one:cloud:*", EMPTY_MAP)))
129 | .isTrue();
130 | }
131 |
132 | @Test
133 | public void notForSelfWithMultipleProfiles() {
134 | initMatcher("customerportal:dev,cloud:80", new String[] { "one", "three" });
135 | assertThat(this.matcher
136 | .isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam", "bar:cloud:*", EMPTY_MAP)))
137 | .isFalse();
138 | }
139 |
140 | @Test
141 | public void notForSelfWithMultipleProfilesDifferentPort() {
142 | initMatcher("customerportal:dev,cloud:80", new String[] { "one", "three" });
143 | assertThat(this.matcher.isForSelf(new EnvironmentChangeRemoteApplicationEvent(this, "foo:bar:spam",
144 | "customerportal:cloud:8008", EMPTY_MAP)))
145 | .isFalse();
146 | }
147 |
148 | }
149 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/test/java/org/springframework/cloud/bus/RefreshListenerIntegrationTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013-2020 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus;
18 |
19 | import java.util.HashMap;
20 |
21 | import org.junit.Test;
22 | import org.junit.runner.RunWith;
23 |
24 | import org.springframework.beans.factory.annotation.Autowired;
25 | import org.springframework.boot.autoconfigure.SpringBootApplication;
26 | import org.springframework.boot.test.context.SpringBootTest;
27 | import org.springframework.boot.test.mock.mockito.MockBean;
28 | import org.springframework.boot.test.web.client.TestRestTemplate;
29 | import org.springframework.cloud.stream.binder.test.TestChannelBinderConfiguration;
30 | import org.springframework.context.annotation.Import;
31 | import org.springframework.http.HttpStatus;
32 | import org.springframework.test.context.junit4.SpringRunner;
33 |
34 | import static org.assertj.core.api.Assertions.assertThat;
35 | import static org.mockito.ArgumentMatchers.any;
36 | import static org.mockito.Mockito.times;
37 | import static org.mockito.Mockito.verify;
38 |
39 | /**
40 | * @author Ryan Baxter
41 | */
42 | @RunWith(SpringRunner.class)
43 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
44 | classes = RefreshListenerIntegrationTests.MyApp.class,
45 | properties = { "management.endpoints.web.exposure.include=*", "spring.application.name=foobar" })
46 | public class RefreshListenerIntegrationTests {
47 |
48 | @Autowired
49 | private TestRestTemplate rest;
50 |
51 | @MockBean
52 | private BusBridge busBridge;
53 |
54 | @Test
55 | public void testEndpoint() {
56 | System.out.println(rest.getForObject("/actuator", String.class));
57 | assertThat(rest.postForEntity("/actuator/busrefresh/demoapp", new HashMap<>(), String.class).getStatusCode())
58 | .isEqualTo(HttpStatus.NO_CONTENT);
59 | assertThat(rest.postForEntity("/actuator/busrefresh/foobar", new HashMap<>(), String.class).getStatusCode())
60 | .isEqualTo(HttpStatus.NO_CONTENT);
61 | verify(busBridge, times(2)).send(any());
62 | }
63 |
64 | @SpringBootApplication
65 | @Import(TestChannelBinderConfiguration.class)
66 | static class MyApp {
67 |
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/test/java/org/springframework/cloud/bus/endpoint/RefreshBusEndpointTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.endpoint;
18 |
19 | import org.junit.Test;
20 |
21 | import static org.assertj.core.api.Assertions.assertThat;
22 |
23 | /**
24 | * @author Dave Syer
25 | */
26 | public class RefreshBusEndpointTests {
27 |
28 | @Test
29 | public void instanceId() throws Exception {
30 | RefreshBusEndpoint endpoint = new RefreshBusEndpoint(null, "foo",
31 | originalDestination -> () -> originalDestination);
32 | assertThat(endpoint.getInstanceId()).isEqualTo("foo");
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/test/java/org/springframework/cloud/bus/event/test/TestRemoteApplicationEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event.test;
18 |
19 | import org.springframework.cloud.bus.event.RemoteApplicationEvent;
20 |
21 | @SuppressWarnings("serial")
22 | public class TestRemoteApplicationEvent extends RemoteApplicationEvent {
23 |
24 | @SuppressWarnings("unused")
25 | private TestRemoteApplicationEvent() {
26 | }
27 |
28 | protected TestRemoteApplicationEvent(Object source, String originService, String destinationService) {
29 | super(source, originService, destinationService);
30 | }
31 |
32 | protected TestRemoteApplicationEvent(Object source, String originService) {
33 | super(source, originService);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/test/java/org/springframework/cloud/bus/event/test/TypedRemoteApplicationEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.event.test;
18 |
19 | import com.fasterxml.jackson.annotation.JsonTypeName;
20 |
21 | import org.springframework.cloud.bus.event.RemoteApplicationEvent;
22 |
23 | @SuppressWarnings("serial")
24 | @JsonTypeName("typed")
25 | public class TypedRemoteApplicationEvent extends RemoteApplicationEvent {
26 |
27 | @SuppressWarnings("unused")
28 | private TypedRemoteApplicationEvent() {
29 | }
30 |
31 | protected TypedRemoteApplicationEvent(Object source, String originService, String destinationService) {
32 | super(source, originService, destinationService);
33 | }
34 |
35 | protected TypedRemoteApplicationEvent(Object source, String originService) {
36 | super(source, originService);
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/test/java/org/springframework/cloud/bus/jackson/RemoteApplicationEventScanTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.jackson;
18 |
19 | import java.util.ArrayList;
20 | import java.util.Arrays;
21 | import java.util.LinkedHashSet;
22 | import java.util.List;
23 |
24 | import com.fasterxml.jackson.databind.ObjectMapper;
25 | import com.fasterxml.jackson.databind.jsontype.NamedType;
26 | import org.junit.Test;
27 | import test.foo.bar.FooBarTestRemoteApplicationEvent;
28 |
29 | import org.springframework.boot.Banner;
30 | import org.springframework.boot.WebApplicationType;
31 | import org.springframework.boot.builder.SpringApplicationBuilder;
32 | import org.springframework.cloud.bus.event.AckRemoteApplicationEvent;
33 | import org.springframework.cloud.bus.event.EnvironmentChangeRemoteApplicationEvent;
34 | import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
35 | import org.springframework.cloud.bus.event.ShutdownRemoteApplicationEvent;
36 | import org.springframework.cloud.bus.event.UnknownRemoteApplicationEvent;
37 | import org.springframework.cloud.bus.event.test.TestRemoteApplicationEvent;
38 | import org.springframework.cloud.bus.event.test.TypedRemoteApplicationEvent;
39 | import org.springframework.cloud.bus.jackson.SubtypeModuleTests.AnotherRemoteApplicationEvent;
40 | import org.springframework.cloud.bus.jackson.SubtypeModuleTests.MyRemoteApplicationEvent;
41 | import org.springframework.context.ConfigurableApplicationContext;
42 | import org.springframework.context.annotation.Configuration;
43 | import org.springframework.context.annotation.Import;
44 | import org.springframework.test.util.ReflectionTestUtils;
45 |
46 | import static org.assertj.core.api.Assertions.assertThat;
47 |
48 | public class RemoteApplicationEventScanTests {
49 |
50 | private BusJacksonMessageConverter converter;
51 |
52 | @Test
53 | public void importingClassMetadataPackageRegistered() {
54 | this.converter = createTestContext(DefaultConfig.class).getBean(BusJacksonMessageConverter.class);
55 |
56 | assertConverterBeanAfterPropertiesSet(
57 | new String[] { "org.springframework.cloud.bus.jackson", "org.springframework.cloud.bus.event" },
58 | AnotherRemoteApplicationEvent.class, MyRemoteApplicationEvent.class, TestRemoteApplicationEvent.class,
59 | TypedRemoteApplicationEvent.class);
60 | }
61 |
62 | @Test
63 | public void annotationValuePackagesRegistered() {
64 | this.converter = createTestContext(ValueConfig.class).getBean(BusJacksonMessageConverter.class);
65 |
66 | assertConverterBeanAfterPropertiesSet(
67 | new String[] { "test.foo.bar", "com.acme", "org.springframework.cloud.bus.event" },
68 | FooBarTestRemoteApplicationEvent.class, TestRemoteApplicationEvent.class,
69 | TypedRemoteApplicationEvent.class);
70 | }
71 |
72 | @Test
73 | public void annotationValueBasePackagesRegistered() {
74 | this.converter = createTestContext(BasePackagesConfig.class).getBean(BusJacksonMessageConverter.class);
75 |
76 | assertConverterBeanAfterPropertiesSet(
77 | new String[] { "test.foo.bar", "fizz.buzz", "com.acme", "org.springframework.cloud.bus.event" },
78 | FooBarTestRemoteApplicationEvent.class, TestRemoteApplicationEvent.class,
79 | TypedRemoteApplicationEvent.class);
80 | }
81 |
82 | @Test
83 | public void annotationBasePackagesRegistered() {
84 | this.converter = createTestContext(BasePackageClassesConfig.class).getBean(BusJacksonMessageConverter.class);
85 |
86 | assertConverterBeanAfterPropertiesSet(
87 | new String[] { "org.springframework.cloud.bus.event.test", "org.springframework.cloud.bus.event" },
88 | TestRemoteApplicationEvent.class, TypedRemoteApplicationEvent.class);
89 | }
90 |
91 | private ConfigurableApplicationContext createTestContext(Class> configuration) {
92 | return new SpringApplicationBuilder(configuration).web(WebApplicationType.NONE)
93 | .bannerMode(Banner.Mode.OFF)
94 | .run();
95 | }
96 |
97 | private void assertConverterBeanAfterPropertiesSet(final String[] expectedPackageToScan,
98 | final Class>... expectedRegisterdClasses) {
99 | final ObjectMapper mapper = (ObjectMapper) ReflectionTestUtils.getField(this.converter, "mapper");
100 |
101 | @SuppressWarnings("unchecked")
102 | final LinkedHashSet registeredSubtypes = (LinkedHashSet) ReflectionTestUtils
103 | .getField(mapper.getSubtypeResolver(), "_registeredSubtypes");
104 |
105 | final List> expectedRegisterdClassesAsList = new ArrayList<>(Arrays.asList(expectedRegisterdClasses));
106 | addStandardSpringCloudEventBusEvents(expectedRegisterdClassesAsList);
107 |
108 | assertThat(expectedRegisterdClassesAsList.size() == registeredSubtypes.size())
109 | .as("Wrong RemoteApplicationEvent classes are registerd in object mapper")
110 | .isTrue();
111 |
112 | for (final NamedType namedType : registeredSubtypes) {
113 | assertThat(expectedRegisterdClassesAsList.contains(namedType.getType())).isTrue();
114 | }
115 |
116 | assertThat(Arrays.asList((String[]) ReflectionTestUtils.getField(this.converter, "packagesToScan")))
117 | .as("RemoteApplicationEvent packages not registered")
118 | .contains(expectedPackageToScan);
119 |
120 | }
121 |
122 | private void addStandardSpringCloudEventBusEvents(final List> expectedRegisterdClassesAsList) {
123 | expectedRegisterdClassesAsList.add(AckRemoteApplicationEvent.class);
124 | expectedRegisterdClassesAsList.add(EnvironmentChangeRemoteApplicationEvent.class);
125 | expectedRegisterdClassesAsList.add(RefreshRemoteApplicationEvent.class);
126 | expectedRegisterdClassesAsList.add(UnknownRemoteApplicationEvent.class);
127 | expectedRegisterdClassesAsList.add(ShutdownRemoteApplicationEvent.class);
128 | }
129 |
130 | @Configuration(proxyBeanMethods = false)
131 | @RemoteApplicationEventScan
132 | static class DefaultConfig {
133 |
134 | }
135 |
136 | @Configuration(proxyBeanMethods = false)
137 | @RemoteApplicationEventScan({ "com.acme", "test.foo.bar" })
138 | static class ValueConfig {
139 |
140 | }
141 |
142 | @Configuration(proxyBeanMethods = false)
143 | @Import(ExtraBasePackagesConfig.class)
144 | @RemoteApplicationEventScan(basePackages = { "com.acme", "test.foo.bar" })
145 | static class BasePackagesConfig {
146 |
147 | }
148 |
149 | @Configuration(proxyBeanMethods = false)
150 | @RemoteApplicationEventScan(basePackages = { "fizz.buzz" })
151 | static class ExtraBasePackagesConfig {
152 |
153 | }
154 |
155 | @Configuration(proxyBeanMethods = false)
156 | @RemoteApplicationEventScan(basePackageClasses = TestRemoteApplicationEvent.class)
157 | static class BasePackageClassesConfig {
158 |
159 | }
160 |
161 | }
162 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/test/java/org/springframework/cloud/bus/jackson/SerializationTests.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package org.springframework.cloud.bus.jackson;
18 |
19 | import java.util.Collections;
20 |
21 | import com.fasterxml.jackson.databind.ObjectMapper;
22 | import org.junit.Test;
23 |
24 | import org.springframework.cloud.bus.event.EnvironmentChangeRemoteApplicationEvent;
25 | import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
26 | import org.springframework.cloud.bus.event.RemoteApplicationEvent;
27 |
28 | import static org.assertj.core.api.Assertions.assertThat;
29 |
30 | /**
31 | * @author Dave Syer
32 | *
33 | */
34 | public class SerializationTests {
35 |
36 | ObjectMapper mapper = new ObjectMapper();
37 |
38 | @Test
39 | public void vanillaDeserialize() throws Exception {
40 | this.mapper.registerModule(
41 | new SubtypeModule(RefreshRemoteApplicationEvent.class, EnvironmentChangeRemoteApplicationEvent.class));
42 | EnvironmentChangeRemoteApplicationEvent source = new EnvironmentChangeRemoteApplicationEvent(this, "foo", "bar",
43 | Collections.emptyMap());
44 | String value = this.mapper.writeValueAsString(source);
45 | RemoteApplicationEvent event = this.mapper.readValue(value, RemoteApplicationEvent.class);
46 | assertThat(event instanceof EnvironmentChangeRemoteApplicationEvent).isTrue();
47 | assertThat(event.getId()).isNotNull();
48 | assertThat(event.getId().equals(source.getId())).isTrue();
49 | }
50 |
51 | @Test
52 | public void deserializeOldValueWithNoId() throws Exception {
53 | this.mapper.registerModule(
54 | new SubtypeModule(RefreshRemoteApplicationEvent.class, EnvironmentChangeRemoteApplicationEvent.class));
55 | EnvironmentChangeRemoteApplicationEvent source = new EnvironmentChangeRemoteApplicationEvent(this, "foo", "bar",
56 | Collections.emptyMap());
57 | String value = this.mapper.writeValueAsString(source);
58 | value = value.replaceAll(",\"id\":\"[a-f0-9-]*\"", "");
59 | RemoteApplicationEvent event = this.mapper.readValue(value, RemoteApplicationEvent.class);
60 | assertThat(event instanceof EnvironmentChangeRemoteApplicationEvent).isTrue();
61 | assertThat(event.getId()).isNotNull();
62 | assertThat(event.getId().equals(source.getId())).isFalse();
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/test/java/test/foo/bar/FooBarTestRemoteApplicationEvent.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2019 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package test.foo.bar;
18 |
19 | import org.springframework.cloud.bus.event.RemoteApplicationEvent;
20 |
21 | @SuppressWarnings("serial")
22 | public class FooBarTestRemoteApplicationEvent extends RemoteApplicationEvent {
23 |
24 | @SuppressWarnings("unused")
25 | private FooBarTestRemoteApplicationEvent() {
26 | }
27 |
28 | protected FooBarTestRemoteApplicationEvent(final Object source, final String originService,
29 | final String destinationService) {
30 | super(source, originService, destinationService);
31 | }
32 |
33 | protected FooBarTestRemoteApplicationEvent(final Object source, final String originService) {
34 | super(source, originService);
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/spring-cloud-bus/src/test/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.main.web-environment:false
2 |
--------------------------------------------------------------------------------
/spring-cloud-starter-bus-amqp/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.springframework.cloud
8 | spring-cloud-bus-parent
9 | 5.0.0-SNAPSHOT
10 | ..
11 |
12 | spring-cloud-starter-bus-amqp
13 | spring-cloud-starter-bus-amqp
14 | Spring Cloud Starter
15 | https://projects.spring.io/spring-cloud
16 |
17 | Pivotal Software, Inc.
18 | https://www.spring.io
19 |
20 |
21 | ${basedir}/../..
22 |
23 |
24 |
25 | org.springframework.cloud
26 | spring-cloud-starter-stream-rabbit
27 |
28 |
29 | org.springframework.cloud
30 | spring-cloud-bus
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/spring-cloud-starter-bus-kafka/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.springframework.cloud
8 | spring-cloud-bus-parent
9 | 5.0.0-SNAPSHOT
10 | ..
11 |
12 | spring-cloud-starter-bus-kafka
13 | spring-cloud-starter-bus-kafka
14 | Spring Cloud Starter
15 | https://projects.spring.io/spring-cloud
16 |
17 | Pivotal Software, Inc.
18 | https://www.spring.io
19 |
20 |
21 | ${basedir}/../..
22 |
23 |
24 |
25 | org.springframework.cloud
26 | spring-cloud-starter-stream-kafka
27 |
28 |
29 | org.springframework.cloud
30 | spring-cloud-bus
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/spring-cloud-starter-bus-stream/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.springframework.cloud
8 | spring-cloud-bus-parent
9 | 5.0.0-SNAPSHOT
10 | ..
11 |
12 | spring-cloud-starter-bus-stream
13 | spring-cloud-starter-bus-stream
14 | Spring Cloud Starter
15 | https://projects.spring.io/spring-cloud
16 |
17 | Pivotal Software, Inc.
18 | https://www.spring.io
19 |
20 |
21 | ${basedir}/../..
22 |
23 |
24 |
25 | org.springframework.cloud
26 | spring-cloud-stream
27 |
28 |
29 | org.springframework.cloud
30 | spring-cloud-bus
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/checkstyle/checkstyle-suppressions.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------