Skip to content

feat(messaging): connect to an external ActiveMQ broker - #6870

Merged
iliyan-velichkov merged 4 commits into
masterfrom
external-messaging-broker
Aug 20, 2026
Merged

feat(messaging): connect to an external ActiveMQ broker#6870
iliyan-velichkov merged 4 commits into
masterfrom
external-messaging-broker

Conversation

@iliyan-velichkov

Copy link
Copy Markdown
Contributor

What

Messaging can now be pointed at an external ActiveMQ broker instead of the embedded one:

DIRIGIBLE_MESSAGING_BROKER_URL=tcp://activemq:61616      # ssl://…, failover:(…) also work
DIRIGIBLE_MESSAGING_BROKER_USERNAME=…                    # optional
DIRIGIBLE_MESSAGING_BROKER_PASSWORD=…                    # optional

Unset (or blank) — which is every existing deployment — keeps today's behaviour exactly: an
in-process BrokerService reached over vm://localhost.

Why

Several deployments sharing one broker is what makes cross-deployment queues usable (the global:
destinations shipped in v14.29.0 assume it), and a managed broker such as Amazon MQ is what a
multi-node or containerised deployment wants rather than a broker embedded in each node.

How

MessagingConfig becomes two configurations selected by whether a broker URL is configured:

EmbeddedBrokerMessagingConfig ExternalBrokerMessagingConfig
condition EmbeddedMessagingBrokerCondition ExternalMessagingBrokerCondition
connection factory vm://localhost?create=false configured URL + credentials
ActiveMQBroker bean yes no
ActiveMQConnection / ActiveMQSession yes yes

The conditions are the exact negation of one another, so exactly one always applies.

Nothing downstream changes: every consumer — the .listener artifacts, the client-Java listeners in
engine-java, MessagingFacade — reaches the broker through ActiveMQConnectionArtifactsFactory,
which resolves the ActiveMQConnectionFactory by type. Swapping that one bean is the whole
change.

Two consumers of the now-optional broker bean were adjusted:

  • CloseActiveMQResourcesApplicationListener takes an ObjectProvider<BrokerService> and still
    closes the listeners, session and connection in both modes.
  • MessagingMonitoringService and MessagingMonitoringEndpoint read broker state out of the
    in-process object, so they are conditional on the embedded mode. With an external broker they are
    not registered and the messaging perspective's calls answer 404
    — such a broker is administered
    from its own console. This is the one user-visible behaviour change, and only in the new mode.

Notes for reviewers

  • The conditions read DirigibleConfig, not the Spring Environment — this is the first
    hand-written Condition in the repo. Dirigible resolves a key across its own layers and a value
    placed there programmatically (Configuration.set, which is how the IT selects the mode) never
    reaches the Environment, so @ConditionalOnProperty cannot see it.
  • DIRIGIBLE_MESSAGING_USE_DEFAULT_DATABASE moved into the DirigibleConfig enum (its key had been
    a bare string literal plus a staticParams entry; getConfigParams() unions the enum keys, so it
    stays exposed). It configures the embedded broker's persistence only and is logged as ignored in
    external mode.
  • An unreachable external broker fails startup, deliberately — matching the embedded broker's
    IllegalStateException.
  • build/helm-charts/dirigible/templates/dirigible.yaml was not extended with the new keys; say
    the word if the chart should carry them.

Testing

  • mvn -pl components/engine/engine-listeners -am clean install -P unit-tests — 64 tests pass.
    New: MessagingBrokerConditionsTest (mode selection, blank handling, mutual exclusivity),
    MessagingConfigSelectionTest (pins the bean-graph shape of both modes),
    ExternalBrokerMessagingConfigTest (URL/credentials, anonymous connection, the ignored-config log,
    and that the password never reaches the log). Updated:
    CloseActiveMQResourcesApplicationListenerTest.
  • New ExternalMessagingBrokerIT starts a real ActiveMQ on a random TCP port, points the platform at
    it before the context exists, and asserts a .listener handler consumes a published message, that
    no BrokerService bean exists, that the connection factory carries the configured URL, and that
    the monitoring beans are absent.
  • Embedded-mode regression: MessagingFacadeIT, GlobalDestinationIT and JavaListenerTenantIT
    pass unchanged.
  • mvn -T 1C formatter:validate clean.

🤖 Generated with Claude Code

iliyan-velichkov and others added 4 commits August 20, 2026 10:51
Adds DIRIGIBLE_MESSAGING_BROKER_URL/_USERNAME/_PASSWORD so a deployment can
point its messaging at an external broker instead of the embedded one, and
adopts DIRIGIBLE_MESSAGING_USE_DEFAULT_DATABASE into the enum so its key has a
single owner (it was a bare string literal read in MessagingConfig plus a
staticParams entry; getConfigParams unions the enum keys, so it stays exposed).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The messaging beans were one configuration that always started an in-process
broker and attached to it over vm://localhost. It is now split in two, selected
by whether a broker URL is configured: the embedded half is the previous
configuration unchanged, the external half builds the connection factory from
the configured URL and credentials and defines no BrokerService at all.

Everything downstream is untouched: both halves keep the ActiveMQConnection and
ActiveMQSession bean names, and every consumer - the .listener artifacts, the
client-Java listeners, the messaging facade - reaches the broker through
ActiveMQConnectionArtifactsFactory, which resolves the connection factory by
type.

The conditions read Dirigible's own configuration rather than the Spring
Environment, because a value set programmatically (how the integration tests
select the mode) never reaches the Environment.

Shutdown no longer requires a broker to exist: with an external broker there is
none to stop, and the connection and session are still closed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ed broker

Both the service and its endpoint read state out of the in-process BrokerService
object, which does not exist when the messaging is pointed at an external
broker - as written, the context would fail to start there. They are now
conditional on the embedded mode, so an external-broker deployment simply has no
monitoring endpoints and the perspective's calls answer 404; that broker is
administered from its own console.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Starts a real ActiveMQ on a TCP port from the test, points the platform at it
before the Spring context exists, and asserts what external mode has to hold: a
.listener handler consumes a published message, no BrokerService bean was
created, the connection factory carries the configured URL, the connection and
session beans the engine consumes are still there, and the monitoring beans -
which read the in-process broker - are absent instead of failing the startup.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
String username = DirigibleConfig.MESSAGING_BROKER_USERNAME.getStringValue();

warnIfEmbeddedOnlyConfigIsSet();
LOGGER.info("Messaging will use the external ActiveMQ broker at [{}] with user [{}]", brokerUrl, username);
String username = DirigibleConfig.MESSAGING_BROKER_USERNAME.getStringValue();

warnIfEmbeddedOnlyConfigIsSet();
LOGGER.info("Messaging will use the external ActiveMQ broker at [{}] with user [{}]", brokerUrl, username);
@iliyan-velichkov
iliyan-velichkov merged commit c42d4fa into master Aug 20, 2026
10 checks passed
@iliyan-velichkov
iliyan-velichkov deleted the external-messaging-broker branch August 20, 2026 09:19
iliyan-velichkov added a commit to dirigible-io/dirigible-io.github.io that referenced this pull request Aug 20, 2026
…209)

Documents DIRIGIBLE_MESSAGING_BROKER_URL and its credentials
(eclipse-dirigible/dirigible#6870): a Messaging section on both env-var pages, a
"Broker - embedded or external" section on the message-listeners page, and an
"Embedded broker only" note on the messaging perspective, whose endpoints answer
404 against an external broker.

Also corrects the pages that asserted an embedded-only broker - the producer SDK
page promised "no broker URL, no client configuration".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants