skip to content

What dependencies and configuration are required to enable Spring Cloud Bus refresh in a service?

level: middleimportance: should knowfreq 30%

answer

  1. One starter: bus-amqp OR bus-kafka
  2. spring-boot-starter-actuator
  3. Broker props: rabbitmq.host / kafka bootstrap
  4. expose busrefresh via exposure.include
  5. still need @RefreshScope / @ConfigurationProperties

basics

~10 s

Add one broker starter — spring-cloud-starter-bus-amqp (RabbitMQ) or spring-cloud-starter-bus-kafka — plus Actuator, point the app at a running broker, and expose the endpoint with management.endpoints.web.exposure.include=busrefresh. Then POST /actuator/busrefresh.

solid answer

~30 s

Three things. (1) Dependency: include exactly one Bus starter — spring-cloud-starter-bus-amqp for RabbitMQ or spring-cloud-starter-bus-kafka for Kafka; it pulls in Spring Cloud Stream and the binder. Also have spring-boot-starter-actuator. (2) Broker connectivity: standard properties like spring.rabbitmq.host/username/password or spring.kafka.bootstrap-servers so every instance connects to the same broker. (3) Expose the endpoint: management.endpoints.web.exposure.include=busrefresh (Actuator hides it by default). You also generally use it with spring-cloud-starter-config so instances actually have a Config Server to re-read from. With that in place, POST /actuator/busrefresh on any instance refreshes the cluster; add ?destination=app:** to scope it. Beans still need @RefreshScope or @ConfigurationProperties to pick up new values.

code

yaml · 19 lines
yaml
# build.gradle
dependencies {
  implementation 'org.springframework.cloud:spring-cloud-starter-bus-kafka'
  implementation 'org.springframework.boot:spring-boot-starter-actuator'
  implementation 'org.springframework.cloud:spring-cloud-starter-config'
}
# dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${scVersion}" } }

# application.yml
spring:
  kafka:
    bootstrap-servers: kafka:9092
  config:
    import: "optional:configserver:http://config-server:8888"
management:
  endpoints:
    web:
      exposure:
        include: busrefresh, busenv, health

go deeper

for a junior

Know: add a broker starter + actuator and expose busrefresh.

for a middle

List the two starters, the broker connection props, and the exposure.include requirement; note @RefreshScope still needed.

for a senior

Add the Stream-binder/BOM alignment detail and busrefresh vs bus-refresh naming history.

for a principal

Fold this into broker-selection and control-plane operability decisions.

**1. The starter.** Spring Cloud Bus ships as two convenience starters, differing only by broker: - **`spring-cloud-starter-bus-amqp`** → RabbitMQ (brings in the Rabbit Stream binder + spring-boot-starter-amqp). - **`spring-cloud-starter-bus-kafka`** → Apache Kafka (brings in the Kafka Stream binder). Include **exactly one**. Each transitively pulls in **Spring Cloud Stream**, which is the transport the Bus rides on. You also need **`spring-boot-starter-actuator`**, because `busrefresh` is an Actuator endpoint. In practice you also have **`spring-cloud-starter-config`** so the instance has a Config Server to re-fetch from on refresh (the Bus broadcasts the *signal*; the Config Server supplies the *values*). **2. Broker connectivity.** Every instance must reach the **same** broker so they share the `springCloudBus` destination: - RabbitMQ: `spring.rabbitmq.host`, `.port`, `.username`, `.password` (or a URI). - Kafka: `spring.kafka.bootstrap-servers` (and any binder/security props). If instances point at different brokers, refresh won't fan out. **3. Endpoint exposure.** Spring Boot Actuator exposes very few endpoints over HTTP by default. You must opt `busrefresh` in: ``` management.endpoints.web.exposure.include=busrefresh ``` (or a list including it, or `*` in non-prod). Forgetting this is the most common 'why is /actuator/busrefresh 404?' cause. In Spring Cloud 2.0+ the id is **`busrefresh`** (older docs say `bus-refresh`). The related property-push endpoint is **`busenv`**. **4. Verifying.** `POST http://any-instance:8080/actuator/busrefresh` (empty body). To scope: `?destination=<app>:**` or `?destination=<app>:<port>`, matched against each instance's `spring.cloud.bus.id`. **5. Don't forget @RefreshScope.** Wiring the Bus is necessary but not sufficient — a value only *changes* at runtime if it lives in a `@RefreshScope` bean or a `@ConfigurationProperties` class. Plain singletons keep startup values. **Optional knobs.** `spring.cloud.bus.enabled=false` to disable, `spring.cloud.bus.refresh.enabled`, `spring.cloud.bus.env.enabled`, `spring.cloud.bus.destination` to rename the shared topic, and `spring.cloud.bus.ack.enabled` / `trace.enabled` for acknowledgement/trace events. **Version management.** Use the Spring Cloud BOM (`spring-cloud-dependencies`) so the Bus, Stream, and binder versions align with your Boot version — mismatches are a frequent source of binder startup failures.

  • Why does POST /actuator/busrefresh return 404 even though the Bus starter is on the classpath?
    Actuator does not expose the endpoint over HTTP by default. You must set management.endpoints.web.exposure.include to include busrefresh (or *). The bean exists but isn't web-exposed until then.
  • Can you switch from RabbitMQ to Kafka without changing application code?
    Largely yes — swap spring-cloud-starter-bus-amqp for spring-cloud-starter-bus-kafka and change the broker connection properties. The Bus uses Spring Cloud Stream binders, so the RemoteApplicationEvent logic is broker-agnostic; only the binder and connection config differ.

saying these in an interview costs you the question

  • Forgetting the exposure.include property and blaming the starter for a 404
  • Including both bus-amqp and bus-kafka starters at once
  • Thinking the Bus alone updates values without @RefreshScope/@ConfigurationProperties
  • Assuming no broker is needed because 'it's just Spring'

context