You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ma...@apache.org on 2022/03/11 22:47:16 UTC

[camel-karavan] branch main updated: First demo (#210)

This is an automated email from the ASF dual-hosted git repository.

marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git


The following commit(s) were added to refs/heads/main by this push:
     new 81cf174  First demo (#210)
81cf174 is described below

commit 81cf1746b98d17b05135ace11dbe79c46afb86ba
Author: Marat Gubaidullin <ma...@gmail.com>
AuthorDate: Fri Mar 11 17:47:12 2022 -0500

    First demo (#210)
    
    * Fix vscode staff
    
    * First try
    
    * First demo works
    
    * Next level
    
    * Stage 2
    
    * End-to-end demo
---
 karavan-core/src/core/api/CamelDefinitionApi.ts    |  34 +-----
 karavan-core/src/core/api/CamelDefinitionYaml.ts   |  14 ++-
 .../src/core/api/CamelDefinitionYamlStep.ts        |  31 +----
 karavan-core/src/core/model/CamelDefinition.ts     |  27 +----
 karavan-core/src/core/model/CamelMetadata.ts       |  14 +--
 karavan-core/test/backward.spec.ts                 |   3 +-
 karavan-core/test/backward.yaml                    |  12 +-
 karavan-core/test/expression.spec.ts               |   7 +-
 karavan-demo/postman/README.md                     |  13 ++
 karavan-demo/postman/docker-compose.yml            |  63 ++++++++++
 karavan-demo/postman/postgres_db.sql               |   6 +
 karavan-demo/postman/postman.yaml                  | 133 +++++++++++++++++++++
 karavan-demo/postman/start.sh                      |   7 ++
 karavan-designer/public/components/aws2-sqs.json   |   2 +-
 karavan-designer/public/components/tika.json       |   2 +-
 karavan-designer/src/App.tsx                       |   2 +-
 .../designer/route/property/DslPropertyField.tsx   |   1 +
 karavan-designer/src/designer/utils/CamelUi.ts     |   3 +-
 karavan-vscode/components/aws2-sqs.json            |   2 +-
 karavan-vscode/components/tika.json                |   2 +-
 karavan-vscode/src/extension.ts                    |  54 +++++----
 karavan-vscode/webview/App.tsx                     |  68 ++++++-----
 22 files changed, 331 insertions(+), 169 deletions(-)

diff --git a/karavan-core/src/core/api/CamelDefinitionApi.ts b/karavan-core/src/core/api/CamelDefinitionApi.ts
index 715e434..17305f3 100644
--- a/karavan-core/src/core/api/CamelDefinitionApi.ts
+++ b/karavan-core/src/core/api/CamelDefinitionApi.ts
@@ -91,7 +91,6 @@ import {
     SplitDefinition,
     StepDefinition,
     StopDefinition,
-    SwitchDefinition,
     TemplatedRouteBeanDefinition,
     TemplatedRouteDefinition,
     TemplatedRouteParameterDefinition,
@@ -226,7 +225,6 @@ import {
     RestSecuritiesDefinition,
     RestsDefinition,
     SecurityDefinition,
-    SecurityRequirementsDefinition,
     CustomTransformerDefinition,
     DataFormatTransformerDefinition,
     EndpointTransformerDefinition,
@@ -331,9 +329,6 @@ export class CamelDefinitionApi {
         if (element?.intercept !== undefined) { 
             def.intercept = CamelDefinitionApi.createInterceptDefinition(element.intercept); 
         } 
-        if (element?.doSwitch !== undefined) { 
-            def.doSwitch = CamelDefinitionApi.createSwitchDefinition(element.doSwitch); 
-        } 
         if (element?.whenSkipSendToEndpoint !== undefined) { 
             def.whenSkipSendToEndpoint = CamelDefinitionApi.createWhenSkipSendToEndpointDefinition(element.whenSkipSendToEndpoint); 
         } 
@@ -1462,18 +1457,6 @@ export class CamelDefinitionApi {
         return def;
     }
 
-    static createSwitchDefinition = (element: any): SwitchDefinition => {
-        
-        const def = element ? new SwitchDefinition({...element}) : new SwitchDefinition();
-        def.uuid = element?.uuid ? element.uuid : def.uuid;
-        if (element?.otherwise !== undefined) { 
-            def.otherwise = CamelDefinitionApi.createOtherwiseDefinition(element.otherwise); 
-        } 
-        def.when = element && element?.when ? element?.when.map((x:any) => CamelDefinitionApi.createWhenDefinition(x)) :[]; 
-
-        return def;
-    }
-
     static createTemplatedRouteBeanDefinition = (element: any): TemplatedRouteBeanDefinition => {
         
         const def = element ? new TemplatedRouteBeanDefinition({...element}) : new TemplatedRouteBeanDefinition();
@@ -3038,9 +3021,7 @@ export class CamelDefinitionApi {
         def.patch = element && element?.patch ? element?.patch.map((x:any) => CamelDefinitionApi.createPatchDefinition(x)) :[]; 
         def.post = element && element?.post ? element?.post.map((x:any) => CamelDefinitionApi.createPostDefinition(x)) :[]; 
         def.get = element && element?.get ? element?.get.map((x:any) => CamelDefinitionApi.createGetDefinition(x)) :[]; 
-        if (element?.securityRequirements !== undefined) { 
-            def.securityRequirements = CamelDefinitionApi.createSecurityRequirementsDefinition(element.securityRequirements); 
-        } 
+        def.securityRequirements = element && element?.securityRequirements ? element?.securityRequirements.map((x:any) => CamelDefinitionApi.createSecurityDefinition(x)) :[]; 
         def.delete = element && element?.delete ? element?.delete.map((x:any) => CamelDefinitionApi.createDeleteDefinition(x)) :[]; 
         if (element?.securityDefinitions !== undefined) { 
             def.securityDefinitions = CamelDefinitionApi.createRestSecuritiesDefinition(element.securityDefinitions); 
@@ -3101,17 +3082,6 @@ export class CamelDefinitionApi {
         return def;
     }
 
-    static createSecurityRequirementsDefinition = (element: any): SecurityRequirementsDefinition => {
-        
-        const def = element ? new SecurityRequirementsDefinition({...element}) : new SecurityRequirementsDefinition();
-        def.uuid = element?.uuid ? element.uuid : def.uuid;
-        if (element?.securityRequirement !== undefined) { 
-            def.securityRequirement = CamelDefinitionApi.createSecurityDefinition(element.securityRequirement); 
-        } 
-
-        return def;
-    }
-
     static createCustomTransformerDefinition = (element: any): CustomTransformerDefinition => {
         
         const def = element ? new CustomTransformerDefinition({...element}) : new CustomTransformerDefinition();
@@ -3406,7 +3376,6 @@ export class CamelDefinitionApi {
             case 'SplitDefinition': return CamelDefinitionApi.createSplitDefinition(newBody);
             case 'StepDefinition': return CamelDefinitionApi.createStepDefinition(newBody);
             case 'StopDefinition': return CamelDefinitionApi.createStopDefinition(newBody);
-            case 'SwitchDefinition': return CamelDefinitionApi.createSwitchDefinition(newBody);
             case 'TemplatedRouteBeanDefinition': return CamelDefinitionApi.createTemplatedRouteBeanDefinition(newBody);
             case 'TemplatedRouteDefinition': return CamelDefinitionApi.createTemplatedRouteDefinition(newBody);
             case 'TemplatedRouteParameterDefinition': return CamelDefinitionApi.createTemplatedRouteParameterDefinition(newBody);
@@ -3541,7 +3510,6 @@ export class CamelDefinitionApi {
             case 'RestSecuritiesDefinition': return CamelDefinitionApi.createRestSecuritiesDefinition(newBody);
             case 'RestsDefinition': return CamelDefinitionApi.createRestsDefinition(newBody);
             case 'SecurityDefinition': return CamelDefinitionApi.createSecurityDefinition(newBody);
-            case 'SecurityRequirementsDefinition': return CamelDefinitionApi.createSecurityRequirementsDefinition(newBody);
             case 'CustomTransformerDefinition': return CamelDefinitionApi.createCustomTransformerDefinition(newBody);
             case 'DataFormatTransformerDefinition': return CamelDefinitionApi.createDataFormatTransformerDefinition(newBody);
             case 'EndpointTransformerDefinition': return CamelDefinitionApi.createEndpointTransformerDefinition(newBody);
diff --git a/karavan-core/src/core/api/CamelDefinitionYaml.ts b/karavan-core/src/core/api/CamelDefinitionYaml.ts
index 32accd6..5547554 100644
--- a/karavan-core/src/core/api/CamelDefinitionYaml.ts
+++ b/karavan-core/src/core/api/CamelDefinitionYaml.ts
@@ -19,7 +19,7 @@ import {Integration, CamelElement, Beans, Dependency,} from "../model/Integratio
 import {RouteDefinition, NamedBeanDefinition} from "../model/CamelDefinition";
 import {CamelUtil} from "./CamelUtil";
 import {CamelDefinitionYamlStep} from "./CamelDefinitionYamlStep";
-import {CamelTrait, Trait, TraitApi} from "../model/TraitDefinition";
+import {Trait, TraitApi} from "../model/TraitDefinition";
 
 export class CamelDefinitionYaml {
 
@@ -143,6 +143,7 @@ export class CamelDefinitionYaml {
         if (typeof value === 'object' && (value.hasOwnProperty('stepName') || value.hasOwnProperty('inArray')  || value.hasOwnProperty('inSteps'))) {
             const stepNameField = value.hasOwnProperty('stepName') ? 'stepName' : 'step-name';
             const stepName = value[stepNameField];
+            const dslName = value.dslName;
             let newValue: any = JSON.parse(JSON.stringify(value));
             delete newValue.dslName;
             if (backward && stepName === 'route'){
@@ -151,7 +152,10 @@ export class CamelDefinitionYaml {
             }
             delete newValue[stepNameField];
             if ((value.inArray && !value.inSteps)
-                || stepName === 'expression'
+                || dslName === 'ExpressionSubElementDefinition'
+                || dslName === 'ExpressionDefinition'
+                || dslName?.endsWith('Expression')
+                || stepName === 'otherwise'
                 || key === 'from') {
                 delete newValue.inArray;
                 delete newValue.inSteps;
@@ -164,15 +168,15 @@ export class CamelDefinitionYaml {
                 return xValue;
             }
         } else {
-            if (value.dslName && value.dslName.endsWith("Trait") && value.dslName !== 'Trait'){
+            if (value?.dslName && value.dslName.endsWith("Trait") && value.dslName !== 'Trait'){
                 delete value.dslName;
                 return {configuration: value};
-            } else if (value.dslName === 'Trait' && value.threeScale){
+            } else if (value?.dslName === 'Trait' && value?.threeScale){
                 delete value.dslName;
                 value["3scale"] = {configuration: value.threeScale};
                 return value;
             }
-            delete value.dslName;
+            delete value?.dslName;
             return value;
         }
     }
diff --git a/karavan-core/src/core/api/CamelDefinitionYamlStep.ts b/karavan-core/src/core/api/CamelDefinitionYamlStep.ts
index d20d4f2..f87d06f 100644
--- a/karavan-core/src/core/api/CamelDefinitionYamlStep.ts
+++ b/karavan-core/src/core/api/CamelDefinitionYamlStep.ts
@@ -92,7 +92,6 @@ import {
     SplitDefinition,
     StepDefinition,
     StopDefinition,
-    SwitchDefinition,
     TemplatedRouteBeanDefinition,
     TemplatedRouteDefinition,
     TemplatedRouteParameterDefinition,
@@ -227,7 +226,6 @@ import {
     RestSecuritiesDefinition,
     RestsDefinition,
     SecurityDefinition,
-    SecurityRequirementsDefinition,
     CustomTransformerDefinition,
     DataFormatTransformerDefinition,
     EndpointTransformerDefinition,
@@ -332,9 +330,6 @@ export class CamelDefinitionYamlStep {
         if (element?.intercept !== undefined) { 
             def.intercept = CamelDefinitionYamlStep.readInterceptDefinition(element.intercept); 
         } 
-        if (element?.doSwitch !== undefined) { 
-            def.doSwitch = CamelDefinitionYamlStep.readSwitchDefinition(element.doSwitch); 
-        } 
         if (element?.whenSkipSendToEndpoint !== undefined) { 
             def.whenSkipSendToEndpoint = CamelDefinitionYamlStep.readWhenSkipSendToEndpointDefinition(element.whenSkipSendToEndpoint); 
         } 
@@ -1546,17 +1541,6 @@ export class CamelDefinitionYamlStep {
         return def;
     }
 
-    static readSwitchDefinition = (element: any): SwitchDefinition => {
-        
-        const def = element ? new SwitchDefinition({...element}) : new SwitchDefinition();
-        if (element?.otherwise !== undefined) { 
-            def.otherwise = CamelDefinitionYamlStep.readOtherwiseDefinition(element.otherwise); 
-        } 
-        def.when = element && element?.when ? element?.when.map((x:any) => CamelDefinitionYamlStep.readWhenDefinition(x)) :[]; 
-
-        return def;
-    }
-
     static readTemplatedRouteBeanDefinition = (element: any): TemplatedRouteBeanDefinition => {
         
         const def = element ? new TemplatedRouteBeanDefinition({...element}) : new TemplatedRouteBeanDefinition();
@@ -3051,9 +3035,7 @@ export class CamelDefinitionYamlStep {
         def.patch = element && element?.patch ? element?.patch.map((x:any) => CamelDefinitionYamlStep.readPatchDefinition(x)) :[]; 
         def.post = element && element?.post ? element?.post.map((x:any) => CamelDefinitionYamlStep.readPostDefinition(x)) :[]; 
         def.get = element && element?.get ? element?.get.map((x:any) => CamelDefinitionYamlStep.readGetDefinition(x)) :[]; 
-        if (element?.securityRequirements !== undefined) { 
-            def.securityRequirements = CamelDefinitionYamlStep.readSecurityRequirementsDefinition(element.securityRequirements); 
-        } 
+        def.securityRequirements = element && element?.securityRequirements ? element?.securityRequirements.map((x:any) => CamelDefinitionYamlStep.readSecurityDefinition(x)) :[]; 
         def.delete = element && element?.delete ? element?.delete.map((x:any) => CamelDefinitionYamlStep.readDeleteDefinition(x)) :[]; 
         if (element?.securityDefinitions !== undefined) { 
             def.securityDefinitions = CamelDefinitionYamlStep.readRestSecuritiesDefinition(element.securityDefinitions); 
@@ -3110,16 +3092,6 @@ export class CamelDefinitionYamlStep {
         return def;
     }
 
-    static readSecurityRequirementsDefinition = (element: any): SecurityRequirementsDefinition => {
-        
-        const def = element ? new SecurityRequirementsDefinition({...element}) : new SecurityRequirementsDefinition();
-        if (element?.securityRequirement !== undefined) { 
-            def.securityRequirement = CamelDefinitionYamlStep.readSecurityDefinition(element.securityRequirement); 
-        } 
-
-        return def;
-    }
-
     static readCustomTransformerDefinition = (element: any): CustomTransformerDefinition => {
         
         const def = element ? new CustomTransformerDefinition({...element}) : new CustomTransformerDefinition();
@@ -3368,7 +3340,6 @@ export class CamelDefinitionYamlStep {
             case 'wireTap': return CamelDefinitionYamlStep.readWireTapDefinition(newBody);
             case 'kamelet': return CamelDefinitionYamlStep.readKameletDefinition(newBody);
             case 'interceptFrom': return CamelDefinitionYamlStep.readInterceptFromDefinition(newBody);
-            case 'doSwitch': return CamelDefinitionYamlStep.readSwitchDefinition(newBody);
             case 'doFinally': return CamelDefinitionYamlStep.readFinallyDefinition(newBody);
             case 'idempotentConsumer': return CamelDefinitionYamlStep.readIdempotentConsumerDefinition(newBody);
             case 'removeHeader': return CamelDefinitionYamlStep.readRemoveHeaderDefinition(newBody);
diff --git a/karavan-core/src/core/model/CamelDefinition.ts b/karavan-core/src/core/model/CamelDefinition.ts
index 08ec691..9d7fd10 100644
--- a/karavan-core/src/core/model/CamelDefinition.ts
+++ b/karavan-core/src/core/model/CamelDefinition.ts
@@ -33,7 +33,6 @@ export class ProcessorDefinition extends CamelElement {
     stop?: StopDefinition;
     serviceCall?: ServiceCallDefinition | string;
     intercept?: InterceptDefinition;
-    doSwitch?: SwitchDefinition;
     whenSkipSendToEndpoint?: WhenSkipSendToEndpointDefinition;
     setProperty?: SetPropertyDefinition;
     removeProperty?: RemovePropertyDefinition | string;
@@ -229,6 +228,7 @@ export class ChoiceDefinition extends CamelElement {
     stepName?: string = 'choice';
     description?: string;
     id?: string;
+    precondition?: boolean;
     when?: WhenDefinition[] = []
     public constructor(init?: Partial<ChoiceDefinition>) {
         super('ChoiceDefinition')
@@ -1137,6 +1137,7 @@ export class RouteConfigurationDefinition extends CamelElement {
     intercept?: InterceptDefinition[] = [];
     onException?: OnExceptionDefinition[] = [];
     id?: string;
+    precondition?: string;
     interceptFrom?: InterceptFromDefinition[] = []
     public constructor(init?: Partial<RouteConfigurationDefinition>) {
         super('RouteConfigurationDefinition')
@@ -1388,19 +1389,6 @@ export class StopDefinition extends CamelElement {
     }
 }
 
-export class SwitchDefinition extends CamelElement {
-    otherwise?: OtherwiseDefinition;
-    inheritErrorHandler?: boolean;
-    stepName?: string = 'doSwitch';
-    description?: string;
-    id?: string;
-    when?: WhenDefinition[] = []
-    public constructor(init?: Partial<SwitchDefinition>) {
-        super('SwitchDefinition')
-        Object.assign(this, init)
-    }
-}
-
 export class TemplatedRouteBeanDefinition extends CamelElement {
     stepName?: string = 'templatedRouteBean';
     name: string = '';
@@ -3494,7 +3482,7 @@ export class RestConfigurationDefinition extends CamelElement {
 
 export class RestDefinition extends CamelElement {
     enableCors?: boolean;
-    securityRequirements?: SecurityRequirementsDefinition;
+    securityRequirements?: SecurityDefinition[] = [];
     description?: string;
     delete?: DeleteDefinition[] = [];
     put?: PutDefinition[] = [];
@@ -3564,15 +3552,6 @@ export class SecurityDefinition extends CamelElement {
     }
 }
 
-export class SecurityRequirementsDefinition extends CamelElement {
-    stepName?: string = 'securityRequirements';
-    securityRequirement?: SecurityDefinition
-    public constructor(init?: Partial<SecurityRequirementsDefinition>) {
-        super('SecurityRequirementsDefinition')
-        Object.assign(this, init)
-    }
-}
-
 export class CustomTransformerDefinition extends CamelElement {
     ref?: string;
     toType?: string;
diff --git a/karavan-core/src/core/model/CamelMetadata.ts b/karavan-core/src/core/model/CamelMetadata.ts
index f9ff600..c355f40 100644
--- a/karavan-core/src/core/model/CamelMetadata.ts
+++ b/karavan-core/src/core/model/CamelMetadata.ts
@@ -992,13 +992,6 @@ export const CamelModelMetadata: ElementMeta[] = [
         new PropertyMeta('parameters', 'parameters', "parameters", 'object', '', '', false, false, false, false, ''),
         new PropertyMeta('steps', 'steps', "steps", 'CamelElement', '', '', false, false, true, true, ''),
     ]),
-    new ElementMeta('doSwitch', 'SwitchDefinition', 'Do Switch', "Route messages based on a series of predicates (optimized during startup to select one predicate that will always be used)", 'eip,routing', [
-        new PropertyMeta('when', 'When', "Sets the when nodes", 'WhenDefinition', '', '', false, false, true, true, ''),
-        new PropertyMeta('otherwise', 'Otherwise', "Sets the otherwise node", 'OtherwiseDefinition', '', '', false, false, false, true, ''),
-        new PropertyMeta('id', 'Id', "Sets the id of this node", 'string', '', '', false, false, false, false, ''),
-        new PropertyMeta('description', 'Description', "Sets the description of this node", 'string', '', '', false, false, false, false, ''),
-        new PropertyMeta('steps', 'steps', "steps", 'CamelElement', '', '', false, false, true, true, ''),
-    ]),
     new ElementMeta('globalOption', 'GlobalOptionDefinition', 'Global Option', "Models a string key/value pair for configuring some global options on a Camel context such as max debug log length.", 'configuration', [
         new PropertyMeta('key', 'Key', "Global option key", 'string', '', '', true, false, false, false, ''),
         new PropertyMeta('value', 'Value', "Global option value", 'string', '', '', true, false, false, false, ''),
@@ -1272,6 +1265,7 @@ export const CamelModelMetadata: ElementMeta[] = [
     new ElementMeta('choice', 'ChoiceDefinition', 'Choice', "Route messages based on a series of predicates", 'eip,routing', [
         new PropertyMeta('when', 'When', "Sets the when nodes", 'WhenDefinition', '', '', false, false, true, true, ''),
         new PropertyMeta('otherwise', 'Otherwise', "Sets the otherwise node", 'OtherwiseDefinition', '', '', false, false, false, true, ''),
+        new PropertyMeta('precondition', 'Precondition', "Indicates whether this Choice EIP is in precondition mode or not. If so its branches (when/otherwise) are evaluated during startup to keep at runtime only the branch that matched.", 'boolean', '', 'false', false, false, false, false, 'advanced'),
         new PropertyMeta('id', 'Id', "Sets the id of this node", 'string', '', '', false, false, false, false, ''),
         new PropertyMeta('description', 'Description', "Sets the description of this node", 'string', '', '', false, false, false, false, ''),
         new PropertyMeta('steps', 'steps', "steps", 'CamelElement', '', '', false, false, true, true, ''),
@@ -1696,6 +1690,7 @@ export const CamelModelMetadata: ElementMeta[] = [
         new PropertyMeta('interceptSendToEndpoint', 'Intercept Send To Endpoint', "Applies a route for an interceptor if an exchange is send to the given endpoint", 'InterceptSendToEndpointDefinition', '', '', false, false, true, true, ''),
         new PropertyMeta('onException', 'On Exception', "Exception clause for catching certain exceptions and handling them.", 'OnExceptionDefinition', '', '', false, false, true, true, ''),
         new PropertyMeta('onCompletion', 'On Completion', "On completion callback for doing custom routing when the org.apache.camel.Exchange is complete.", 'OnCompletionDefinition', '', '', false, false, true, true, ''),
+        new PropertyMeta('precondition', 'Precondition', "The predicate of the precondition in simple language to evaluate in order to determine if this route configuration should be included or not.", 'string', '', '', false, false, false, false, 'advanced'),
         new PropertyMeta('id', 'Id', "Sets the id of this node", 'string', '', '', false, false, false, false, ''),
     ]),
     new ElementMeta('optimisticLockRetryPolicy', 'OptimisticLockRetryPolicyDefinition', 'Optimistic Lock Retry Policy', "To configure optimistic locking", 'configuration', [
@@ -1850,7 +1845,7 @@ export const CamelModelMetadata: ElementMeta[] = [
         new PropertyMeta('apiDocs', 'Api Docs', "Whether to include or exclude this rest operation in API documentation. This option will override what may be configured on a parent level. The default value is true.", 'boolean', '', 'true', false, false, false, false, 'advanced'),
         new PropertyMeta('tag', 'Tag', "To configure a special tag for the operations within this rest definition.", 'string', '', '', false, false, false, false, 'advanced'),
         new PropertyMeta('securityDefinitions', 'Security Definitions', "Sets the security definitions such as Basic, OAuth2 etc.", 'RestSecuritiesDefinition', '', '', false, false, false, true, 'security'),
-        new PropertyMeta('securityRequirements', 'Security Requirements', "Sets the security requirement(s) for all endpoints.", 'SecurityRequirementsDefinition', '', '', false, false, false, true, 'security'),
+        new PropertyMeta('securityRequirements', 'Security Requirements', "Sets the security requirement(s) for all endpoints.", 'SecurityDefinition', '', '', false, false, true, true, 'security'),
         new PropertyMeta('id', 'Id', "Sets the id of this node", 'string', '', '', false, false, false, false, ''),
         new PropertyMeta('description', 'Description', "Sets the description of this node", 'string', '', '', false, false, false, false, ''),
         new PropertyMeta('delete', 'delete', "delete", 'DeleteDefinition', '', '', false, false, true, true, ''),
@@ -1932,9 +1927,6 @@ export const CamelModelMetadata: ElementMeta[] = [
         new PropertyMeta('description', 'Description', "Sets the description of this node", 'string', '', '', false, false, false, false, ''),
         new PropertyMeta('steps', 'steps', "steps", 'CamelElement', '', '', false, false, true, true, ''),
     ]),
-    new ElementMeta('securityRequirements', 'SecurityRequirementsDefinition', 'Rest Security Requirements', "To configure global rest security requirements.", 'rest,security,configuration', [
-        new PropertyMeta('securityRequirement', 'securityRequirement', "securityRequirement", 'SecurityDefinition', '', '', false, false, false, true, ''),
-    ]),
     new ElementMeta('outputType', 'OutputTypeDefinition', 'Output Type', "Set the expected data type of the output message. If the actual message type is different at runtime, camel look for a required Transformer and apply if exists. If validate attribute is true then camel applies Validator as well. Type name consists of two parts, 'scheme' and 'name' connected with ':'. For Java type 'name' is a fully qualified class name. For example {code java:java.lang.String} , {code json:ABCOrder [...]
         new PropertyMeta('urn', 'Urn', "Set output type URN.", 'string', '', '', true, false, false, false, ''),
         new PropertyMeta('validate', 'Validate', "Whether if validation is required for this output type.", 'boolean', '', 'false', false, false, false, false, ''),
diff --git a/karavan-core/test/backward.spec.ts b/karavan-core/test/backward.spec.ts
index bc79998..1d20fbd 100644
--- a/karavan-core/test/backward.spec.ts
+++ b/karavan-core/test/backward.spec.ts
@@ -41,7 +41,7 @@ describe('Backward for Camel version < 3.16.x', () => {
             steps: [new LogDefinition({logName: 'log11', message: "hello11"})]
         })
         const when2 = new WhenDefinition({
-            expression: new ExpressionDefinition({simple: '${body} == null'}),
+            expression: new ExpressionDefinition({simple: new SimpleExpression({expression:'${body} == null'})}),
             steps: [new LogDefinition({logName: 'log22', message: "hello22"})]
         })
         const otherwise = new OtherwiseDefinition({steps: [new LogDefinition({logName: 'logX', message: "helloX"})]})
@@ -61,6 +61,7 @@ describe('Backward for Camel version < 3.16.x', () => {
         i1.spec.flows?.push(new RouteDefinition({from: flow2}));
         const yaml1 = CamelDefinitionYaml.integrationToYaml(i1, true);
         const yaml2 = fs.readFileSync('test/backward.yaml',{encoding:'utf8', flag:'r'});
+        console.log(yaml1)
         expect(yaml1).to.equal(yaml2);
     });
 
diff --git a/karavan-core/test/backward.yaml b/karavan-core/test/backward.yaml
index ac24364..0426c19 100644
--- a/karavan-core/test/backward.yaml
+++ b/karavan-core/test/backward.yaml
@@ -16,17 +16,17 @@ spec:
                         message: hello11
                         logName: log11
                 - expression:
-                    simple: ${body} == null
+                    simple:
+                      expression: ${body} == null
                   steps:
                     - log:
                         message: hello22
                         logName: log22
               otherwise:
-                otherwise:
-                  steps:
-                    - log:
-                        message: helloX
-                        logName: logX
+                steps:
+                  - log:
+                      message: helloX
+                      logName: logX
           - to:
               uri: kamelet:kamelet2
           - to:
diff --git a/karavan-core/test/expression.spec.ts b/karavan-core/test/expression.spec.ts
index 9d80b62..04647e0 100644
--- a/karavan-core/test/expression.spec.ts
+++ b/karavan-core/test/expression.spec.ts
@@ -30,7 +30,7 @@ import {
 } from "../src/core/model/CamelDefinition";
 import { RouteDefinition} from "../src/core/model/CamelDefinition";
 import {Integration} from "../src/core/model/IntegrationDefinition";
-import {AggregateDefinition} from "../lib/model/CamelDefinition";
+import {AggregateDefinition, ExpressionSubElementDefinition, FilterDefinition} from "../lib/model/CamelDefinition";
 
 describe('Expression to yaml', () => {
 
@@ -38,11 +38,14 @@ describe('Expression to yaml', () => {
         const i1 = Integration.createNew("test")
 
         const agg = new AggregateDefinition({
-            correlationExpression: new ExpressionDefinition({simple: new SimpleExpression({expression:'${body} != null'})}),
+            correlationExpression: new ExpressionSubElementDefinition({simple: new SimpleExpression({expression:'${body} != null'})}),
             steps: [new LogDefinition({logName: 'log11', message: "hello11"})]
         })
 
+        const filter = new FilterDefinition({expression: new ExpressionDefinition({simple: new SimpleExpression({expression:"not null"})})})
+
         const flow1 = new FromDefinition({uri: "direct1"});
+        flow1.steps?.push(filter);
         flow1.steps?.push(agg);
         i1.spec.flows?.push(new RouteDefinition({from: flow1}));
 
diff --git a/karavan-demo/postman/README.md b/karavan-demo/postman/README.md
new file mode 100644
index 0000000..a93c745
--- /dev/null
+++ b/karavan-demo/postman/README.md
@@ -0,0 +1,13 @@
+
+```
+curl -X POST -H "Content-Type: application/json" --data '{"id":1,"address":"666 Sin Street, Holy City"}' http://0.0.0.0:8080/parcels
+```
+
+```
+<?xml version="1.0" encoding="UTF-8" ?>
+<root>
+  <id>1</id>
+  <amount>777</amount>
+  <status>confirmed</status>  
+</root>
+```
\ No newline at end of file
diff --git a/karavan-demo/postman/docker-compose.yml b/karavan-demo/postman/docker-compose.yml
new file mode 100644
index 0000000..852194a
--- /dev/null
+++ b/karavan-demo/postman/docker-compose.yml
@@ -0,0 +1,63 @@
+---
+version: '3.8'
+services:
+
+  zookeeper:
+    container_name: zookeeper
+    image: confluentinc/cp-zookeeper:latest
+    ports:
+      - "2181:2181"
+    environment:
+      ZOOKEEPER_CLIENT_PORT: 2181
+      ZOOKEEPER_TICK_TIME: 2000
+
+  kafka:
+    container_name: kafka
+    image: confluentinc/cp-kafka:latest
+    depends_on:
+      - zookeeper
+    ports:
+      - "9092:9092"
+    environment:
+      KAFKA_BROKER_ID: 1
+      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
+      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092
+      KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
+      KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
+      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
+      KAFKA_CREATE_TOPICS: "events:1:1"
+
+  activemq:
+    image: registry.redhat.io/amq7/amq-broker:latest
+    container_name: activemq
+    environment:
+      - AMQ_USER=admin
+      - AMQ_PASSWORD=admin
+    ports:
+      - "61616:61616"
+      - "1883:1883"
+      - "8161:8161"  
+  
+  postgres:
+    image: postgres
+    container_name: postgres
+    restart: always
+    environment:
+      - POSTGRES_USER=postgres
+      - POSTGRES_PASSWORD=postgres
+      - POSTGRES_DB=demo
+    ports:
+      - '5432:5432'
+    volumes:
+      - ./postgres_db.sql:/docker-entrypoint-initdb.d/postgres_db.sql
+    command: 'postgres --max_prepared_transactions=100'
+
+  pgadmin:
+    container_name: pgadmin
+    image: dpage/pgadmin4
+    restart: always
+    environment:
+      PGADMIN_DEFAULT_EMAIL: admin@admin.com
+      PGADMIN_DEFAULT_PASSWORD: root
+    ports:
+      - "5050:80"
diff --git a/karavan-demo/postman/postgres_db.sql b/karavan-demo/postman/postgres_db.sql
new file mode 100644
index 0000000..92a7bbb
--- /dev/null
+++ b/karavan-demo/postman/postgres_db.sql
@@ -0,0 +1,6 @@
+CREATE TABLE IF NOT EXISTS parcels (
+  id varchar(250) NOT NULL,
+  address varchar(250) NOT NULL,
+  status varchar(250),
+  PRIMARY KEY (id)
+);
diff --git a/karavan-demo/postman/postman.yaml b/karavan-demo/postman/postman.yaml
new file mode 100644
index 0000000..3084a05
--- /dev/null
+++ b/karavan-demo/postman/postman.yaml
@@ -0,0 +1,133 @@
+apiVersion: camel.apache.org/v1
+kind: Integration
+metadata:
+  name: postman.yaml
+spec:
+  flows:
+    - rest:
+        post:
+          - to: direct:post
+        path: /parcels
+        consumes: application/json
+        produces: application/json
+    - route:
+        from:
+          uri: direct:post
+          steps:
+            - log:
+                message: 'Received: ${body}'
+            - multicast:
+                steps:
+                  - kamelet:
+                      name: kafka-not-secured-sink
+                      parameters:
+                        topic: parcels
+                        bootstrapServers: localhost:9092
+                  - kamelet:
+                      name: postgresql-sink
+                      parameters:
+                        serverName: localhost
+                        serverPort: '5432'
+                        username: postgres
+                        password: postgres
+                        databaseName: demo
+                        query: >-
+                          INSERT INTO parcels (id,address) VALUES
+                          (:#id,:#address) ON CONFLICT (id)  DO NOTHING
+                aggregationStrategy: >-
+                  #class:org.apache.camel.processor.aggregate.UseOriginalAggregationStrategy
+                parallelProcessing: false
+                streaming: false
+        id: post
+    - route:
+        from:
+          uri: kamelet:jms-apache-artemis-source
+          steps:
+            - to:
+                uri: xj:identity
+                parameters:
+                  transformDirection: XML2JSON
+            - kamelet:
+                name: kafka-not-secured-sink
+                parameters:
+                  topic: payments
+                  bootstrapServers: localhost:9092
+          parameters:
+            destinationType: queue
+            destinationName: payments
+            brokerURL: tcp://localhost:61616
+        id: payment
+    - route:
+        from:
+          uri: kamelet:kafka-not-secured-source
+          steps:
+            - log:
+                message: 'Aggegating: ${body}'
+            - unmarshal:
+                json:
+                  library: jackson
+            - aggregate:
+                steps:
+                  - choice:
+                      when:
+                        - expression:
+                            groovy:
+                              expression: >-
+                                body.find { it.containsKey('status') }.status ==
+                                'confirmed'
+                          steps:
+                            - marshal:
+                                json:
+                                  library: jackson
+                            - log:
+                                message: 'Send to MQTT : ${body}'
+                            - kamelet:
+                                name: mqtt-sink
+                                parameters:
+                                  topic: deliveries
+                                  brokerUrl: tcp://localhost:1883
+                      otherwise:
+                        steps:
+                          - setBody:
+                              expression:
+                                groovy:
+                                  expression: 'body.find { it.containsKey(''status'') } '
+                          - marshal:
+                              json:
+                                library: jackson
+                          - log:
+                              message: 'Send to database: ${body}'
+                          - kamelet:
+                              name: postgresql-sink
+                              parameters:
+                                serverName: localhost
+                                serverPort: '5432'
+                                username: postgres
+                                password: postgres
+                                databaseName: demo
+                                query: >-
+                                  UPDATE parcels set status = 'CANCELED' WHERE
+                                  id = :#id
+                aggregationStrategy: aggregator
+                completionSize: 2
+                correlationExpression:
+                  groovy:
+                    expression: body.get('id')
+          parameters:
+            topic: parcels,payments
+            bootstrapServers: localhost:9092
+            autoCommitEnable: true
+            consumerGroup: postman
+        id: aggregator
+    - route:
+        from:
+          uri: kamelet:mqtt-source
+          steps:
+            - log:
+                message: 'Delivery: ${body}'
+          parameters:
+            topic: deliveries
+            brokerUrl: tcp://localhost:1883
+    - beans:
+        - name: aggregator
+          type: org.apache.camel.processor.aggregate.GroupedBodyAggregationStrategy
diff --git a/karavan-demo/postman/start.sh b/karavan-demo/postman/start.sh
new file mode 100755
index 0000000..ccb09e3
--- /dev/null
+++ b/karavan-demo/postman/start.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+docker-compose down
+docker rm -f $(docker ps -a -q)
+docker volume rm $(docker volume ls -q)
+docker-compose up -d
+docker-compose logs -f
\ No newline at end of file
diff --git a/karavan-designer/public/components/aws2-sqs.json b/karavan-designer/public/components/aws2-sqs.json
index 9b18063..d426fa5 100644
--- a/karavan-designer/public/components/aws2-sqs.json
+++ b/karavan-designer/public/components/aws2-sqs.json
@@ -1 +1 @@
-{"component":{"kind":"component","name":"aws2-sqs","title":"AWS Simple Queue Service (SQS)","description":"Send and receive messages to/from AWS SQS service using AWS SDK version 2.x.","deprecated":false,"firstVersion":"3.1.0","label":"cloud,messaging","javaType":"org.apache.camel.component.aws2.sqs.Sqs2Component","supportLevel":"Stable","groupId":"org.apache.camel","artifactId":"camel-aws2-sqs","version":"3.16.0-SNAPSHOT","scheme":"aws2-sqs","extendsScheme":"","syntax":"aws2-sqs:queueNa [...]
\ No newline at end of file
+{"component":{"kind":"component","name":"aws2-sqs","title":"AWS Simple Queue Service (SQS)","description":"Send and receive messages to/from AWS SQS service using AWS SDK version 2.x.","deprecated":false,"firstVersion":"3.1.0","label":"cloud,messaging","javaType":"org.apache.camel.component.aws2.sqs.Sqs2Component","supportLevel":"Stable","groupId":"org.apache.camel","artifactId":"camel-aws2-sqs","version":"3.16.0-SNAPSHOT","scheme":"aws2-sqs","extendsScheme":"","syntax":"aws2-sqs:queueNa [...]
\ No newline at end of file
diff --git a/karavan-designer/public/components/tika.json b/karavan-designer/public/components/tika.json
index c9ee8e2..3e50b61 100644
--- a/karavan-designer/public/components/tika.json
+++ b/karavan-designer/public/components/tika.json
@@ -1 +1 @@
-{"component":{"kind":"component","name":"tika","title":"Tika","description":"Parse documents and extract metadata and text using Apache Tika.","deprecated":false,"firstVersion":"2.19.0","label":"document,transformation","javaType":"org.apache.camel.component.tika.TikaComponent","supportLevel":"Stable","groupId":"org.apache.camel","artifactId":"camel-tika","version":"3.16.0-SNAPSHOT","scheme":"tika","extendsScheme":"","syntax":"tika:operation","async":false,"api":false,"consumerOnly":fals [...]
\ No newline at end of file
+{"component":{"kind":"component","name":"tika","title":"Tika","description":"Parse documents and extract metadata and text using Apache Tika.","deprecated":false,"firstVersion":"2.19.0","label":"document,transformation","javaType":"org.apache.camel.component.tika.TikaComponent","supportLevel":"Stable","groupId":"org.apache.camel","artifactId":"camel-tika","version":"3.16.0-SNAPSHOT","scheme":"tika","extendsScheme":"","syntax":"tika:operation","async":false,"api":false,"consumerOnly":fals [...]
\ No newline at end of file
diff --git a/karavan-designer/src/App.tsx b/karavan-designer/src/App.tsx
index 25a7fa0..bc92ad4 100644
--- a/karavan-designer/src/App.tsx
+++ b/karavan-designer/src/App.tsx
@@ -247,7 +247,7 @@ class App extends React.Component<Props, State> {
                                  onSave={(filename, yaml) => this.save(filename, yaml)}
                                  borderColor="#fb8824"
                                  borderColorSelected="#303284"
-                                 backward={false}
+                                 backward={true}
                                  dark={document.body.className.includes('vscode-dark')}
                 />
             </Page>
diff --git a/karavan-designer/src/designer/route/property/DslPropertyField.tsx b/karavan-designer/src/designer/route/property/DslPropertyField.tsx
index 0282273..6d54f77 100644
--- a/karavan-designer/src/designer/route/property/DslPropertyField.tsx
+++ b/karavan-designer/src/designer/route/property/DslPropertyField.tsx
@@ -464,6 +464,7 @@ export class DslPropertyField extends React.Component<Props, State> {
         const isKamelet = CamelUi.isKameletComponent(this.props.element);
         const property: PropertyMeta = this.props.property;
         const value = this.props.value;
+
         return (
             <FormGroup
                 label={this.props.hideLabel ? undefined : this.getLabel(property, value)}
diff --git a/karavan-designer/src/designer/utils/CamelUi.ts b/karavan-designer/src/designer/utils/CamelUi.ts
index fa1996a..8ee329b 100644
--- a/karavan-designer/src/designer/utils/CamelUi.ts
+++ b/karavan-designer/src/designer/utils/CamelUi.ts
@@ -50,7 +50,6 @@ const StepElements: string[] = [
     "SetHeaderDefinition",
     "SortDefinition",
     "SplitDefinition",
-    "SwitchDefinition",
     "ThreadsDefinition",
     "ThrottleDefinition",
     "ToDynamicDefinition",
@@ -128,7 +127,7 @@ export class CamelUi {
                     .forEach(child => result.push(CamelUi.getDslMetaModel(child.className)));
             }
         }
-        return result.sort((a, b) => (a.title.toLowerCase() > b.title.toLowerCase() ? 1 : -1));
+        return result.length > 1 ? result.sort((a, b) => (a.title?.toLowerCase() > b.title?.toLowerCase() ? 1 : -1)) : [];
     }
 
     static getDslMetaModel = (className: string): DslMetaModel => {
diff --git a/karavan-vscode/components/aws2-sqs.json b/karavan-vscode/components/aws2-sqs.json
index 9b18063..d426fa5 100644
--- a/karavan-vscode/components/aws2-sqs.json
+++ b/karavan-vscode/components/aws2-sqs.json
@@ -1 +1 @@
-{"component":{"kind":"component","name":"aws2-sqs","title":"AWS Simple Queue Service (SQS)","description":"Send and receive messages to/from AWS SQS service using AWS SDK version 2.x.","deprecated":false,"firstVersion":"3.1.0","label":"cloud,messaging","javaType":"org.apache.camel.component.aws2.sqs.Sqs2Component","supportLevel":"Stable","groupId":"org.apache.camel","artifactId":"camel-aws2-sqs","version":"3.16.0-SNAPSHOT","scheme":"aws2-sqs","extendsScheme":"","syntax":"aws2-sqs:queueNa [...]
\ No newline at end of file
+{"component":{"kind":"component","name":"aws2-sqs","title":"AWS Simple Queue Service (SQS)","description":"Send and receive messages to/from AWS SQS service using AWS SDK version 2.x.","deprecated":false,"firstVersion":"3.1.0","label":"cloud,messaging","javaType":"org.apache.camel.component.aws2.sqs.Sqs2Component","supportLevel":"Stable","groupId":"org.apache.camel","artifactId":"camel-aws2-sqs","version":"3.16.0-SNAPSHOT","scheme":"aws2-sqs","extendsScheme":"","syntax":"aws2-sqs:queueNa [...]
\ No newline at end of file
diff --git a/karavan-vscode/components/tika.json b/karavan-vscode/components/tika.json
index c9ee8e2..3e50b61 100644
--- a/karavan-vscode/components/tika.json
+++ b/karavan-vscode/components/tika.json
@@ -1 +1 @@
-{"component":{"kind":"component","name":"tika","title":"Tika","description":"Parse documents and extract metadata and text using Apache Tika.","deprecated":false,"firstVersion":"2.19.0","label":"document,transformation","javaType":"org.apache.camel.component.tika.TikaComponent","supportLevel":"Stable","groupId":"org.apache.camel","artifactId":"camel-tika","version":"3.16.0-SNAPSHOT","scheme":"tika","extendsScheme":"","syntax":"tika:operation","async":false,"api":false,"consumerOnly":fals [...]
\ No newline at end of file
+{"component":{"kind":"component","name":"tika","title":"Tika","description":"Parse documents and extract metadata and text using Apache Tika.","deprecated":false,"firstVersion":"2.19.0","label":"document,transformation","javaType":"org.apache.camel.component.tika.TikaComponent","supportLevel":"Stable","groupId":"org.apache.camel","artifactId":"camel-tika","version":"3.16.0-SNAPSHOT","scheme":"tika","extendsScheme":"","syntax":"tika:operation","async":false,"api":false,"consumerOnly":fals [...]
\ No newline at end of file
diff --git a/karavan-vscode/src/extension.ts b/karavan-vscode/src/extension.ts
index 5109a0b..3a2453e 100644
--- a/karavan-vscode/src/extension.ts
+++ b/karavan-vscode/src/extension.ts
@@ -119,19 +119,6 @@ function openKaravanWebView(context: vscode.ExtensionContext, webviewContent: st
         "icons/icon.svg"
     );
 
-    // Send backward compatibility
-    const backward = vscode.workspace.getConfiguration().get("camel.backward");
-    if (backward) panel.webview.postMessage({ command: 'backward'});
-
-    // Read and send Kamelets
-    panel.webview.postMessage({ command: 'kamelets', kamelets: readKamelets(context) });
-
-    // Read and send Components
-    panel.webview.postMessage({ command: 'components', components: readComponents(context) });
-
-    // Send integration
-    panel.webview.postMessage({ command: 'open', filename: filename, relativePath: relativePath, yaml: yaml });
-
     // Handle messages from the webview
     panel.webview.onDidReceiveMessage(
         message => {
@@ -145,7 +132,10 @@ function openKaravanWebView(context: vscode.ExtensionContext, webviewContent: st
                             if (err) vscode.window.showErrorMessage("Error: " + err?.message);
                         });
                     }
-                    return;
+                    break;
+                case 'getData':
+                    sendData(context, panel, filename, relativePath, yaml);
+                    break;
             }
         },
         undefined,
@@ -155,6 +145,24 @@ function openKaravanWebView(context: vscode.ExtensionContext, webviewContent: st
     vscode.commands.executeCommand("setContext", KARAVAN_LOADED, true);
 }
 
+function sendData(context: vscode.ExtensionContext, panel: vscode.WebviewPanel, filename: string, relativePath: string, yaml?: string){
+
+    // Send backward compatibility
+    const backward = vscode.workspace.getConfiguration().get("camel.backward");
+    if (backward) panel.webview.postMessage({ command: 'backward' });
+
+    // Read and send Kamelets
+    console.log("Kamelets sent");
+    panel.webview.postMessage({ command: 'kamelets', kamelets: readKamelets(context) });
+
+    // Read and send Components
+    console.log("Components sent");
+    panel.webview.postMessage({ command: 'components', components: readComponents(context) });
+
+    // Send integration
+    panel.webview.postMessage({ command: 'open', filename: filename, relativePath: relativePath, yaml: yaml });
+}
+
 function createIntegration(context: vscode.ExtensionContext, webviewContent: string, crd: boolean) {
     vscode.window
         .showInputBox({
@@ -180,9 +188,9 @@ function createIntegration(context: vscode.ExtensionContext, webviewContent: str
         });
 }
 
-function getRalativePath(fullPath:string): string {
+function getRalativePath(fullPath: string): string {
     const root = vscode.workspace.workspaceFolders ? vscode.workspace.workspaceFolders[0].uri.path : "";
-    const relativePath =  path.resolve(fullPath).replace(root + path.sep, '');
+    const relativePath = path.resolve(fullPath).replace(root + path.sep, '');
     return relativePath;
 }
 
@@ -190,11 +198,11 @@ function readKamelets(context: vscode.ExtensionContext): string[] {
     const dir = path.join(context.extensionPath, 'kamelets');
     const yamls: string[] = fs.readdirSync(dir).filter(file => file.endsWith("yaml")).map(file => fs.readFileSync(dir + "/" + file, 'utf-8'));
     try {
-        const kameletsPath:string = vscode.workspace.getConfiguration().get("Karavan.kameletsPath") || '';
+        const kameletsPath: string = vscode.workspace.getConfiguration().get("Karavan.kameletsPath") || '';
         const kameletsDir = path.isAbsolute(kameletsPath) ? kameletsPath : path.resolve(kameletsPath);
         const customKamelets: string[] = fs.readdirSync(kameletsDir).filter(file => file.endsWith("yaml")).map(file => fs.readFileSync(kameletsDir + "/" + file, 'utf-8'));
         if (customKamelets && customKamelets.length > 0) yamls.push(...customKamelets);
-    } catch(e) {
+    } catch (e) {
 
     }
     return yamls;
@@ -220,10 +228,10 @@ function runCamelJbang(filename: string) {
     const maxMessages = vscode.workspace.getConfiguration().get("camel.maxMessages");
     const loggingLevel = vscode.workspace.getConfiguration().get("camel.loggingLevel");
     const reload = vscode.workspace.getConfiguration().get("camel.reload");
-    const command = "jbang -Dcamel.jbang.version=" + version + " camel@apache/camel run " + filename 
-            + " --max-messages=" + maxMessages 
-            + " --logging-level=" + loggingLevel
-            + (reload ? " --reload" : "");
+    const command = "jbang -Dcamel.jbang.version=" + version + " camel@apache/camel run " + filename
+        + " --max-messages=" + maxMessages
+        + " --logging-level=" + loggingLevel
+        + (reload ? " --reload" : "");
     const existTerminal = TERMINALS.get(filename);
     if (existTerminal) existTerminal.dispose();
     const terminal = vscode.window.createTerminal('Camel: ' + filename);
@@ -232,7 +240,7 @@ function runCamelJbang(filename: string) {
     terminal.sendText(command);
 }
 
-function nameFromTitle (title: string): string {
+function nameFromTitle(title: string): string {
     return title.replace(/[^a-z0-9+]+/gi, "-").toLowerCase();
 }
 
diff --git a/karavan-vscode/webview/App.tsx b/karavan-vscode/webview/App.tsx
index bb3681a..e93deb0 100644
--- a/karavan-vscode/webview/App.tsx
+++ b/karavan-vscode/webview/App.tsx
@@ -18,9 +18,9 @@ import * as React from "react";
 import {
   Page,
 } from "@patternfly/react-core";
-import {KaravanDesigner} from "./designer/KaravanDesigner";
+import { KaravanDesigner } from "./designer/KaravanDesigner";
 import vscode from "./vscode";
-import {KameletApi} from "karavan-core/lib/api/KameletApi";
+import { KameletApi } from "karavan-core/lib/api/KameletApi";
 import { ComponentApi } from "karavan-core/lib/api/ComponentApi";
 
 interface Props {
@@ -47,28 +47,42 @@ class App extends React.Component<Props, State> {
 
 
   componentDidMount() {
-    window.addEventListener('message', event => {
-      const message = event.data; // The JSON data our extension sent
-      switch (message.command) {
-        case 'backward':
-          this.setState({backward: true});
-          break;
-        case 'kamelets':
-          KameletApi.saveKamelets(message.kamelets);
-          break;
-        case 'components':
-          ComponentApi.saveComponents(message.components);
-          break;  
-        case 'open':
-          console.log(event);
-          if (this.state.filename === '' && this.state.key === ''){
-            this.setState({filename: message.filename, yaml: message.yaml, relativePath: message.relativePath, key: Math.random().toString()});
-          }
-          break;
-      }
-    });
+    console.log("componentDidMount");
+    window.addEventListener('message', this.onMessage, false);
+    vscode.postMessage({command: 'getData'})
   }
 
+  componentWillUnmount() {
+    window.removeEventListener('message', this.onMessage, false);
+  }
+
+  onMessage = (event) => {
+    const message = event.data; 
+    console.log("Message received", message);
+    switch (message.command) {
+      case 'backward':
+        console.log("backward", message);
+        this.setState({ backward: true });
+        break;
+      case 'kamelets':
+        console.log("Kamelets saving");
+        KameletApi.saveKamelets(message.kamelets);
+        console.log("Kamelets saved");
+        break;
+      case 'components':
+        console.log("Components saving");
+        ComponentApi.saveComponents(message.components);
+        console.log("Components saved");
+        break;
+      case 'open':
+        console.log(event);
+        if (this.state.filename === '' && this.state.key === '') {
+          this.setState({ filename: message.filename, yaml: message.yaml, relativePath: message.relativePath, key: Math.random().toString() });
+        }
+        break;
+    }
+  };
+
   save(filename: string, yaml: string) {
     vscode.postMessage({
       command: 'save',
@@ -81,16 +95,16 @@ class App extends React.Component<Props, State> {
   public render() {
     return (
       <Page className="karavan">
-         <KaravanDesigner 
-          key={this.state.key} 
+        <KaravanDesigner
+          key={this.state.key}
           backward={this.state.backward}
-          filename={this.state.filename} 
-          yaml={this.state.yaml} 
+          filename={this.state.filename}
+          yaml={this.state.yaml}
           onSave={(filename, yaml) => this.save(filename, yaml)}
           borderColor="rgb(239, 166, 79)"
           borderColorSelected="rgb(171, 172, 224)"
           dark={this.props.dark}
-         />
+        />
       </Page>
     );
   }