<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alexandros Korovesis</title>
    <description>The latest articles on DEV Community by Alexandros Korovesis (@korove_sys).</description>
    <link>https://dev.to/korove_sys</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3096390%2F76d322c5-f9c9-474a-ba56-a146091d7f90.png</url>
      <title>DEV Community: Alexandros Korovesis</title>
      <link>https://dev.to/korove_sys</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/korove_sys"/>
    <language>en</language>
    <item>
      <title>I Built a Zero-Dependency Visual JSON Flow Editor in Vanilla JS for the Camino Flow Engine</title>
      <dc:creator>Alexandros Korovesis</dc:creator>
      <pubDate>Sat, 28 Mar 2026 13:40:53 +0000</pubDate>
      <link>https://dev.to/korove_sys/i-built-a-zero-dependency-visual-json-flow-editor-in-vanilla-js-for-the-camino-flow-engine-j1g</link>
      <guid>https://dev.to/korove_sys/i-built-a-zero-dependency-visual-json-flow-editor-in-vanilla-js-for-the-camino-flow-engine-j1g</guid>
      <description>&lt;p&gt;A few days ago, I introduced Camino-a lightweight, rule-driven JSON flow engine for Java. &lt;br&gt;
📖 &lt;a href="https://dev.to/korove_sys/stop-hardcoding-your-workflows-meet-the-rule-driven-json-flow-engine-for-java-4289"&gt;Stop Hardcoding Your Workflows: Meet the Rule-Driven JSON Flow Engine for Java&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The goal of Camino was simple: give Spring Boot developers an alternative to heavyweight BPMN tools like Camunda or Flowable. Instead of dealing with massive XML files, steep learning curves, and database bloat, Camino lets you map your service layer execution dynamically using a clean, readable JSON structure and MVEL expressions.&lt;/p&gt;

&lt;p&gt;But there was a catch. As your business logic scales, hand-writing nested JSON arrays with exact id and nextId references gets tedious. You lose the "visual map" aspect that makes traditional BPMN tools so appealing to system architects and business analysts.&lt;/p&gt;

&lt;p&gt;I needed a way to visually design these JSON flows. And because I wanted to keep the "lightweight" philosophy of the Camino engine, I decided to build the frontend without any dependencies. No React. No NPM install. &lt;/p&gt;

&lt;p&gt;Meet the Camino Flow Editor a zero-dependency, Vanilla JS visual canvas for the Camino engine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73c71ghskdyh1t54x0ma.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73c71ghskdyh1t54x0ma.png" alt="Main view of the flow editor" width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Problem: JSON is for Machines, Visuals are for Humans
&lt;/h2&gt;

&lt;p&gt;When you define a flow in the Camino Java engine, it expects a schema like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"myFirstFlow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"blocks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"f2966cbd..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"START"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"nextId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e21464b9..."&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e21464b9..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"checkNameIntersection"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"INTERSECTION"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"conditions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
                    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
                    &lt;/span&gt;&lt;span class="nl"&gt;"expression"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name.equals('George')"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
                    &lt;/span&gt;&lt;span class="nl"&gt;"nextId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3a18a..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; 
                    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"no"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
                    &lt;/span&gt;&lt;span class="nl"&gt;"defaultCondition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
                    &lt;/span&gt;&lt;span class="nl"&gt;"nextId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fa337..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you define a flow in the Camino Java engine, it expects a schema where blocks are linked by matching IDs. The engine is incredibly flexible it doesn't care if your IDs are long UUIDs or simple strings like "fetch_user" or "step_1", as long as the &lt;code&gt;nextId&lt;/code&gt; property correctly points to the &lt;code&gt;id&lt;/code&gt; of the target block.&lt;/p&gt;

&lt;p&gt;However, manually maintaining these links in a text editor is a recipe for a typo. The Camino Flow Editor solves this by giving you an infinite drag-and-drop canvas. &lt;/p&gt;

&lt;p&gt;When you select a "Target" in the UI, the editor handles the "plumbing" automatically mapping the relationship between the source and destination IDs. You simply connect the blocks, configure the rules, and click Save. The editor exports the exact JSON schema your Spring Boot backend expects.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It (Without Frameworks)
&lt;/h2&gt;

&lt;p&gt;Building a node-based visual editor using just HTML, CSS, and Vanilla JS presented some really fun architectural challenges.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Compact Canvas &amp;amp; Modal Configuration
&lt;/h3&gt;

&lt;p&gt;One of the issues with visual flow editors is cognitive overload. When every block displays all of its configuration properties, a 10-step flow takes up three monitors. &lt;/p&gt;

