Skip to content

CAMEL-25771: camel-jbang - the Routes and Diagram views show the revision and checksum of a route, and the Source view whether the file runs as saved - #28220

Open
davsclaus wants to merge 4 commits into
feature/CAMEL-25771-route-checksumfrom
feature/CAMEL-25771-route-checksum-views
Open

davsclaus wants to merge 4 commits into
feature/CAMEL-25771-route-checksumfrom
feature/CAMEL-25771-route-checksum-views

Conversation

@davsclaus

@davsclaus davsclaus commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #28213, which gives each route a checksum and a revision (CAMEL-25771). The route console has both, so the Camel TUI shows them where they help:

Routes: a route added again changed in this run, such as by a reload of its file, has its revision after its id, in parentheses and dimmed: orders (rev 3). A route that never changed shows just its id. tui_get_table has the checksum and the revision of each route.

Routes

Diagram: the Info panel of a route in the topology has its checksum, and its revision with the changes in this run (Revision: 3 · 2 changes).

Diagram

Source: the bottom border says whether the integration runs the file as it is saved:

  • ● running as saved: the integration loaded the file after it was last saved;
  • ○ reloading...: saved a moment ago, and the integration reloads on save (--dev);
  • ○ not running yet: saved after the integration loaded it. It says why: the integration runs without --dev (restart it), or it did not reload the file;
  • ⚠ the reload failed: the integration runs what it ran before the reload, until a reload succeeds.

tui_get_table on the Source tab has it as runState, so an AI agent can tell whether its edit runs. It is computed when the table is read, also while another tab is on screen, and when the tab is selected.

Source

Why the Source tab compares times, not checksums. The plan was to compute the checksums of the saved file's routes and compare them with the running ones. Two things rule it out for YAML and XML:

  • Loading a route file with the Camel DSL loaders runs parts of it: the YAML loader creates and binds the beans of the file as it loads it. The TUI opens any file the user browses, and a tool that reads route sources without running them must not run code from them (security model).
  • An endpoint written with parameters: is built by its component's EndpointUriFactory, which wraps secrets in RAW() and places path parameters. The TUI does not have most components, so its checksum would differ from the one the route runs with, and the TUI would say "not running yet" for a route that runs.

So the Source tab compares when the file was saved with when the integration loaded the routes it has from the file:

  • An integration that has not reloaded loaded its routes when it started, as the process start time says. A route stopped and started again by hand keeps what it loaded.
  • After a reload, a route that started after the save runs what is saved. The route console gives only the uptime as text, so this is to the second; a route stopped and started by hand after a reload counts as loaded then.
  • A failed reload puts back the routes that ran before it, so until a reload succeeds the state is the reload error.

