Details
-
Bug
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
3.19.0, 3.20.1, 3.20.2, 4.0-M1
-
None
-
Unknown
Description
Hi guys, I'm attaching a test class that will reproduce the issue that I'm experiencing.
As summary: The cache inside the SimpleLanguage class looks like it's going to be affected by the evaluation of the simple expression, producing unexpected results.
When the method resolveTemplate is used the result is not the expected one.
To make it work I have to simulate a new entry in the cache making use of the method resolveTemplateNoCache.
Thanks in advance
public class SimpleLanguageTest extends CamelTestSupport { @EndpointInject("mock:result") private MockEndpoint mockResult; @EndpointInject("mock:fail") private MockEndpoint mockWithFailure; @Test public void whenSimpleLanguageNotUseCachedEntriesItWillNotFail() throws Exception { mockResult.await(20, TimeUnit.SECONDS); mockResult.expectedMessageCount(102); assertMockEndpointsSatisfied(); List<Exchange> exchanges = mockResult.getExchanges(); exchanges.stream() .forEach(exchange -> assertTrue(exchange.getMessage().getHeader("#CustomHeader", String.class).equals("This is a test a with startLabel: `Document` endLabel: `Document` and label: `ALabel`"))); } @Test public void whenSimpleLanguageUseCachedEntriesItWillFail() throws Exception { mockWithFailure.expectedMessageCount(102); assertMockEndpointsSatisfied(); List<Exchange> exchanges = mockWithFailure.getExchanges(); exchanges.stream() .forEach(exchange -> assertTrue(exchange.getMessage().getHeader("#CustomHeader", String.class).equals("This is a test a with startLabel: `Document` endLabel: `Document` and label: `ALabel`"))); } @Override protected RoutesBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { Map body = new HashMap() {{ put("label", "ALabel"); put("startLabel", "Document"); put("endLabel", "Document"); }}; String simpleTemplate = "This is a test a with startLabel: `${body.get('startLabel')}` endLabel: `${body.get('endLabel')}` and label: `${body.get('label')}`"; @Override public void configure() throws Exception { from("timer://test-timer?fixedRate=true&period=10&delay=1") .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { exchange.getMessage().setBody(body); exchange.getMessage().setHeader("#CustomHeader", resolveTemplateNoCache(simpleTemplate, exchange)); } }) .to("mock:result"); from("timer://test-timer1?fixedRate=true&period=10&delay=1") .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { exchange.getMessage().setBody(body); exchange.getMessage().setHeader("#CustomHeader", resolveTemplateNoCache(simpleTemplate, exchange)); } }) .to("mock:result"); from("timer://test-timer2?fixedRate=true&period=10&delay=1") .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { exchange.getMessage().setBody(body); exchange.getMessage().setHeader("#CustomHeader", resolveTemplateNoCache(simpleTemplate, exchange)); } }) .to("mock:result"); from("timer://test-timer3?fixedRate=true&period=10&delay=1") .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { exchange.getMessage().setBody(body); exchange.getMessage().setHeader("#CustomHeader", resolveTemplate(simpleTemplate, exchange)); } }) .to("mock:fail"); from("timer://test-timer4?fixedRate=true&period=10&delay=1") .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { exchange.getMessage().setBody(body); exchange.getMessage().setHeader("#CustomHeader", resolveTemplate(simpleTemplate, exchange)); } }) .to("mock:fail"); from("timer://test-timer5?fixedRate=true&period=10&delay=1") .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { exchange.getMessage().setBody(body); exchange.getMessage().setHeader("#CustomHeader", resolveTemplate(simpleTemplate, exchange)); } }) .to("mock:fail"); } }; } public String resolveTemplate(String template, Exchange exchange) { var simpleExpression = new SimpleExpression(); simpleExpression.setExpression(template); return simpleExpression.evaluate(exchange, String.class); } public String resolveTemplateNoCache(String template, Exchange exchange) { var simpleExpression = new SimpleExpression(); //This will force to create a new entry in the cache in the SimpleLanguage class String nocache = String.join("-", "-nocache", UUID.randomUUID().toString()); simpleExpression.setExpression("%s%s".formatted(template, nocache)); return simpleExpression.evaluate(exchange, String.class).replace(nocache, ""); } }
Attachments
Issue Links
- fixes
-
CAMEL-19346 Builder.simple expression is not thread safe
- Resolved
- links to