&lt;p&gt;To solve this, Camino Flow Editor keeps the canvas entirely compact. Blocks only show their Name and Type. All of the heavy lifting-defining the Java AbstractActionHandler names, writing MVEL expressions, and setting fallback "Default" conditions-is tucked away in a dedicated modal window accessible by double-clicking.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpg7l023ytptwv1aau9l1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpg7l023ytptwv1aau9l1.png" alt="Edit intersection modal view" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Dynamic SVG Orthogonal Routing
&lt;/h3&gt;

&lt;p&gt;I wanted smooth, Manhattan-style (orthogonal) routing that stays perfectly vertical or horizontal. Without a heavy library like jsPlumb, I had to build a custom geometry engine.&lt;/p&gt;

&lt;p&gt;There is a transparent SVG layer draped over the DOM workspace. Whenever you move a block or change a target dropdown in the config modal, the engine calculates the coordinates, paths around adjacent blocks to prevent "backward loop" overlapping, and draws beautiful 15px-radius rounded corners terminating in an arrowhead. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyq5f1zsgkj0c1kiojlin.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyq5f1zsgkj0c1kiojlin.png" alt="Conditional paths after the intersection evaluation" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  3. A Deep-Copy History Engine
&lt;/h3&gt;

&lt;p&gt;You can't have a serious editor without Ctrl+Z. &lt;/p&gt;

&lt;p&gt;I implemented a comprehensive history stack. The editor takes a lightweight snapshot of the underlying state object before every destructive action (creating a block, deleting one, changing an MVEL expression, or lifting your mouse after a drag). Hit Ctrl+Z to undo or Ctrl+Shift+Z to redo, and the SVG canvas repaints itself instantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Perfect Workflow
&lt;/h2&gt;

&lt;p&gt;With these two projects combined, the workflow is incredibly fast:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Draw it: Open CaminoFlowEditor.html locally. Drag and drop your workflow, add your MVEL routing logic, and click Save.&lt;/li&gt;
&lt;li&gt;Drop it: Move the exported .json file into your Spring Boot src/main/resources/camino folder.&lt;/li&gt;
&lt;li&gt;Code it: Create your AbstractActionHandler Java classes to match the names you defined in the UI. &lt;/li&gt;
&lt;li&gt;Run it: Pass your initial context HashMap to the FlowExecutor, and watch Camino execute your visual map.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No database schemas. No heavy XML parsing. No bloated dependencies. Just pure, decoupled business logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Out!
&lt;/h2&gt;

&lt;p&gt;Both the Java Engine and the Flow Editor are completely open-source. I would love for you to try them out, fork them, and let me know what you think!&lt;/p&gt;

