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

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


The following commit(s) were added to refs/heads/main by this push:
     new 295c7871cf3 fix: solve issue where having more than one Smooks 
endpoint on the same route implicitly referencing via header the same execution 
context could cause Smooks to misbehave (#16141)
295c7871cf3 is described below

commit 295c7871cf351340021795d6d38258e0c3e92ca9
Author: cjmamo <823038+cjm...@users.noreply.github.com>
AuthorDate: Sat Nov 2 08:11:39 2024 +0100

    fix: solve issue where having more than one Smooks endpoint on the same 
route implicitly referencing via header the same execution context could cause 
Smooks to misbehave (#16141)
    
    Refs: https://github.com/apache/camel/pull/16129
---
 .../apache/camel/catalog/components/smooks.json    |  3 +-
 .../component/smooks/SmooksEndpointConfigurer.java |  6 +++
 .../component/smooks/SmooksEndpointUriFactory.java |  3 +-
 .../org/apache/camel/component/smooks/smooks.json  |  3 +-
 .../camel/component/smooks/SmooksEndpoint.java     | 17 ++++++-
 .../camel/component/smooks/SmooksProcessor.java    | 17 ++++++-
 .../component/smooks/SmooksProcessorTest.java      | 52 +++++++++++++++++++++-
 .../endpoint/dsl/SmooksEndpointBuilderFactory.java | 33 ++++++++++++++
 8 files changed, 125 insertions(+), 9 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smooks.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smooks.json
index 4525d223b10..7416ef4bfb4 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smooks.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/smooks.json
@@ -34,6 +34,7 @@
   "properties": {
     "smooksConfig": { "index": 0, "kind": "path", "displayName": "Smooks 
Config", "group": "producer", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "supportFileReference": true, 
"description": "Path to the Smooks configuration file" },
     "reportPath": { "index": 1, "kind": "parameter", "displayName": "Report 
Path", "group": "producer", "label": "", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "description": "File path to place the generated HTML 
execution report. The report is a useful tool in the developers arsenal for 
diagnosing issues or comprehending a transformation. Do not set in production 
since this is a major performance drain" },
-    "lazyStartProducer": { "index": 2, "kind": "parameter", "displayName": 
"Lazy Start Producer", "group": "producer (advanced)", "label": 
"producer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Whether the producer should be started 
lazy (on the first message). By starting lazy you can use this to allow 
CamelContext and routes to startup in situations where a produc [...]
+    "lazyStartProducer": { "index": 2, "kind": "parameter", "displayName": 
"Lazy Start Producer", "group": "producer (advanced)", "label": 
"producer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Whether the producer should be started 
lazy (on the first message). By starting lazy you can use this to allow 
CamelContext and routes to startup in situations where a produc [...]
+    "allowExecutionContextFromHeader": { "index": 3, "kind": "parameter", 
"displayName": "Allow Execution Context From Header", "group": "advanced", 
"label": "advanced", "required": false, "type": "boolean", "javaType": 
"java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "false", "description": "Allow execution context to be set from 
the CamelSmooksExecutionContext header" }
   }
 }
diff --git 
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointConfigurer.java
 
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointConfigurer.java
index 74e8088e31d..5358bdf4c61 100644
--- 
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointConfigurer.java
+++ 
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointConfigurer.java
@@ -23,6 +23,8 @@ public class SmooksEndpointConfigurer extends 
PropertyConfigurerSupport implemen
     public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
         SmooksEndpoint target = (SmooksEndpoint) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowexecutioncontextfromheader":
+        case "allowExecutionContextFromHeader": 
target.setAllowExecutionContextFromHeader(property(camelContext, 
java.lang.Boolean.class, value)); return true;
         case "lazystartproducer":
         case "lazyStartProducer": 
target.setLazyStartProducer(property(camelContext, boolean.class, value)); 
return true;
         case "reportpath":
@@ -34,6 +36,8 @@ public class SmooksEndpointConfigurer extends 
PropertyConfigurerSupport implemen
     @Override
     public Class<?> getOptionType(String name, boolean ignoreCase) {
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowexecutioncontextfromheader":
+        case "allowExecutionContextFromHeader": return java.lang.Boolean.class;
         case "lazystartproducer":
         case "lazyStartProducer": return boolean.class;
         case "reportpath":
@@ -46,6 +50,8 @@ public class SmooksEndpointConfigurer extends 
PropertyConfigurerSupport implemen
     public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
         SmooksEndpoint target = (SmooksEndpoint) obj;
         switch (ignoreCase ? name.toLowerCase() : name) {
+        case "allowexecutioncontextfromheader":
+        case "allowExecutionContextFromHeader": return 
target.getAllowExecutionContextFromHeader();
         case "lazystartproducer":
         case "lazyStartProducer": return target.isLazyStartProducer();
         case "reportpath":
diff --git 
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointUriFactory.java
 
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointUriFactory.java
index f1d0e702ae0..b1412b5e968 100644
--- 
a/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointUriFactory.java
+++ 
b/components/camel-smooks/src/generated/java/org/apache/camel/component/smooks/SmooksEndpointUriFactory.java
@@ -23,7 +23,8 @@ public class SmooksEndpointUriFactory extends 
org.apache.camel.support.component
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Set<String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(3);
+        Set<String> props = new HashSet<>(4);
+        props.add("allowExecutionContextFromHeader");
         props.add("lazyStartProducer");
         props.add("reportPath");
         props.add("smooksConfig");
diff --git 
a/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/component/smooks/smooks.json
 
b/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/component/smooks/smooks.json
index 4525d223b10..7416ef4bfb4 100644
--- 
a/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/component/smooks/smooks.json
+++ 
b/components/camel-smooks/src/generated/resources/META-INF/org/apache/camel/component/smooks/smooks.json
@@ -34,6 +34,7 @@
   "properties": {
     "smooksConfig": { "index": 0, "kind": "path", "displayName": "Smooks 
Config", "group": "producer", "label": "", "required": true, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", 
"autowired": false, "secret": false, "supportFileReference": true, 
"description": "Path to the Smooks configuration file" },
     "reportPath": { "index": 1, "kind": "parameter", "displayName": "Report 
Path", "group": "producer", "label": "", "required": false, "type": "string", 
"javaType": "java.lang.String", "deprecated": false, "autowired": false, 
"secret": false, "description": "File path to place the generated HTML 
execution report. The report is a useful tool in the developers arsenal for 
diagnosing issues or comprehending a transformation. Do not set in production 
since this is a major performance drain" },
-    "lazyStartProducer": { "index": 2, "kind": "parameter", "displayName": 
"Lazy Start Producer", "group": "producer (advanced)", "label": 
"producer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Whether the producer should be started 
lazy (on the first message). By starting lazy you can use this to allow 
CamelContext and routes to startup in situations where a produc [...]
+    "lazyStartProducer": { "index": 2, "kind": "parameter", "displayName": 
"Lazy Start Producer", "group": "producer (advanced)", "label": 
"producer,advanced", "required": false, "type": "boolean", "javaType": 
"boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": false, "description": "Whether the producer should be started 
lazy (on the first message). By starting lazy you can use this to allow 
CamelContext and routes to startup in situations where a produc [...]
+    "allowExecutionContextFromHeader": { "index": 3, "kind": "parameter", 
"displayName": "Allow Execution Context From Header", "group": "advanced", 
"label": "advanced", "required": false, "type": "boolean", "javaType": 
"java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, 
"defaultValue": "false", "description": "Allow execution context to be set from 
the CamelSmooksExecutionContext header" }
   }
 }
diff --git 
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksEndpoint.java
 
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksEndpoint.java
index 1091f79d9cb..22ee794fba8 100644
--- 
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksEndpoint.java
+++ 
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksEndpoint.java
@@ -41,6 +41,11 @@ public class SmooksEndpoint extends DefaultEndpoint {
     private String smooksConfig;
     @UriParam(description = "File path to place the generated HTML execution 
report. The report is a useful tool in the developer’s arsenal for diagnosing 
issues or comprehending a transformation. Do not set in production since this 
is a major performance drain")
     private String reportPath;
+    @UriParam(description = "Allow execution context to be set from the " + 
SmooksConstants.SMOOKS_EXECUTION_CONTEXT
+                            + " header",
+              label = "advanced",
+              defaultValue = "false")
+    private Boolean allowExecutionContextFromHeader = false;
 
     private final SmooksProcessor smooksProcessor;
 
@@ -50,12 +55,12 @@ public class SmooksEndpoint extends DefaultEndpoint {
     }
 
     @Override
-    public Producer createProducer() throws Exception {
+    public Producer createProducer() {
         return new SmooksProducer(this, smooksProcessor);
     }
 
     @Override
-    public Consumer createConsumer(Processor processor) throws Exception {
+    public Consumer createConsumer(Processor processor) {
         throw new IllegalArgumentException("Consumer is not supported");
     }
 
@@ -86,4 +91,12 @@ public class SmooksEndpoint extends DefaultEndpoint {
     public void setReportPath(String reportPath) {
         this.reportPath = reportPath;
     }
+
+    public Boolean getAllowExecutionContextFromHeader() {
+        return allowExecutionContextFromHeader;
+    }
+
+    public void setAllowExecutionContextFromHeader(Boolean 
allowExecutionContextFromHeader) {
+        this.allowExecutionContextFromHeader = allowExecutionContextFromHeader;
+    }
 }
diff --git 
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksProcessor.java
 
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksProcessor.java
index 5f1ab2492c6..605ac7f78aa 100644
--- 
a/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksProcessor.java
+++ 
b/components/camel-smooks/src/main/java/org/apache/camel/component/smooks/SmooksProcessor.java
@@ -80,6 +80,7 @@ public class SmooksProcessor extends ServiceSupport 
implements Processor, CamelC
     private Smooks smooks;
     private String configUri;
     private String reportPath;
+    private Boolean allowExecutionContextFromHeader = false;
 
     private final Set<VisitorAppender> visitorAppender = new HashSet<>();
     private final Map<String, Visitor> selectorVisitorMap = new HashMap<>();
@@ -107,9 +108,20 @@ public class SmooksProcessor extends ServiceSupport 
implements Processor, CamelC
         return camelContext;
     }
 
+    public Boolean getAllowExecutionContextFromHeader() {
+        return allowExecutionContextFromHeader;
+    }
+
+    public void setAllowExecutionContextFromHeader(Boolean 
allowExecutionContextFromHeader) {
+        this.allowExecutionContextFromHeader = allowExecutionContextFromHeader;
+    }
+
     public void process(final Exchange exchange) {
-        ExecutionContext executionContext
-                = 
exchange.getIn().getHeader(SmooksConstants.SMOOKS_EXECUTION_CONTEXT, 
ExecutionContext.class);
+        ExecutionContext executionContext = null;
+        if (allowExecutionContextFromHeader) {
+            executionContext
+                    = 
exchange.getMessage().getHeader(SmooksConstants.SMOOKS_EXECUTION_CONTEXT, 
ExecutionContext.class);
+        }
         if (executionContext == null) {
             executionContext = smooks.createExecutionContext();
             Charset charset = ExchangeHelper.getCharset(exchange, false);
@@ -118,6 +130,7 @@ public class SmooksProcessor extends ServiceSupport 
implements Processor, CamelC
                 executionContext.setContentEncoding(charset.name());
             }
         }
+
         try {
             executionContext.put(EXCHANGE_TYPED_KEY, exchange);
             
exchange.getIn().setHeader(SmooksConstants.SMOOKS_EXECUTION_CONTEXT, 
executionContext);
diff --git 
a/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksProcessorTest.java
 
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksProcessorTest.java
index 9ac2752fc71..79cd2633780 100644
--- 
a/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksProcessorTest.java
+++ 
b/components/camel-smooks/src/test/java/org/apache/camel/component/smooks/SmooksProcessorTest.java
@@ -60,6 +60,7 @@ import static org.hamcrest.CoreMatchers.notNullValue;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
@@ -95,7 +96,8 @@ public class SmooksProcessorTest extends CamelTestSupport {
     }
 
     @Test
-    public void 
testProcessUsesExistingExecutionContextWhenExecutionContextIsInHeader() throws 
Exception {
+    public void 
testProcessUsesExistingExecutionContextWhenExecutionContextIsInHeaderAndAllowExecutionContextFromHeaderIsTrue()
+            throws Exception {
         Smooks smooks = new Smooks();
         SmooksProcessor processor = new 
SmooksProcessor("edi-to-xml-smooks-config.xml", context);
         processor.setSmooksFactory(new SmooksFactory() {
@@ -114,6 +116,7 @@ public class SmooksProcessorTest extends CamelTestSupport {
                 return null;
             }
         });
+        processor.setAllowExecutionContextFromHeader(true);
 
         final ExecutionContext[] executionContext = new ExecutionContext[1];
         context.addRoutes(new RouteBuilder() {
@@ -124,7 +127,8 @@ public class SmooksProcessorTest extends CamelTestSupport {
                             executionContext[0] = 
smooks.createExecutionContext();
                             return executionContext[0];
                         })
-                        .process(processor).to("mock:result");
+                        .process(processor)
+                        .to("mock:result");
             }
 
         });
@@ -135,6 +139,50 @@ public class SmooksProcessorTest extends CamelTestSupport {
         assertEquals(executionContext[0], 
exchange.getMessage().getHeader(SmooksConstants.SMOOKS_EXECUTION_CONTEXT));
     }
 
+    @Test
+    public void 
testProcessDoesNotUseExistingExecutionContextWhenExecutionContextIsInHeaderAndAllowExecutionContextFromHeaderIsFalse()
+            throws Exception {
+        Smooks smooks = new Smooks();
+        SmooksProcessor processor = new 
SmooksProcessor("edi-to-xml-smooks-config.xml", context);
+        processor.setSmooksFactory(new SmooksFactory() {
+            @Override
+            public Smooks createInstance() {
+                return smooks;
+            }
+
+            @Override
+            public Smooks createInstance(InputStream config) {
+                return null;
+            }
+
+            @Override
+            public Smooks createInstance(String config) {
+                return null;
+            }
+        });
+        processor.setAllowExecutionContextFromHeader(false);
+
+        final ExecutionContext[] executionContext = new ExecutionContext[1];
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:input")
+                        .setHeader(SmooksConstants.SMOOKS_EXECUTION_CONTEXT, 
() -> {
+                            executionContext[0] = 
smooks.createExecutionContext();
+                            return executionContext[0];
+                        })
+                        .process(processor)
+                        .to("mock:result");
+            }
+
+        });
+        context.start();
+        template.sendBody("direct://input", getOrderEdi());
+
+        Exchange exchange = result.assertExchangeReceived(0);
+        assertNotEquals(executionContext[0], 
exchange.getMessage().getHeader(SmooksConstants.SMOOKS_EXECUTION_CONTEXT));
+    }
+
     @Test
     public void testProcessGivenAttachment() throws Exception {
         context.addRoutes(createEdiToXmlRouteBuilder());
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SmooksEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SmooksEndpointBuilderFactory.java
index e5be1f84cf4..58b2d7b959b 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SmooksEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/SmooksEndpointBuilderFactory.java
@@ -120,6 +120,39 @@ public interface SmooksEndpointBuilderFactory {
             doSetProperty("lazyStartProducer", lazyStartProducer);
             return this;
         }
+        /**
+         * Allow execution context to be set from the
+         * CamelSmooksExecutionContext header.
+         * 
+         * The option is a: <code>java.lang.Boolean</code> type.
+         * 
+         * Default: false
+         * Group: advanced
+         * 
+         * @param allowExecutionContextFromHeader the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSmooksEndpointBuilder 
allowExecutionContextFromHeader(Boolean allowExecutionContextFromHeader) {
+            doSetProperty("allowExecutionContextFromHeader", 
allowExecutionContextFromHeader);
+            return this;
+        }
+        /**
+         * Allow execution context to be set from the
+         * CamelSmooksExecutionContext header.
+         * 
+         * The option will be converted to a <code>java.lang.Boolean</code>
+         * type.
+         * 
+         * Default: false
+         * Group: advanced
+         * 
+         * @param allowExecutionContextFromHeader the value to set
+         * @return the dsl builder
+         */
+        default AdvancedSmooksEndpointBuilder 
allowExecutionContextFromHeader(String allowExecutionContextFromHeader) {
+            doSetProperty("allowExecutionContextFromHeader", 
allowExecutionContextFromHeader);
+            return this;
+        }
     }
 
     public interface SmooksBuilders {

Reply via email to