For an exact answer, route by route, camel cmd route-structure <file> gives the checksum of each route of a file and camel get route --checksum that of each running route (#28213). If the runtime ever records a hash of the source it loaded each route from, the Source tab can compare that with the saved file instead.

Tests

  • RouteChecksumViewsTest: the status file values, orders (rev 3) in the Routes table (and none for an unchanged route), the id cut to leave room for the revision, the Info panel lines, and tui_get_table.
  • SourceRunStateTest: each state; a route restarted by hand without a reload; dev mode reloading, reloaded and not reloaded; a failed reload; only the started routes of the file; the uptime text; the JSON for agents; the Source tab drawing it on the border; and tui_get_table computing it while another tab is on screen.
  • The camel-jbang-plugin-tui suite: 2217 tests pass. LaunchManagerOutcomeTest failed once and passed on the rerun. It swaps the global CLI home folder while the module's tests run in parallel, and is not touched here.
  • Checked live, with the Camel CLI of CAMEL-25771: camel-core - a route checksum and revision, so tools can tell which routes changed between two runs or after a reload #28213:
    • An integration in dev mode: after an edit of the orders route, the Routes tab has orders (rev 2), then (rev 3), with the new checksum in the Info panel. The audit route in the same file keeps its checksum and revision 1.
    • The Source tab went from running to reloading and back to running through each reload.
    • A second integration without --dev: after a save in the editor, it says not running yet: the integration runs without --dev, restart it.

Docs: the Routes, Diagram and Source help pages, and the Diagram and Source Editor pages of the manual, with the screenshots. They say that an integration without camel-xml-io has no checksum and revision either: camel run always has it, while a Spring Boot or Quarkus application may not.

Claude Code on behalf of davsclaus

🤖 Generated with Claude Code

@davsclaus davsclaus added this to the 4.24.0 milestone Oct 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

…sion and checksum of a route, and the Source view whether the file runs as saved

The route console has the checksum and the revision of each route, so the
views show them:

- Routes: a route added again changed in this run, such as by a reload, has
  its revision after its id, muted ("orders rev 3"). tui_get_table has the
  checksum and the revision of each route.
- Diagram: the Info panel of a route in the topology has its checksum, and
  its revision with the changes in this run ("3 · 2 changes").
- Source: the bottom border says whether the integration runs the file as it
  is saved: running as saved, reloading, not running yet (the integration
  runs without --dev, or did not reload the file), or the reload failed.
  tui_get_table has it as runState, so an agent can tell its edit runs.

The Source view compares when the file was saved with when the integration
loaded the routes it has from the file, not the checksums of the file:
- loading a YAML or XML file with Camel runs parts of it, such as creating
  its beans, which a tool that reads route sources must not do;
- an endpoint written with parameters is built by its component, which the
  TUI does not have, so the checksum would not be the one the route runs
  with.
An integration that has not reloaded loaded its routes when it started; after
a reload, a route that started after the save runs what is saved.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
@davsclaus
davsclaus force-pushed the feature/CAMEL-25771-route-checksum branch from c76501b to f4147ca Compare October 21, 2026 08:56
@davsclaus
davsclaus force-pushed the feature/CAMEL-25771-route-checksum-views branch from 69f5048 to 9dd55f9 Compare October 21, 2026 08:56

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Clean, well-designed TUI enhancement. The concurrency model using volatile fields with an immutable Computed record in SourceRunState.Tracker is correct — shown() and current() run on the single UI thread so they never interleave; refresh() runs on the background thread; the file-match guard in current() makes any cross-thread read mismatch return null safely. Test coverage is thorough: all four run states, uptime parser edge cases, stopped-and-restarted routes, dev-mode vs non-dev-mode, and the end-to-end Tracker flow.

The aRouteStoppedAndStartedAgainKeepsWhatItLoaded scenario is intentional — without a reload, a manually restarted route still runs code from the integration start, regardless of route uptime. The class Javadoc documents this explicitly.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

…e is in parentheses and dimmed

The Routes table shows the revision of a changed route as "orders (rev 3)",
with the revision dimmed like the time since the last exchange beside the totals.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>

@oscerd oscerd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TL;DR

A well-layered, well-tested TUI half of CAMEL-25771: older integrations fall back to a blank, and the Source tab compares times instead of loading the route file, in line with the security model. Two things before it lands: a completed CI build, and a fresh runState when tui_get_table reads the Source tab while it is off screen.

Blockers

  • None

Other findings: 4 (2 important but non-blocking, 1 suggestion, 1 small)

  1. [Important] No build has run on this PR yet. Build and test, PR doc validation and PR license check trigger only for PRs into main (pull_request.branches: [main]). This one targets #28213's branch, so the green rollup is Dependency Review and PR id uploader only. The earlier red was those two, cancelled by their concurrency group and re-run green a second later. Once #28213 is in, could we rebase onto main and merge after Build and test completes on that head?

  2. [Important] runState goes stale while the Source tab is off screen (SourceTab.java:223-224, :576). runState.refresh(...) runs only from refreshWhileVisible(), which CamelMonitor.refreshConditionalData() calls for the active tab only. tui_get_table reads the Source tab by name without showing it (McpFacade.getTableData). An AI write confirmed in the dialog keeps the current tab on screen, so an agent that then reads the Source table gets the state from the last time the tab was visible, such as running from before its save. getTableDataAsJson() already stats the selected file, so refreshing there keeps it current:

    // tui_get_table may read this tab while another one is on screen
    runState.refresh(ctx.findSelectedIntegration());
    runState.addTo(json);

    A test that moves the mtime and reads getTableDataAsJson() without refreshWhileVisible() would cover it. The same call in onTabSelected() (:212) would stop the border from showing the previous state for one refresh.

  3. [Suggestion] SourceTab.java:1191: sourceViewer.getCurrentFilePath() looks like it returns the same loaded path and is already used at :667 and :1779, so the new SourceLiveColumn.loadedFile() (SourceLiveColumn.java:76) could go.

  4. [Small] camel-jbang-tui-diagram.adoc:232, help/diagram.md:73, help/routes.md:89: besides a Camel before 4.24, an app without camel-xml-io has neither (#28213: "only present when known, as it needs camel-xml-io"). camel run always has it, while a Spring Boot or Quarkus app may not.

Reviewed with Claude Code on behalf of oscerd. This review was generated by an AI agent and may contain inaccuracies; please verify all suggestions before applying.

… tui_get_table reads it or the tab is selected (address review)

- tui_get_table may read the Source tab while another tab is on screen,
  which the data refresh does not refresh, so its run state is computed when
  the table is read.
- Selecting the tab computes it in the background at once, so the border
  does not show the state of before for a refresh.
- The file shown comes from SourceViewer.getCurrentFilePath(), which already
  gave it.
- The docs say that an integration without camel-xml-io has no checksum and
  revision either: camel run always has it, a Spring Boot or Quarkus
  application may not.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Claus Ibsen <claus.ibsen@gmail.com>
@davsclaus

Copy link
Copy Markdown
Contributor Author

Thanks. These are addressed in 3694bf7:

  1. CI: agreed. Build and test runs only for PRs into main. Once CAMEL-25771: camel-core - a route checksum and revision, so tools can tell which routes changed between two runs or after a reload #28213 is merged, this PR moves to main and is merged after Build and test completes on that head.

  2. Fixed. The run state is now computed in two more places:

    • getTableDataAsJson(), when tui_get_table reads the tab. That runs on the MCP thread, which already reads the attributes of the selected file.
    • onTabSelected(), in the background at once.

    tuiGetTableComputesItWhileAnotherTabIsOnScreen moves the mtime and reads the table without a refresh of the tab.

  3. Done. The file comes from SourceViewer.getCurrentFilePath(), and SourceLiveColumn.loadedFile() is gone.

  4. Done. The two help pages and the Diagram page say that an integration without camel-xml-io has neither: camel run always has it, while a Spring Boot or Quarkus application may not.

Claude Code on behalf of davsclaus

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants