Releases: sudoitir/artemis-studio
Release list
2026.09.14
Fixed
-
Name the right capability in the console's uncertainty banner (c2add88f)
The SQL Console is gated on message I/O, which is unproven until a management
write has been attempted — but the banner said no management read had been
attempted, which is not what is unknown and not what settles it. It also
promised the first query would settle it, which a read cannot do. -
Keep an endpoint box inside the slot the layout reserved for it (d41a3fc7)
An endpoint whose name wrapped and which carried an error sentence — a stopped
backup, exactly the case the view exists for — grew taller than the 160px the
layout allots between the serving and standby rows, so it was drawn on top of
the box below it and out through its own pair's border.The box is now pinned to the geometry
layout.tspublishes (260x132) and the
two variable-length lines clamp to two lines each, with the full text on the
title and, as before, in the node's accessible name. Split-brain endpoints were
laid out 150px apart while being 190px wide, so those overlapped too; they are
now pitched by the box width.
2026.09.13
Fixed
-
Take the clock from Studio, and let the operator pick the timezone (6a970c39)
Every duration, expiry check and metric window in the UI was computed against
the browser's clock. An operator whose workstation ran four minutes fast saw
every request-reply flow age inflated by four minutes, a live API key rendered
asexpired, and an empty metrics chart with nothing saying why — the window it
asked the server for had not happened yet.Studio already refuses to trust a broker's clock (ADR-0053). The browser is one
more foreign clock, and it was the only one still taken on faith.What changes for you:
- Ages, staleness labels and token expiry now follow Studio's clock, not the
machine the browser runs on. On a correctly-synchronised workstation nothing
moves; on a skewed one, the numbers become right. - The metrics window and the queue drawer's chart are quantised on the server's
clock, so a skewed workstation no longer requests a range the server has no
samples for. - Timestamps now render in your own timezone by default, detected from the
browser, where they were previously always UTC. Settings → Display picks a
different one, including UTC to match container and broker logs. The choice is
per-browser, needs no permission, and is never reset once made. - Every absolute timestamp now names the offset it is written in (
Z,+03:30)
and is rendered to whole seconds, where before some carried milliseconds and
some did not. - The metric charts previously drew their axis in the browser's local zone while
every table beside them was UTC, with nothing disclosing the difference. Both
now follow the chosen zone.
How it works: a new
GET /api/v1/timereturns Studio's clock, and the client
measures its own offset NTP-style with round-trip bracketing — the same
estimator and the same constants asClockOffsetRegistry, so the two halves of
the system agree about method. A reading is only allowed to teach the estimate
when its round trip is at or near the best seen; an offset inside its own error
bar is held at zero rather than correcting by noise. The SSEpingalready
carried the server's clock and the client discarded it; it is now a drift
detector that asks for a real probe, never a measurement of its own, since a
one-way frame cannot measure its own latency. A wall-clock step — a laptop
waking, an NTP correction — is caught by comparingDate.now()against
performance.now(), the client-sideMonotonicClockWatch, and discards the
estimate rather than slowly unlearning it.web/src/app/time.tsstates the rule for the whole frontend: durations and
expiry against a server timestamp useserverNow(); a browser-stamped instant
entering such a comparison (TanStack'sdataUpdatedAtis the only one) is
normalised withtoServerMs()at the boundary; monotonic work keeps using
performance.now(). Three duplicate "ago" formatters and seven copies of the
absolute-timestamp formatter are folded into it.Known and deliberately out of scope: the queue detail drawer's chart window is
memoised on the range spec alone, so it is fixed at first render and does not
advance while the drawer stays open. That predates this change. - Ages, staleness labels and token expiry now follow Studio's clock, not the
2026.09.12
Added
-
Query messages across a cluster in SQL, with a live tail and an opt-in index (46c44883)
The SQL Console is a new screen at Clusters → SQL Console. It answers questions
that previously meant guessing a queue, walking pages by hand, and writing a JMS
selector that cannot see a message body at all:SELECT messageId, timestamp, props.tenant, body FROM "ORDER.*" WHERE priority > 4 AND body->>'orderId' = '4471' ORDER BY timestamp DESC LIMIT 500What it costs a broker is stated before it runs. The EXPLAIN strip says which
predicates the broker evaluates for free, which ones force Studio to read
messages, and roughly how many that is — and a query over the ceiling is refused
with the estimate and how to narrow it, rather than being run and truncated. The
fan-out is the existing browse loop behind the existing per-node rate limiter, so
a runaway query throttles itself against the broker.Every result says what it could not see. A node that did not answer is named
rather than left out, a result that stopped at a bound says which bound, a body
the management channel truncated is flagged because a body predicate over it can
be a false negative, and an empty grid distinguishes "no queue matched" from "the
queue is empty" from "a node was unreachable".Live tail streams matches as they arrive. It is a sample, not a capture: Studio
re-reads the queues every few seconds, and a message that arrives and is consumed
between two reads is never seen. The console says so permanently while tailing,
and reports the observed gap where it can measure one. A dropped connection is
not silently reopened — reopening would re-run an audited fan-out nobody asked
for twice.The message index is off until you turn it on, per queue, in Settings → Message
index. It keeps a copy of the messages Studio observes — headers, properties and
bodies — so the console can still find a message the broker has already handed
out. Because that is stored application payload, creating a subscription needs
the settings write permission, is audited, states what it stores before it is
confirmed, defaults to seven days' retention, and can be deleted with everything
it captured in one action that tells you the count first. Any indexed row can be
checked against the live broker: present, gone, or — when the read could not
settle it — unknown, never a guess.Everything here is read-only. Acting on a result row goes back through the
existing message operations, with their dry run, bulk cap and audit record.Requires a database migration (changeset 021), which Studio applies on startup.
It creates thepg_trgmextension; a database user without permission to do that
must have it created for them first:CREATE EXTENSION IF NOT EXISTS pg_trgm;New settings live under
artemis-studio.sql: target, scan, row and timeout caps,
the per-user concurrent query limit, the cost ceiling and the tail interval. The
packaged defaults are deliberately conservative.
2026.09.11
Added
-
Close a connection, a session, or an address's consumers (b91c6d88)
Studio could tell you which consumer was holding up a queue and could list
every connection behind it. It could not do the one thing that finding
implies. Closing a wedged consumer's connection returns its in-flight
messages to the queue so a healthy instance can take them — the most common
3am intervention on an Artemis cluster, and the reason people kept a JMX
console open next to Studio.The connections, sessions and consumers views gain a row action; the
addresses view gains a cluster-wide "close consumers" action. All four
preview before they act.What to know before you use it:
- A close by id names a node. This is the one mutating route in Studio
that is not a cluster-wide fan-out. A connection identifier is issued by,
and meaningful only on, the node that accepted the connection. Only the
address-scoped close names a cluster, and it reports per node. - A target that has already gone is a success, not an error. Rows come
from a cache, so by the time you click, the connection may be gone. The
requested state — that connection is not open — holds. Nothing retries: an
identifier can be reissued, so a retry may land on a different application. - Closing a consumer moves messages. Its in-flight messages return to
their queue with an increased delivery count, which can push one past its
maximum delivery attempts and into the dead-letter queue. The confirmation
states this, with the count where the broker reports it and an explicit
"not reported" where it does not. - You confirm against the client id, not the connection id. An operator
cannot verify thata3f1c9deis the right connection; they can recognise a
client id or a remote address. The audit row records the same, read
immediately before the close, because afterwards the identifier resolves to
nothing. - The address-scoped close is capped. It previews per node and is refused
abovesafety.bulk-capwithout an explicit override. A node that could not
be counted also demands the override: an incomplete total is a floor, not a
figure, and passing the cap on the nodes that happened to answer would wave
through exactly the close whose blast radius is unknown.
A new permission,
connection:close. Grant it explicitly — no message or
queue permission implies it. Authority over a cluster's messages says nothing
about authority to disconnect the applications producing them.MCP gains
connection_action, declared destructive and not idempotent,
previewing by default. Its confirmation is the client id the preview
returned, so a model that guesses cannot close anything.There is deliberately no "close all slow consumers". Slow-consumer detection
has false positives by construction, and an operation that selects its own
targets from a heuristic turns every one of them into a disconnected
production application. Detection informs; you name the target.See ADR-0057.
- A close by id names a node. This is the one mutating route in Studio
2026.09.10
Added
-
Make refresh, pause and the metric charts tell the truth (b25868e7)
The shell reported freshness, but three of its claims were wrong, and the
metrics page was wrong in a way a screenshot hides.Refresh now means your refresh. The control's busy state came from
cache-wideisFetching, so it spun on every background poll — a spinner that
never stops says nothing. It now tracks only the promise the operator started,
floored at 350ms so a fast refetch reads as an acknowledgement rather than a
flicker, and repeated activation joins the running refetch instead of aborting
and restarting it (cancelRefetch: false).Pause now holds. It stopped intervals but not mounts, so pausing and then
navigating silently resumed.refetchOnMountgoes through the same seam, gated
so a query that has never resolved still fetches once — pausing a screen to stop
it moving is not asking for an empty one. The paused control also renders
differently, rather than differing only inaria-pressed.Metric charts carry time. The x-axis was array position, so an omitted
bucket rendered flush against its neighbour — themetricscapability requires a
cold subject to show a gap, and it could not. The axis is now a numeric time
scale over the requested window. The live window was also frozen at page-open by
auseMemothat never re-ran; it now advances, quantized to the bucket width so
the query key changes once per bucket rather than once per second. A failed read
rendered as "No samples yet" — an absence presented as a fact — and now states
the failure.The dashboard around them is rebuilt: current depth, added/s, acked/s and
consumers as stat tiles that say "Not sampled" rather than showing zero; each
chart a titled panel with its unit; a table view of the window; and?subject=
to scope the whole page to one queue, linked from the queue drawer.Bounded views. Requests, events, audit and DLQ rendered every row they were
given. They page now, through one shared pager, with events and audit moved onto
the virtualised grid. Above 24 nodes the topology canvas collapses each pair to
one node, drops edge labels, renders only what is visible, and says that detail
has been reduced.Two fixes found while shooting the screenshots. The command palette mounts on
every route and asked for/clusters//queuesoutside a cluster — a 400, and one
errored observed query put the whole shell into its offline state, so every
cluster-less screen claimed Studio had lost the brokers. And the consumer chart's
y-axis rounded fractional ticks to integers, printing "0" five times beside bars
of visibly different heights.Colour. The latency panel used the reserved warning and danger colours as
series colours; p50/p95/p99 are now a validated sequential blue ramp. The depth
chart's two neutral series failed the normal-vision separation floor and are now
one hue distinguished by mark shape. Both checked with the palette validator in
both schemes rather than by eye.Release. The Docker Hub description step has failed with
Forbiddenon every
release, hidden bycontinue-on-error. It now points at a realdocs/dockerhub.md,
completes relative URLs so the screenshots resolve, and fails loudly. The
credential must be a PAT with read, write and delete scope — the description
endpoint rejects a repo-scoped token. It is the last step of the release job, so
a failure there cannot burn a version.Screenshots are recaptured from a four-node cluster carrying real traffic:
just demobrings up two live/backup pairs, registers them through Studio's own
API and drives messages with the broker image's own client — nothing is written
tometric_sampleby hand — andjust shotscaptures the four README images.ADR-0055 records the time axis and the quantized window. ADR-0056 records bounded
views and topology level of detail.
2026.09.9
Breaking
-
Make discovery a tool, and generate the surface from one catalogue (06945d2d)
The MCP tool listing is sent to a model on every conversation that touches
Studio, before it has asked for anything. It is now 1696 tokens across 13 tools,
down from 2115 across 14 — a fifth off every session — and it gained a discovery
tool while shrinking.studio_helpis the new route to the detail the schemas leave out. Call it with
no topic for an index of every tool, or with a tool name for that tool's accepted
values, JSON body shapes and semantics.ADR-0050 had put that detail in the
studio://toolsresource, on the reasoning
that a host fetches a resource once and keeps it. That is true of hosts that read
resources.resourcesis an optional server capability and nothing in the MCP
specification obliges a client to callresources/read— ever. On a host that
skips them, ADR-0050 did not make discovery progressive; it made it absent, and a
model was left inferring valid values by triggering rejections. Tools are the one
part of MCP every host implements, so the detail moved behind one.studio://tools
remains as a generated mirror that nothing depends on.Because that channel is now reliable, every other schema dropped the hedging text
it carried in case the resource was never read — spelled defaults, type codes,
"see studio://tools" pointers. The help tool costs about thirty-five tokens and
licensed stripping several hundred, which is why the listing is smaller despite
being one tool larger.Rejections now name
studio_helpalongside the values they would have accepted,
so a wrong guess is a recovery rather than a retry loop.The server
instructionsblock is generated from the same catalogue instead of
being retyped inapplication.yml. The hand-written one had already drifted: it
omittedqueue_lifecycleandmessage_bodyand never named a discovery route.
Under a host that searches tools rather than sending the whole listing, that text
is the only thing guaranteed to be read, so a stale copy did not merely go out of
date — it told a model that two capabilities the product has did not exist. The
build now fails when a registered tool is missing from the catalogue.Two further checks are enforced: no tool may declare itself both read-only and
destructive, and a tool's declared posture must match the catalogue's. A host
gates a whole tool on onedestructiveHint, so a read reachable through a tool
that can purge would make every read prompt the operator — which is how an
operator is trained to reflex-approve the purge.The budget ceilings ratchet down with the win rather than banking it as headroom:
per-tool 200 → 175, average 160 → 135, calibrated against a measured run.
Added
-
Make discovery a tool, and generate the surface from one catalogue (06945d2d)
The MCP tool listing is sent to a model on every conversation that touches
Studio, before it has asked for anything. It is now 1696 tokens across 13 tools,
down from 2115 across 14 — a fifth off every session — and it gained a discovery
tool while shrinking.studio_helpis the new route to the detail the schemas leave out. Call it with
no topic for an index of every tool, or with a tool name for that tool's accepted
values, JSON body shapes and semantics.ADR-0050 had put that detail in the
studio://toolsresource, on the reasoning
that a host fetches a resource once and keeps it. That is true of hosts that read
resources.resourcesis an optional server capability and nothing in the MCP
specification obliges a client to callresources/read— ever. On a host that
skips them, ADR-0050 did not make discovery progressive; it made it absent, and a
model was left inferring valid values by triggering rejections. Tools are the one
part of MCP every host implements, so the detail moved behind one.studio://tools
remains as a generated mirror that nothing depends on.Because that channel is now reliable, every other schema dropped the hedging text
it carried in case the resource was never read — spelled defaults, type codes,
"see studio://tools" pointers. The help tool costs about thirty-five tokens and
licensed stripping several hundred, which is why the listing is smaller despite
being one tool larger.Rejections now name
studio_helpalongside the values they would have accepted,
so a wrong guess is a recovery rather than a retry loop.The server
instructionsblock is generated from the same catalogue instead of
being retyped inapplication.yml. The hand-written one had already drifted: it
omittedqueue_lifecycleandmessage_bodyand never named a discovery route.
Under a host that searches tools rather than sending the whole listing, that text
is the only thing guaranteed to be read, so a stale copy did not merely go out of
date — it told a model that two capabilities the product has did not exist. The
build now fails when a registered tool is missing from the catalogue.Two further checks are enforced: no tool may declare itself both read-only and
destructive, and a tool's declared posture must match the catalogue's. A host
gates a whole tool on onedestructiveHint, so a read reachable through a tool
that can purge would make every read prompt the operator — which is how an
operator is trained to reflex-approve the purge.The budget ceilings ratchet down with the win rather than banking it as headroom:
per-tool 200 → 175, average 160 → 135, calibrated against a measured run.
2026.09.8
Release 2026.09.8
2026.09.7
Added
- Queues and addresses can now be created, destroyed, reconfigured, paused and
resumed from Studio, without dropping to theartemisCLI or a JMX console. A
command names a cluster, not a node: Artemis cluster nodes each own their own
queues, so the operation fans out to every live node and the result is a per-node
outcome rather than a single yes or no. A node that was not live is reported as
skipped, never as a failure, and re-running after a partial application converges.
Nothing is rolled back on a partial failure — a destroyed queue cannot be restored,
and a compensating create would be a different state dressed up as the original —
so the divergence is reported and left in your hands. - Every lifecycle command has a preview.
?dryRun=truenames the target nodes
and, for a destroy, the messages that would be lost on each, without touching any
broker. Destroying a queue destroys its messages, so it is counted against the same
safety.bulk-capas any other bulk destructive operation and needs the same
explicit override above it. - Four new permissions —
queue:create,queue:delete,queue:updateand
queue:pause— grantable globally, per environment, or per cluster. Holding
queue:purgedoes not imply any of them: emptying a queue and destroying it are
different authorities. They appear in the role editor with no upgrade step. - One MCP tool,
queue_lifecycle, covering every kind. It previews by default,
and turning the preview off for a destructive kind additionally requires a
confirmation matching the target's name. - A node's effective broker configuration is now readable on its own — the
settings it is actually running with, as the broker resolves them — at
GET /api/v1/clusters/{id}/nodes/{nodeId}/config, and to an MCP client as the
cluster://{id}/nodes/{nodeId}/settingsresource. Previously configuration could
only be seen by diffing two nodes against each other. - A paused queue is now identifiable as paused in the cluster's queue view,
including when it is paused on some nodes and not others.
Changed
-
managementWriteis no longer inferred from a read. It was reported as
available whenever a read-onlylistNetworkTopology()call succeeded, which proves
only that Jolokia is not under a read-only policy — not that any particular
operation is permitted. It is now unknown until a management write has actually
been attempted on that connection, available once one has succeeded, and
unavailable once one has been refused for an authorization reason, with the
broker.xmlthat would grant it.A connection previously shown as
AVAILABLEon inference alone will now read
UNKNOWNuntil its first write. This is a correction, not a regression — the
previous value was not evidence-backed. Write operations are still offered while it
is unknown, with the uncertainty stated: absence of evidence must not block you.
A write that fails for any other reason — an unreachable broker, an argument the
broker rejects — leaves the assessment alone, so one bad request cannot permanently
disable a button. -
Warning and danger text is legible in the light theme. Measured against the
WCAG 2.2 AA floor rather than assumed: warning text was 2.13:1 and danger text
3.84:1 on white, both under the 4.5:1 minimum for body text. They are now 6.67:1
and 5.46:1, keeping their hue. Purely graphical marks — chart axes, graph edges,
the alert dot — are unchanged, since the text floor does not apply to them. -
The MCP tool listing budget now scales with the number of tools rather than being a
fixed ceiling, and enum values and JSON body shapes moved out of the tool schemas
into astudio://toolsresource that a client reads only when it needs them
(ADR-0050). No tool was removed.
Added
- Clock and rr fix (b8a33d32)
Changed
-
Add queue and address lifecycle across a cluster (77ed26bf)
Studio could read every queue in a cluster and mutate every message in one, and
could not create, delete, pause or reconfigure the queue itself. That was the
largest remaining gap between an observability tool and a management tool, and
the one the product name already promises.A lifecycle command names a CLUSTER, not a node. Artemis cluster nodes each own
their own queues, so the operation fans out to every live node — resolved from
polled topology, never from configuration — and the result is a per-node outcome
list rather than a boolean. A node that was not live is reported as skipped, not
failed: it never received the command. Nothing is rolled back on a partial
failure, because a destroyed queue cannot be restored and a compensating create
would be a different state dressed up as the original; the divergence is
reported instead, and one audit row carries the whole fan-out.Verified against the broker rather than assumed, which changed the design three
times (ADR-0049, and the change's design.md records the method):- Every positional createQueue/updateQueue overload is deprecated as of 2.56;
the current API is JSON QueueConfiguration, and createQueue(cfg,
ignoreIfExists) supplies the already-in-state semantics directly. - updateQueue REPLACES rather than merges. A document omitting a field clears
it, so sending only an operator's changed fields silently destroyed the
queue's filter. The update path now reads, merges, and sends the whole config. - The filter is mutable; only the routing type is not. The spec asserted both
were immutable and has been corrected.
managementWrite stops being inferred from a read-only listNetworkTopology()
call, which proves only that Jolokia is not under a read-only policy. Nothing
depended on that guess until a create button did. It is now UNKNOWN until a
write has been attempted, AVAILABLE once one succeeds, and UNAVAILABLE only on
an authorization refusal — so one malformed request cannot permanently disable a
button. Evidence is persisted on the cluster, because the probe makes no write
and must not. Three existing screens gated on!== AVAILABLEand would have
locked operators out of working brokers; they now block only on a known refusal
and state the uncertainty otherwise.Also folded in, at the maintainer's request:
- A node's effective broker configuration is readable on its own, over HTTP and
as an MCP resource. ConfigReader already read exactly this for the two-node
diff and had no endpoint of its own. - The MCP listing budget scales per tool instead of a flat ceiling, and enum
members and body shapes move to a studio://tools resource a client reads only
once it has chosen a tool (ADR-0050). The flat 2000-token limit had no headroom
left, so any new capability would have failed it. No tool was removed.
Light-theme warning and danger text were measured, not assumed, and failed:
2.13:1 and 3.84:1 against a 4.5:1 AA floor. No shade of Mantine's yellow or
orange ramp reaches 4.5:1 on white, so the warning needed a dark amber literal.
Now 6.67:1 and 5.46:1; graphical marks stay on the bright ramp. - Every positional createQueue/updateQueue overload is deprecated as of 2.56;
-
Propose MCP tool grouping and progressive discovery (3bd1b31b)
The MCP surface is 14 tools and ~2100 tokens of tools/list, re-sent on every
conversation before a model has asked for anything. Four more roadmap changes
each add tools, so the listing roughly doubles on the current trajectory — at
which point cost matters and, more importantly, so does selection accuracy: a
model choosing between thirty flat tools picks worse than one choosing a domain
and then an operation. On a surface that can destroy a queue, that is a safety
property.This decides the shape before the surface gets there rather than after.
Deliberately a thin proposal — nothing is implemented. The answer depends on
what the MCP specification actually guarantees about tools/list_changed and what
the Spring AI MCP version here actually supports, and both are facts to verify
rather than assume. proposal.md records that the change must be brainstormed
first, the protocol and library checked through ctx7, tasks.md rewritten to
match, and only then implemented.design.md frames six open questions rather than answering them, and records the
constraints any answer must survive: no capability leaves the surface,
progressive discovery may not be mandatory, discriminators stay validated
server-side, and the budget stays enforced by a test.
Fixed
-
Accept a disabled interval in the poll() pausable-refetch helper (adb10625)
useMetricspassesnumber | falsetopoll()so an absolute (non-live)
chart range never polls, butpoll()only acceptednumber, so the frontend
build failed to typecheck. Widening the parameter keeps the pause seam intact:
afalseinterval stays disabled whether or not polling is paused.
2026.09.6
Release 2026.09.6
2026.09.4
Breaking
- An expectation's reply address is now a set of patterns. The request-reply
expectation API fieldreplyAddress(a single string) is replaced by
replyAddresses(an array of strings) on the create, update and read payloads.
Any client postingreplyAddressmust sendreplyAddresses: ["<the old value>"]
instead, or[]where it previously sent nothing. Stored expectations migrate
themselves — an existing reply address becomes a one-entry set — so no operator
action is required in the UI.
Added
-
One expectation can trace reply queues you cannot list in advance. Reply
addresses are now a set, and each entry may be a pattern:orders.reply.*covers
a reply queue per responder, including ones created after you declared it. This is
what makes tracing work against a deployment whose reply queue is named after the
broker node or the client host, where any fixed list is stale as soon as something
is redeployed.*matches any run of characters and matching is anchored at both
ends; Artemis's#is not a wildcard here. The form shows what a pattern currently
resolves to as you type it, and says so when it matches nothing yet — which is
normal, not an error. -
A completed flow records which reply queue answered it. When more than one
reply address is in play, the flow takes its reply destination from the reply that
joined it, so you can see which responder served a given exchange. -
"Check connection" now tests the Core connection too, and registration waits for
it. The check opened no Core connection at all, so it reported nothing about the
channel that carries notifications and faithful message I/O — a wrong Core account, or
the same wrong password entered twice, passed the check and only failed after the
cluster was registered. The check now opens and closes a real subscription to
activemq.notifications, and Register cluster stays disabled until a check of the
exact details in the form has passed, saying which of those it is waiting for. Editing
a URL, a username or a password invalidates the previous check rather than carrying it
over. -
A separate broker account for the Core connection. Settings can now rotate the
Core-protocol credentials independently of the management (Jolokia) ones. Set these
when your management account is also the broker's<cluster-user>: Artemis reserves
that account for inter-node traffic and refuses it over Core withAMQ229099, which
previously left the notification subscription failing with no way to fix it short of
re-registering the cluster. -
Pick an address instead of typing it. The request and reply address fields on the
Requests screen now suggest the cluster's own addresses as you type, each with its
routing type, current depth and how many nodes carry it — enough to tell a request
queue from a reply queue without leaving the form. You can still type a name that does
not exist yet; the field says it matched nothing rather than refusing it. The
suggestions can be narrowed to anycast or multicast.
Changed
- The broker-capabilities notice can be dismissed. It stays dismissed for the rest of
your session and comes back when you sign out, when someone else signs in, or when a
different capability starts falling short — so waving away a known gap never hides a
new one.
Fixed
-
Every node serving a traced address is now sampled. Studio browsed only the
first active node of a cluster, so in a multi-primary cluster the request and reply
traffic on the other nodes was never read and the correlation identity that only
browsing supplies was missing for most exchanges. -
A reply consumed faster than the sampler ticks is no longer missed. A delivery
on a declared reply address now counts as a reply observation, alongside the
existing browse. It carries no correlation id, so it completes a flow only where
sampling already identified the request — coverage, not a replacement for browsing. -
Request-reply sampling failures are reported. A failure was swallowed at debug
level, so a correctly-configured-looking expectation produced no flows and said
nothing about why. Failures now log a warning naming the expectation and the node,
rate-limited so a node that is down for an hour does not flood the log. -
Capabilities are assessed against a live node. Studio probed whichever node sorted
first by name. On a cluster whose backup sorts before its primary that meant probing a
passive backup, which registers no acceptor and no address MBeans — so Studio reported
"CORE acceptor not found" and "activemq.notifications address not found" about a broker
where both were present. -
A Jolokia agent that labels its JSON
text/plainis understood. The agent bundled
with Artemis 2.39 answers a valid Jolokia response with
Content-Type: text/plain;charset=utf-8where 2.44 sendsapplication/json. Studio's
client only accepted the JSON content types, so every response from the older broker
failed to convert and a healthy cluster was reported as "the broker answered, but not
with a Jolokia response". -
The MCP client configuration example is valid. It omitted
"type": "http", which
clients reject. -
A broker that refuses the connection now says so. Registering a cluster against an
Artemis console that rejects the credentials reported "The broker answered, but not with
a Jolokia response" — a message that sent operators looking for a proxy or a CORS problem
that was not there. Studio now classifies the refusal from the HTTP status rather than
from an exception subclass, and repeats what the broker itself said: the
Hawtio-Forbidden-Reasonheader the Artemis console sets on its bare 403, and any
WWW-Authenticatechallenge. -
A management URL pointing at the console instead of the agent is named as such. Studio
no longer follows redirects to the console's login page and then reports the resulting
HTML as a bad Jolokia response; a redirect is reported as the wrong path, with the
location the broker sent. A seed typed ashost:port/consoleis completed to
/console/jolokiarather than left to fail. -
Tracing an already-traced request address returns a conflict, not a server error.
Adding the same request address twice failed with an HTTP 500 whose body said nothing;
it now returns 409 naming the address, and the Requests screen shows that message. The
enable/disable switch and the remove button on that screen also report their failures
instead of appearing to do nothing. -
The config diff table is readable again. Long acceptor values no longer take the whole
row and squeeze the key and status columns to one character per line; wide values scroll
inside the section, and a key too long for its column is revealed on hover.