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 25780ce52ac CAMEL-18445: camel-caffeine - DynamicAware to optimize for action/key/value using expressions 25780ce52ac is described below commit 25780ce52acea41b65e35b19b137751f03853dbe Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Wed Aug 31 17:42:22 2022 +0200 CAMEL-18445: camel-caffeine - DynamicAware to optimize for action/key/value using expressions --- .../org/apache/camel/send-dynamic/caffeine-cache | 2 + .../apache/camel/send-dynamic/caffeine-loadcache | 2 + .../caffeine/CaffeineLoadSendDynamicAware.java | 24 +++++ .../caffeine/CaffeineSendDynamicAware.java | 24 +++++ .../caffeine/DefaultCaffeineSendDynamicAware.java | 105 +++++++++++++++++++++ .../cache/CaffeineSendDynamicAwareOffTest.java | 60 ++++++++++++ .../cache/CaffeineSendDynamicAwareTest.java | 57 +++++++++++ 7 files changed, 274 insertions(+) diff --git a/components/camel-caffeine/src/generated/resources/META-INF/services/org/apache/camel/send-dynamic/caffeine-cache b/components/camel-caffeine/src/generated/resources/META-INF/services/org/apache/camel/send-dynamic/caffeine-cache new file mode 100644 index 00000000000..8ba9de71d9e --- /dev/null +++ b/components/camel-caffeine/src/generated/resources/META-INF/services/org/apache/camel/send-dynamic/caffeine-cache @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.caffeine.CaffeineSendDynamicAware diff --git a/components/camel-caffeine/src/generated/resources/META-INF/services/org/apache/camel/send-dynamic/caffeine-loadcache b/components/camel-caffeine/src/generated/resources/META-INF/services/org/apache/camel/send-dynamic/caffeine-loadcache new file mode 100644 index 00000000000..b4f5c0d7ef4 --- /dev/null +++ b/components/camel-caffeine/src/generated/resources/META-INF/services/org/apache/camel/send-dynamic/caffeine-loadcache @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.component.caffeine.CaffeineLoadSendDynamicAware diff --git a/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/CaffeineLoadSendDynamicAware.java b/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/CaffeineLoadSendDynamicAware.java new file mode 100644 index 00000000000..ac9d15f3ef1 --- /dev/null +++ b/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/CaffeineLoadSendDynamicAware.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.caffeine; + +import org.apache.camel.spi.annotations.SendDynamic; + +@SendDynamic("caffeine-loadcache") +public class CaffeineLoadSendDynamicAware extends DefaultCaffeineSendDynamicAware { + +} diff --git a/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/CaffeineSendDynamicAware.java b/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/CaffeineSendDynamicAware.java new file mode 100644 index 00000000000..2990add93c6 --- /dev/null +++ b/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/CaffeineSendDynamicAware.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.caffeine; + +import org.apache.camel.spi.annotations.SendDynamic; + +@SendDynamic("caffeine-cache") +public class CaffeineSendDynamicAware extends DefaultCaffeineSendDynamicAware { + +} diff --git a/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/DefaultCaffeineSendDynamicAware.java b/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/DefaultCaffeineSendDynamicAware.java new file mode 100644 index 00000000000..58b78f4ef82 --- /dev/null +++ b/components/camel-caffeine/src/main/java/org/apache/camel/component/caffeine/DefaultCaffeineSendDynamicAware.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.caffeine; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.support.component.SendDynamicAwareSupport; +import org.apache.camel.util.StringHelper; +import org.apache.camel.util.URISupport; + +abstract class DefaultCaffeineSendDynamicAware extends SendDynamicAwareSupport { + + @Override + public boolean isLenientProperties() { + return false; + } + + @Override + public DynamicAwareEntry prepare(Exchange exchange, String uri, String originalUri) throws Exception { + Map<String, Object> properties = endpointProperties(exchange, uri); + return new DynamicAwareEntry(uri, originalUri, properties, null); + } + + @Override + public String resolveStaticUri(Exchange exchange, DynamicAwareEntry entry) throws Exception { + Object action = exchange.getMessage().getHeader(CaffeineConstants.ACTION); + Object key = exchange.getMessage().getHeader(CaffeineConstants.KEY); + Object keys = exchange.getMessage().getHeader(CaffeineConstants.KEYS); + Object value = exchange.getMessage().getHeader(CaffeineConstants.VALUE); + if (action == null && key == null && keys == null && value == null) { + // remove keys + Map<String, Object> copy = new LinkedHashMap<>(entry.getProperties()); + copy.remove("action"); + copy.remove("key"); + copy.remove("keys"); + copy.remove("value"); + // build static uri + String u = entry.getUri(); + // remove query parameters + if (u.indexOf('?') > 0) { + u = StringHelper.before(u, "?"); + } + String query = URISupport.createQueryString(copy); + if (!query.isEmpty()) { + return u + "?" + query; + } else { + return u; + } + } else { + // no optimisation possible + return null; + } + } + + @Override + public Processor createPreProcessor(Exchange exchange, DynamicAwareEntry entry) throws Exception { + // store as headers + return ex -> { + Object action = entry.getProperties().get("action"); + if (action != null) { + ex.getMessage().setHeader(CaffeineConstants.ACTION, action); + } + Object key = entry.getProperties().get("key"); + if (key != null) { + ex.getMessage().setHeader(CaffeineConstants.KEY, key); + } + Object keys = entry.getProperties().get("keys"); + if (keys != null) { + ex.getMessage().setHeader(CaffeineConstants.KEYS, key); + } + Object value = entry.getProperties().get("value"); + if (value != null) { + ex.getMessage().setHeader(CaffeineConstants.VALUE, value); + } + }; + } + + @Override + public Processor createPostProcessor(Exchange exchange, DynamicAwareEntry entry) throws Exception { + // cleanup and remove the headers we used + return ex -> { + ex.getMessage().removeHeader(CaffeineConstants.ACTION); + ex.getMessage().removeHeader(CaffeineConstants.KEY); + ex.getMessage().removeHeader(CaffeineConstants.KEYS); + ex.getMessage().removeHeader(CaffeineConstants.VALUE); + }; + } +} diff --git a/components/camel-caffeine/src/test/java/org/apache/camel/component/caffeine/cache/CaffeineSendDynamicAwareOffTest.java b/components/camel-caffeine/src/test/java/org/apache/camel/component/caffeine/cache/CaffeineSendDynamicAwareOffTest.java new file mode 100644 index 00000000000..3c45eea028f --- /dev/null +++ b/components/camel-caffeine/src/test/java/org/apache/camel/component/caffeine/cache/CaffeineSendDynamicAwareOffTest.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.caffeine.cache; + +import java.util.Map; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class CaffeineSendDynamicAwareOffTest extends CaffeineCacheTestSupport { + + @Test + public void testToD() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedBodiesReceived("VALUE_1"); + + template.sendBodyAndHeaders("direct:start", "Hello World", + Map.of("action1", "PUT", "action2", "GET", "myKey", "foobar")); + + assertMockEndpointsSatisfied(); + + // there are 2 caffeine endpoints + int count = (int) context.getEndpoints().stream() + .filter(e -> e.getEndpointUri().startsWith("caffeine-cache")).count(); + Assertions.assertEquals(2, count); + } + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + public void configure() { + // turn optimization off + from("direct://start") + .setBody(constant("VALUE_1")) + .toD().allowOptimisedComponents(false) + .uri("caffeine-cache://mycache?action=${header.action1}&key=${header.myKey}") + .setBody(constant("VALUE_2")) + .toD().allowOptimisedComponents(false) + .uri("caffeine-cache://mycache?key=${header.myKey}&action=${header.action2}") + .to("mock:result"); + } + }; + } +} diff --git a/components/camel-caffeine/src/test/java/org/apache/camel/component/caffeine/cache/CaffeineSendDynamicAwareTest.java b/components/camel-caffeine/src/test/java/org/apache/camel/component/caffeine/cache/CaffeineSendDynamicAwareTest.java new file mode 100644 index 00000000000..5e8798df4a3 --- /dev/null +++ b/components/camel-caffeine/src/test/java/org/apache/camel/component/caffeine/cache/CaffeineSendDynamicAwareTest.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.caffeine.cache; + +import java.util.Map; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class CaffeineSendDynamicAwareTest extends CaffeineCacheTestSupport { + + @Test + public void testSendDynamic() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:result"); + mock.expectedBodiesReceived("VALUE_1"); + + template.sendBodyAndHeaders("direct:start", "Hello World", + Map.of("action1", "PUT", "action2", "GET", "myKey", "foobar")); + + assertMockEndpointsSatisfied(); + + // there are 1 caffeine endpoints + int count = (int) context.getEndpoints().stream() + .filter(e -> e.getEndpointUri().startsWith("caffeine-cache")).count(); + Assertions.assertEquals(1, count); + } + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + public void configure() { + from("direct://start") + .setBody(constant("VALUE_1")) + .toD("caffeine-cache://mycache?action=${header.action1}&key=${header.myKey}") + .setBody(constant("VALUE_2")) + .toD("caffeine-cache://mycache?key=${header.myKey}&action=${header.action2}") + .to("mock:result"); + } + }; + } +}