&lt;p&gt;If you missed the deep dive into how the backend engine works, check out the original article here:&lt;br&gt;
📖 &lt;a href="https://dev.to/korove_sys/stop-hardcoding-your-workflows-meet-the-rule-driven-json-flow-engine-for-java-4289"&gt;Stop Hardcoding Your Workflows: Meet the Rule-Driven JSON Flow Engine for Java&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🎨 Frontend Editor: [&lt;a href="https://github.com/a-koro/CaminoFlowEditor" rel="noopener noreferrer"&gt;https://github.com/a-koro/CaminoFlowEditor&lt;/a&gt;]&lt;br&gt;
⚙️ Java Backend Engine: [&lt;a href="https://github.com/a-koro/camino" rel="noopener noreferrer"&gt;https://github.com/a-koro/camino&lt;/a&gt;]&lt;br&gt;
🚀 Working Demo: [&lt;a href="https://github.com/a-koro/caminoDemoApplication" rel="noopener noreferrer"&gt;https://github.com/a-koro/caminoDemoApplication&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>springboot</category>
      <category>spring</category>
      <category>caminoengine</category>
    </item>
    <item>
      <title>Stop Hardcoding Your Workflows: Meet the Rule-Driven JSON Flow Engine for Java</title>
      <dc:creator>Alexandros Korovesis</dc:creator>
      <pubDate>Thu, 12 Mar 2026 08:00:34 +0000</pubDate>
      <link>https://dev.to/korove_sys/stop-hardcoding-your-workflows-meet-the-rule-driven-json-flow-engine-for-java-4289</link>
      <guid>https://dev.to/korove_sys/stop-hardcoding-your-workflows-meet-the-rule-driven-json-flow-engine-for-java-4289</guid>
      <description>&lt;p&gt;Managing complex business processes in Java often leads to "Service Layer Bloat." You know the feeling: one service method that calls five others, with complex branching logic and error handling that's impossible to visualize.&lt;/p&gt;

&lt;p&gt;I decided to build a &lt;strong&gt;&lt;em&gt;lightweight library&lt;/em&gt;&lt;/strong&gt; to solve this: a JSON-based engine that treats your business logic as a dynamic map rather than a static script.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem: Rigid Workflows vs. "Heavy" Alternatives&lt;/strong&gt;&lt;br&gt;
Usually, if you want to change the order of two operations or add a conditional check, you have to modify the Java code, recompile, and redeploy.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why not just use BPMN?&lt;/em&gt;&lt;br&gt;
Many enterprise developers turn to BPMN (like Camunda or Flowable) for these problems. While powerful, BPMN comes with significant baggage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Heavyweight Libraries: They often require complex database schemas, massive dependencies, and a lot of boilerplate to set up.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Not Truly Human-Readable: While the diagrams look nice, the underlying XML is a nightmare to read, version control, or manually edit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Steep Learning Curve: You often need specialized training just to configure the engine.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted something lightweight, JSON-native, and Spring-friendly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution.&lt;/strong&gt;&lt;br&gt;
Camino allows you to define a "Flow" as a series of Blocks in a JSON file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Add Camino to your application&lt;/strong&gt;&lt;br&gt;
Download the camino code from &lt;a href="https://github.com/a-koro/camino" rel="noopener noreferrer"&gt;https://github.com/a-koro/camino&lt;/a&gt; , build it locally and add the dependency in your pom file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;com.korovesys&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;camino&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.1-SNAPSHOT&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Define the Flow&lt;/strong&gt;&lt;br&gt;
A Camino JSON flow defines a logical sequence using four primary block types: START, ACTION, INTERSECTION, and END.&lt;/p&gt;

&lt;p&gt;There is also a dedicate Camino Flow Editor you can download and run in any browser: &lt;a href="https://github.com/a-koro/CaminoFlowEditor" rel="noopener noreferrer"&gt;https://github.com/a-koro/CaminoFlowEditor&lt;/a&gt;&lt;br&gt;
Editor guide: &lt;a href="https://dev.to/korove_sys/i-built-a-zero-dependency-visual-json-flow-editor-in-vanilla-js-for-the-camino-flow-engine-j1g"&gt;https://dev.to/korove_sys/i-built-a-zero-dependency-visual-json-flow-editor-in-vanilla-js-for-the-camino-flow-engine-j1g&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default, flow files are located in the Maven-standard resource directory &lt;em&gt;src/main/resources/camino&lt;/em&gt; .&lt;/p&gt;

&lt;p&gt;To customize this location, update the following property in your configuration &lt;em&gt;camino.path=/your/custom/path&lt;/em&gt; .&lt;/p&gt;

&lt;p&gt;Here's a snippet where we check a user's name before deciding which action to take &lt;em&gt;(condition expressions use MVEL)&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"myFirstFlow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"blocks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"START"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"nextId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"getNameFromIdAction"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ACTION"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"getNameFromIdActionHandler"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"nextId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"checkNameIntersection"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"INTERSECTION"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"conditions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"expression"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name.equals('George')"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"nextId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"no"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"defaultCondition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"nextId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"updateUserAction"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ACTION"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"updateUserActionHandler"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"nextId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"6"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"informUserAction"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ACTION"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"informUserActionHandler"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"nextId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"6"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"END"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Implement the Logic&lt;/strong&gt;&lt;br&gt;
You don't lose the power of Java. You start the execution of the flow as defined in your JSON file by calling the FlowExecutor method execute and passing as parameters the name of the flow and a map to carry all your data (process context). The same map will be used to evaluate each condition in your flow with the provided key. &lt;/p&gt;

&lt;p&gt;For every ACTION in your JSON, you simply create a class that extends AbstractActionHandler and declare the bean using the same name from the corresponding "action" property.&lt;/p&gt;

&lt;p&gt;You process context is propagated in each action in the flow as a HashMap and can me accessed from the &lt;em&gt;ctx&lt;/em&gt; property of the execute method.&lt;br&gt;
Finally use this map to construct the response data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GetNameFromIdActionHandler&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractActionHandler&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"executing get name from ID action handler"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;GetNameFromIdActionHandler&lt;/span&gt; &lt;span class="nf"&gt;getNameFromIdActionHandler&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;GetNameFromIdActionHandler&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Enable the library&lt;/strong&gt;&lt;br&gt;
Add &lt;em&gt;spring.camino.enabled=true&lt;/em&gt; to your application properties file.&lt;/p&gt;




&lt;p&gt;Final Thoughts&lt;/p&gt;

&lt;p&gt;Hardcoding business logic into your Java services creates a rigid architecture that's expensive to change. By adopting a flow-based approach, you give your application the flexibility to grow alongside your business requirements.&lt;/p&gt;

&lt;p&gt;⭐️ Check it out on GitHub: &lt;a href="https://github.com/a-koro/camino" rel="noopener noreferrer"&gt;https://github.com/a-koro/camino&lt;/a&gt;&lt;br&gt;
🚀 See the demo: &lt;a href="https://github.com/a-koro/caminoDemoApplication" rel="noopener noreferrer"&gt;https://github.com/a-koro/caminoDemoApplication&lt;/a&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>java</category>
      <category>caminoengine</category>
    </item>
  </channel>
</rss>
