The VS Code extension on the Marketplace: a project from a template, schema completion, bean hints, a route tree and graph, Mermaid, the way to a Tsak worker.
An integration route in redb.Route can be written in C# or in markup: a .route.xml file goes into a package, the package into the folder of a Tsak worker, and the route starts working. The format needs no editor; it is plain XML that the service loads as it is. But writing it by hand from memory is awkward: which options a connector has, what an element is called, which bean to refer to, where a message goes when no branch matches.
That is what the redb Route XML extension for VS Code is for. Since late October it has been on the Visual Studio Marketplace, current version 0.2.25. Below is the whole path with it: from an empty folder and a project from a template, through markup, completion and the graph, to a diagram for the docs and a module on a worker.
What you get
-
A start in a minute. A working module with routes, checks and a stand is created from a page, without knowing the
dotnet newcommands or hunting for the right template package. - Errors show while you type. A wrong element, an option of the wrong connector or the wrong side of an endpoint is underlined at once, not in the worker's log after deployment.
- No connector options to memorize. Kafka alone has more than forty options; the editor offers them with their types and allowed values, exactly what the service of the current release accepts.
- A route others can read too. The graph shows the transaction boundary, the branches and the path of a message that matched no condition. Walking a flow through with an analyst, a tester or support is easier with it than with the text.
- Clean changes in git. The graph changes only the place it edits, so a change made with the mouse looks like an ordinary short diff in review.
- Docs that do not drift from the code. The Mermaid diagram is built from the same route that runs on the worker and is refreshed with one command.
- No cost. The extension is licensed under Apache 2.0, and the schema, tree and graph work offline.
What the extension does
- New Project: a page that creates a project from the redb templates and installs the template packages itself.
- Schema: completion of elements, attributes and the options of every connector, validation as you type.
- Skeletons: a route, a choice and an error-handling block in one insert.
-
Bean references: a list of declared objects on
#. - Route tree: every route in the workspace with a jump to its line.
- Graph: the route as a diagram you edit with the mouse that stays text.
- Mermaid: a route diagram for a README or a wiki.
Installation
In the Extensions view search for redb Route XML and click Install, or from a terminal:
code --install-extension redb.redb-route-xml
VS Code installs Red Hat XML along with it: that extension does the completion and validation, and ours hands it the schema. VS Code 1.85 or newer is required.
For a machine without Marketplace access, and for VSCodium and Cursor, the same redb-route-xml-0.2.25.vsix is attached to the redb-route releases on GitHub: Extensions, the ... menu, Install from VSIX. Offline, install the Red Hat XML .vsix first the same way.
A new project without the command line
redb: New Project from the Command Palette opens a page that creates a project from the redb templates through dotnet new. The top shows what is on the machine: the .NET SDKs and two template packages, redb.Templates and redb.Tsak.Templates. A missing package gets an Install button:
When nuget.org has a newer version of a package, the button turns into Update.
Every template is a card, in three groups.
XML route modules, twenty redb-route-* templates. Each creates a Tsak module with routes in markup and the same scenario in C# next to it, in routes/*.cs: handy for comparing two ways of writing one flow. Among them: files (a local folder, FTP, SFTP), a REST API, an SQL outbox and batch inserts, redb objects, Kafka, RabbitMQ, AMQP 1.0, MQTT, S3, LDAP, mail, AS2 and AS4, a Quartz schedule, an XSD check with XSLT, scatter-gather and a set of integration patterns without a broker.
Tsak hosts: a worker that loads modules from its folder, reloads them on the fly, and offers a management API and a scheduler.
Applications on redb: a console app, Blazor and Razor Pages sites, Blazor WebAssembly with a redb.Route REST API, a Blazor BFF, an integration worker, an application on redb.Identity, an LLM chat.
On the right is the form with the chosen template's parameters: project name, target framework, database, state store, folder. A framework with no SDK on this machine is marked, and a folder that already holds files is refused.
Create runs dotnet new, and when the project carries a local tool manifest, dotnet tool restore as well. The output goes to the page and to the redb Route output channel, and a running step can be cancelled. At the end the page offers to open the project in this window, in a new one, or to add it to the workspace.
The cards and the form are built from the templates themselves. A new template in the redb packages shows up on the page without an extension update.
The route project
From here the example uses the redb.Route XML module: files template (redb-route-file). It needs no server at all: an inbox folder, an XSD check, folders for processed and failed files, a receipt per file. From a terminal it is the same command the page runs:
dotnet new install redb.Templates
dotnet new redb-route-file -n Orders
Orders/
.config/dotnet-tools.json the redb-route-xml local tool
context.xml the context document: beans, C# routes
routes/files.route.xml two XML routes
routes/CsvFilesRoute.cs the same pattern for CSV in C#
resources/order.xsd the order schema
config/orders.config.json context name and auto start, shipped in the package
config/context.sample.json a deployment sample of the settings
deploy/docker-compose.files.yml the module on a Tsak worker
The layout is a convention of the format. Routes live in routes/, the resources they refer to by name in resources/. context.xml loads before the routes, so the routes see its beans. The package carries only the module's identity, orders.config.json, while settings come from the worker's configuration: the same package goes to staging and production without a rebuild.
Markup by example
Here is the template's second route, the one that processes incoming files:
<routes xmlns="urn:redb:route:1.0">
<route id="orders-files-in" description="Processes the files of the inbox">
<from uri="file://{{files.inbox:inbox}}?antInclude=*.xml&delay=5000&moveTo=done&moveFailed=error"/>
<convertBody type="System.String"/>
<validateXsd file="resources/order.xsd" throwOnFailure="true"/>
<log level="Information" showRouteId="true">
<message>processed ${header.redbFile.NameOnly}: ${body}</message>
</log>
<setBody expr="received ${header.redbFile.NameOnly}"/>
<to uri="file://{{files.outbox:outbox}}?fileName=${header.redbFile.NameOnly}.receipt"/>
</route>
</routes>
Five things are enough to read any route:
-
<from>and<to>are the input and the output. The URI works as in C# routes: the connector scheme, a path, options. A long endpoint can be written as a structure, for example<to><sql dataSource="#main-db">with the query text inside. -
Steps run top to bottom: turn the body into a string, check it against the XSD, log it, replace the body, send a receipt. If a file fails the schema, the exception sends it to
error/through themoveFailedoption. -
{{files.inbox:inbox}}is a configuration placeholder with a default. It resolves from the worker's configuration. A key with no default goes into the package manifest as required. -
${header...}andexprare the expression language, the same as in C# routes. In a condition the string becomes a predicate, in a value it is evaluated. -
Branching and error handling are elements:
<choice>with<when expr="...">and<otherwise>,<tryCatch>with<try>,<catch>and<finally>,<transaction>around steps that commit together. The template's first route, the test file generator, uses<choice>: every fifth file it makes deliberately not XML.
The loader turns the markup into the same DSL calls you write in C#, so everything the engine can do the XML can do: retries, transactions, message history, metrics, mocks in tests. The format, the package check and swapping a module on the fly are covered in detail in XML routes in redb.Route.
Schema completion
The document starts with the urn:redb:route:1.0 namespace. That is how Red Hat XML picks the schema the extension ships, and from then on you get completion of elements and attributes, enum values and validation as you type. The binding goes by namespace, not by file name: someone else's route.xml without our namespace is left alone.
The schema knows the typed options of every connector. Type <to><kafka and a space inside a route, and the editor offers topic, brokers, key, acks, compressionType and a few dozen more Kafka options with their types and allowed values.
The schema also knows the sides of an endpoint. An option that only a producer takes is flagged as an error inside <from>: AS4's addressQuery, for example, gives "The 'addressQuery' attribute is not allowed". The error shows in the editor, before the build and before the run.
context.xml gets the same help: inside <context>, after < the editor offers bean, components, dataFormat, deadLetterChannel, onInit, redb, routeBuilder, routeConfiguration.
Nobody writes the schema by hand. The redb-route-xml tool generates it from the connector assemblies at each redb.Route release, and the release checks that the schema in the extension matches its assemblies. A new connector option reaches the editor with the next extension version.
Skeletons
Some constructs the schema cannot offer as a whole: a route without from or a choice without branches makes no sense. For those there are three skeletons, inserted wherever a new element may start:
| Type | Inserts |
|---|---|
<route |
a route with its consumer |
<choice |
a choice with a when branch and otherwise
|
<tryCatch |
a try block with catch and finally
|
They are offered only in redb route documents and only where an element may stand: not inside an attribute and not in foreign XML.
Bean references
Registry objects, connection factories and handlers, are declared with <bean name="...">, and a route refers to them with #. Type # and the editor lists the names of the declared beans. The hint works in three places: the whole attribute value (dataSource="#"), right after the URI scheme (bean:#) and a URI option value (?headerFilterStrategy=#). A # inside other text, such as the SQL parameter :#login, is not a reference and gets no hint.
<routes xmlns="urn:redb:route:1.0">
<bean name="main-db" type="redb.Route.Sql.Connection.SqlConnectionFactory, redb.Route.Sql">
<constructorArg>
<bean type="redb.Route.Sql.Connection.SqlConnectionOptions, redb.Route.Sql">
<property key="ConnectionString" value="{{db.main.connection}}"/>
</bean>
</constructorArg>
</bean>
<route id="audit">
<from uri="direct://audit"/>
<to>
<sql dataSource="#main-db"> <!-- here # offers main-db -->
<![CDATA[ INSERT INTO audit_log(at) VALUES (CURRENT_TIMESTAMP) ]]>
</sql>
</to>
</route>
</routes>
The limit in version 0.2.25: the hint sees only the beans of the current file and does not filter them by type. The redb templates declare their beans in context.xml, so in a template's route file # offers nothing yet. A wrong or dangling reference is caught either way by redb-route-xml check and pack: the bean's type, methods and properties are checked against the real assemblies.
Route tree
The redb button in the Activity Bar opens the Routes view: every routes document in the workspace (*.route.xml, *.redb-route.xml), and for each route its id and from endpoint. A click opens the file at the route's line. The tree refreshes by itself when files are created, edited or deleted, and covers every folder of the workspace. Without routes, the view offers to create a project.
The shot shows the serial number request route from the SerialNumbers.Xml demo: an XSD check in tryCatch, a decision in a transaction, two choices. It reads well as text, but where the transaction ends and where a message goes without a matching branch is easier to see in the graph.
Route graph
The graph button in the editor title, Open With and redb Route Graph, or redb Route: Open Route Graph open the same file as a graph. The graph is a second view of the same text: every edit in it is an edit of the XML and is undone with the usual Ctrl+Z. The file is never reserialized and every edit is a point replacement: comments, indentation and attribute order in untouched text stay as the author left them, and a new attribute added from the panel goes last in the tag. A step moves or is deleted together with the comment lines directly above it (a blank line breaks the link, a comment below the step stays put) and takes the indentation of its new place. The text editor stays the default.
How to read the graph:
-
Tiles of one size with glyphs in the Enterprise Integration Patterns notation and a short caption:
from,bean,sql,choice,loop,log. What a step does (the property name, the condition, the SQL) is in the tooltip and the properties panel. -
Wrappers on the route line.
transaction,loop,split,meteredput their steps between their own tile and anendtile;choice,tryCatchandfilterfan out into branches. A run ofsetHeaderandsetPropertysteps folds into oneset ×Ntile. -
Paths by meaning. Conditional paths are dashed: orange where a message goes past a step (filter not passed, no branch matched, a duplicate), grey with a cross where it is dropped (
sample,debounce), red where a step throws. In the shot the orange "no match" path goes around both branches of thechoiceinside the transaction. -
Colors by role. Green in, blue out, purple your code (
bean), orange data changes, cyan routing, grey observation, red errors.
What you can do:
- See an endpoint taken apart. For a step with a URI the properties panel splits it into the scheme, the path and the connector's options, with enum values picked from a list. A sensitive option, a password or a key, is masked and cannot be edited from the panel.
-
See the settings. A
{{files.inbox:inbox}}value is shown together with what it resolves to: the graph readsconfig/context.sample.jsonandconfig/*.config.jsonnext to the file or up to three folders above it, and merges them the way a Tsak worker does. An edit always keeps the placeholder itself. -
Edit with the mouse. Insert a step from the palette at any "+" between steps, delete it with
Delete, drag it to a new place or into a container, rename it; attributes and texts are edited in the properties panel. - Change the layout. Left to right or top down, fold or unfold every container at once, zoom, fold a route to its title.
Among the templates, redb-route-eip gives the most telling graph: its routes/orders.route.xml has six integration patterns in a row.
Mermaid diagrams
The graph lives in the editor, while a README, a wiki or a ticket needs a picture that will not drift from the code. redb Route: Show Mermaid Diagram saves the current file, runs the redb-route-xml mermaid tool and opens the diagram text in a new Markdown tab. It needs the .NET tool:
dotnet tool install -g redb.Route.Xml.CodeGen
A project from a template already has it in its local manifest, and the same diagram comes from a terminal:
dotnet tool restore
dotnet redb-route-xml mermaid routes/files.route.xml
This is the output for the routes of the redb-route-file template, unedited:
flowchart TD
n0["orders-files-feed: timer://orders-files-feed?period={{fil..."]
n1{"choice"}
n0 --> n1
n2{{"when: header.CamelTimerCounter % 5 == 4"}}
n1 -.-> n2
n3["setBodyStatic"]
n2 --> n3
n4(["otherwise"])
n1 -.-> n4
n5["setBodyExpression"]
n4 --> n5
n6[["file://{{files.inbox:inbox}}?fileName=order-${header.Came..."]]
n3 --> n6
n5 --> n6
n7["orders-files-in: file://{{files.inbox:inbox}}?antInclude=..."]
n8["convertBody"]
n7 --> n8
n9["validateXsdNamespace"]
n8 --> n9
n10["richLogScope"]
n9 --> n10
n11["setBodyExpression"]
n10 --> n11
n12[["file://{{files.outbox:outbox}}?fileName=${header.redbFile..."]]
n11 --> n12
It is text, not a picture: GitHub, GitLab and most wikis render such a block themselves, and in VS Code you see it through the Markdown preview plus a Mermaid extension. The diagram is built from the same definition tree as the running route: a diamond for choice, a hexagon for the condition, a stadium for otherwise, a double frame for a sending endpoint. Node captions are engine step names (setBodyExpression, richLogScope), not markup elements, and long URIs are cut short.
Check and pack
The route is written and the graph has been checked by eye. Next comes the same check as on a build server, only on your machine:
dotnet build -p:PackRouteOnBuild=true -p:Version=1.0.0
The build checks the markup against the schema, every endpoint option against its connector, the beans against the real assemblies, resources such as resources/order.xsd and the configuration keys, then writes the package pkg/orders-1.0.0.tpkg. An error in the markup becomes a build error, and a package with an error is not built. Without a package, the same checks run with:
dotnet redb-route-xml check .
What else it finds, such as literal secrets in a URI or dangling bean references, and what its messages look like is shown in the article about the format.
On to the worker
The template brings a stand too: the compose file starts the Tsak worker image and mounts pkg/ as its module folder.
docker compose -f deploy/docker-compose.files.yml up -d
The log shows processed order-N.xml: ... lines. Every fifth test file is deliberately not XML: it fails the schema and goes to error/, the rest get a receipt in outbox. On a worker of your own it is enough to drop the .tpkg into its modules folder: the worker loads the module by itself and unloads it the same way when the file is removed. Settings go in context.json next to the package or in the worker's configuration. How Tsak builds services out of such modules is covered in the article about microservices on Tsak.
Limits
| What | Today |
|---|---|
| Own language server, hover, diagnostics | none: validation and messages come from Red Hat XML against the schema |
| Extension settings | none: the schema catalog is registered with Red Hat XML through its API |
# hints |
beans of the current file, no type filter |
| New connector options | arrive with the next extension version |
| Mermaid diagram | Markdown text, needs the redb-route-xml tool |
| New Project | needs a .NET SDK; template packages install with one click |
| Offline | schema, tree, graph and skeletons work; installing also needs the Red Hat XML .vsix
|
| After an update | the redb Activity Bar button appears after Developer: Reload Window |
| Open VSX | no; for VSCodium and Cursor there is the .vsix from the release |
Versions
The extension has its own numbering, 0.2.x, which does not move with the redb packages. Every redb.Route release regenerates the schema, the element list and the bean catalog from its assemblies and checks them against what the extension ships. The extension first reached the Marketplace on October 23, 2026; version 0.2.25 went up on October 29 and matches the redb-route v4.6.0 release, which carries the same .vsix. The extension is licensed under Apache 2.0.
If this was useful, a ⭐ on GitHub helps others find it.
More of my writing: redbase.app/articles, and on dev.to.







Top comments (0)