This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit 4f1c2ea5e0550b3cb91f9dbff62bbbb8fc6b3e16 Author: James Netherton <jamesnether...@gmail.com> AuthorDate: Tue Feb 28 15:37:11 2023 +0000 Split infinispan testing into separate modules for the quarkus and camel managed clients Fixes #4570 Fixes #4499 --- .../infinispan/deployment/InfinispanProcessor.java | 15 + .../{infinispan => infinispan-common}/pom.xml | 76 ++--- .../common/InfinispanCommonProducers.java | 53 +++ .../common/InfinispanCommonResources.java | 325 ++++++++++++++++++ .../infinispan/common/InfinispanCommonRoutes.java | 198 +++++++++++ .../component/infinispan/common}/model/Person.java | 2 +- .../infinispan/common}/model/PersonSchema.java | 2 +- .../common/InfinispanCommonServerTestResource.java | 70 ++++ .../infinispan/common/InfinispanCommonTest.java} | 235 ++++--------- .../src/test/resources/infinispan.xml | 18 +- .../pom.xml | 92 +---- .../infinispan/InfinispanQuarkusClientRoutes.java | 68 ++++ .../src/main/resources/application.properties | 20 ++ .../infinispan/InfinispanQuarkusClientIT.java} | 2 +- .../infinispan/InfinispanQuarkusClientTest.java} | 23 +- .../infinispan/InfinispanServerTestResource.java | 42 +++ integration-tests/infinispan/pom.xml | 73 +--- .../infinispan/src/main/java/InfinispanRoutes.java | 75 ++++ .../component/infinispan/InfinispanResources.java | 376 --------------------- .../component/infinispan/InfinispanRoutes.java | 305 ----------------- .../component/infinispan => }/InfinispanIT.java | 1 - .../test/java/InfinispanServerTestResource.java | 40 +++ .../infinispan/src/test/java/InfinispanTest.java | 44 +++ .../infinispan/InfinispanServerTestResource.java | 99 ------ integration-tests/pom.xml | 4 +- poms/bom-test/pom.xml | 11 + tooling/scripts/test-categories.yaml | 1 + tooling/scripts/validate-github-workflows.groovy | 1 + 28 files changed, 1102 insertions(+), 1169 deletions(-) diff --git a/extensions/infinispan/deployment/src/main/java/org/apache/camel/quarkus/component/infinispan/deployment/InfinispanProcessor.java b/extensions/infinispan/deployment/src/main/java/org/apache/camel/quarkus/component/infinispan/deployment/InfinispanProcessor.java index f305db1c6d..6e8688a333 100644 --- a/extensions/infinispan/deployment/src/main/java/org/apache/camel/quarkus/component/infinispan/deployment/InfinispanProcessor.java +++ b/extensions/infinispan/deployment/src/main/java/org/apache/camel/quarkus/component/infinispan/deployment/InfinispanProcessor.java @@ -18,6 +18,9 @@ package org.apache.camel.quarkus.component.infinispan.deployment; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; +import org.infinispan.commons.marshall.ProtoStreamMarshaller; class InfinispanProcessor { @@ -27,4 +30,16 @@ class InfinispanProcessor { FeatureBuildItem feature() { return new FeatureBuildItem(FEATURE); } + + @BuildStep + NativeImageResourceBuildItem nativeImageResources() { + // Only required when Camel instantiates and manages its own internal CacheContainer + return new NativeImageResourceBuildItem("org/infinispan/protostream/message-wrapping.proto"); + } + + @BuildStep + ReflectiveClassBuildItem reflectiveClasses() { + // Only required when Camel instantiates and manages its own internal CacheContainer + return new ReflectiveClassBuildItem(false, false, ProtoStreamMarshaller.class); + } } diff --git a/integration-tests/infinispan/pom.xml b/integration-tests/infinispan-common/pom.xml similarity index 73% copy from integration-tests/infinispan/pom.xml copy to integration-tests/infinispan-common/pom.xml index bca76cd9a0..3fd5f0a3af 100644 --- a/integration-tests/infinispan/pom.xml +++ b/integration-tests/infinispan-common/pom.xml @@ -26,9 +26,9 @@ <relativePath>../../poms/build-parent-it/pom.xml</relativePath> </parent> - <artifactId>camel-quarkus-integration-test-infinispan</artifactId> - <name>Camel Quarkus :: Integration Tests :: Infinispan</name> - <description>Integration tests for Camel Infinispan component</description> + <artifactId>camel-quarkus-integration-test-infinispan-common</artifactId> + <name>Camel Quarkus :: Integration Tests :: Infinispan Common</name> + <description>Integration tests for Camel Infinispan</description> <dependencies> <dependency> @@ -85,35 +85,24 @@ </dependency> </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.jboss.jandex</groupId> + <artifactId>jandex-maven-plugin</artifactId> + <executions> + <execution> + <id>make-index</id> + <goals> + <goal>jandex</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> <profiles> - <profile> - <id>native</id> - <activation> - <property> - <name>native</name> - </property> - </activation> - <properties> - <quarkus.package.type>native</quarkus.package.type> - </properties> - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-failsafe-plugin</artifactId> - <executions> - <execution> - <goals> - <goal>integration-test</goal> - <goal>verify</goal> - </goals> - </execution> - </executions> - </plugin> - </plugins> - </build> - </profile> <profile> <id>virtualDependencies</id> <activation> @@ -177,33 +166,6 @@ </dependency> </dependencies> </profile> - <profile> - <id>skip-testcontainers-tests</id> - <activation> - <property> - <name>skip-testcontainers-tests</name> - </property> - </activation> - <properties> - <skipTests>true</skipTests> - </properties> - </profile> - <profile> - <id>jdk17-build</id> - <activation> - <jdk>[17,)</jdk> - </activation> - <build> - <plugins> - <plugin> - <artifactId>maven-surefire-plugin</artifactId> - <configuration> - <argLine>--add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED</argLine> - </configuration> - </plugin> - </plugins> - </build> - </profile> </profiles> </project> diff --git a/integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonProducers.java b/integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonProducers.java new file mode 100644 index 0000000000..45deb3d587 --- /dev/null +++ b/integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonProducers.java @@ -0,0 +1,53 @@ +/* + * 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.quarkus.component.infinispan.common; + +import java.util.function.BiFunction; + +import jakarta.inject.Named; +import org.apache.camel.component.infinispan.remote.InfinispanRemoteCustomListener; +import org.infinispan.client.hotrod.annotation.ClientCacheEntryCreated; +import org.infinispan.client.hotrod.annotation.ClientListener; +import org.infinispan.client.hotrod.event.ClientCacheEntryCreatedEvent; + +public class InfinispanCommonProducers { + @Named("customMappingFunction") + public BiFunction<String, String, String> mappingFunction() { + return (k, v) -> v + "-remapped"; + } + + @Named("customListener") + public InfinispanRemoteCustomListener customListener() { + return new CustomListener(); + } + + @ClientListener + public static final class CustomListener extends InfinispanRemoteCustomListener { + + @ClientCacheEntryCreated + public void entryCreated(ClientCacheEntryCreatedEvent<?> event) { + if (isAccepted(event.getType())) { + getEventProcessor().processEvent( + event.getType().toString(), + getCacheName(), + event.getKey(), + null, + null); + } + } + } +} diff --git a/integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonResources.java b/integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonResources.java new file mode 100644 index 0000000000..047d5c8aaf --- /dev/null +++ b/integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonResources.java @@ -0,0 +1,325 @@ +/* + * 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.quarkus.component.infinispan.common; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.PATCH; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response; +import org.apache.camel.CamelContext; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.component.infinispan.InfinispanConstants; +import org.apache.camel.component.infinispan.InfinispanOperation; +import org.apache.camel.component.infinispan.InfinispanQueryBuilder; +import org.apache.camel.component.infinispan.remote.InfinispanRemoteComponent; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.quarkus.component.infinispan.common.model.Person; +import org.apache.camel.util.CollectionHelper; +import org.infinispan.client.hotrod.ServerStatistics; + +import static org.apache.camel.quarkus.component.infinispan.common.InfinispanCommonRoutes.CORRELATOR_HEADER; + +@Path("/infinispan") +@ApplicationScoped +public class InfinispanCommonResources { + public static final String CACHE_NAME = "camel-infinispan"; + + @Inject + ProducerTemplate template; + + @Inject + CamelContext camelContext; + + @Path("/inspect") + @GET + @Produces(MediaType.APPLICATION_JSON) + public JsonObject inspectCamelInfinispanClientConfiguration() { + InfinispanRemoteComponent component = camelContext.getComponent("infinispan", InfinispanRemoteComponent.class); + + return Json.createObjectBuilder() + .add("hosts", Objects.toString(component.getConfiguration().getHosts(), "none")) + .add("cache-manager", Objects.toString(component.getConfiguration().getCacheContainer(), "none")) + .build(); + } + + @Path("/aggregate") + @GET + public void aggregate() throws InterruptedException { + MockEndpoint mockEndpoint = camelContext.getEndpoint("mock:aggregationResult", MockEndpoint.class); + mockEndpoint.expectedMessageCount(2); + mockEndpoint.expectedBodiesReceived(1 + 3 + 4 + 5, 6 + 7 + 20 + 21); + + try { + Map<String, Object> headers = Map.of(CORRELATOR_HEADER, CORRELATOR_HEADER); + + Stream.of(1, 3, 4, 5, 6, 7, 20, 21) + .forEach(value -> template.sendBodyAndHeaders("direct:aggregation", value, headers)); + + mockEndpoint.assertIsSatisfied(15000); + } finally { + mockEndpoint.reset(); + } + } + + @Path("/clear") + @DELETE + public void clear() { + template.sendBody("direct:clear", null); + } + + @Path("/clearAsync") + @DELETE + public void clearAsync() + throws ExecutionException, InterruptedException, TimeoutException { + CompletableFuture<?> future = template.requestBody("direct:clearAsync", null, CompletableFuture.class); + future.get(5, TimeUnit.SECONDS); + } + + @Path("/compute") + @POST + public void compute() { + template.sendBody("direct:compute", null); + } + + @Path("/computeAsync") + @POST + public void computeAsync() + throws ExecutionException, InterruptedException, TimeoutException { + CompletableFuture<?> future = template.requestBody("direct:computeAsync", null, CompletableFuture.class); + future.get(5, TimeUnit.SECONDS); + } + + @Path("/containsKey") + @GET + @Produces(MediaType.TEXT_PLAIN) + public Boolean containsKey() { + return template.requestBody("direct:containsKey", null, Boolean.class); + } + + @Path("/containsValue") + @GET + @Produces(MediaType.TEXT_PLAIN) + public Boolean containsValue(@QueryParam("value") String value) { + return template.requestBody("direct:containsValue", value, Boolean.class); + } + + @Path("/event/verify") + @GET + public void listener( + @QueryParam("mockEndpointUri") String mockEndpointUri, + String content) throws InterruptedException { + MockEndpoint mockEndpoint = camelContext.getEndpoint(mockEndpointUri, MockEndpoint.class); + mockEndpoint.expectedMessageCount(1); + mockEndpoint.message(0).header(InfinispanConstants.EVENT_TYPE).isEqualTo("CLIENT_CACHE_ENTRY_CREATED"); + mockEndpoint.message(0).header(InfinispanConstants.CACHE_NAME).isNotNull(); + mockEndpoint.message(0).header(InfinispanConstants.KEY).isEqualTo("the-key"); + + try { + template.sendBody("direct:put", content); + mockEndpoint.assertIsSatisfied(5000); + } finally { + mockEndpoint.reset(); + } + } + + @Path("/get") + @GET + @Produces(MediaType.TEXT_PLAIN) + public String get(@QueryParam("key") String key) { + Map<String, Object> headers = Map.of(InfinispanConstants.KEY, Objects.requireNonNullElse(key, "the-key")); + return template.requestBodyAndHeaders("direct:get", null, headers, String.class); + } + + @Path("/getOrDefault") + @GET + @Produces(MediaType.TEXT_PLAIN) + public String getOrDefault() { + return template.requestBody("direct:getOrDefault", null, String.class); + } + + @Path("/put") + @POST + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + public String put(String content) { + return template.requestBody("direct:put", content, String.class); + } + + @Path("/putAsync") + @POST + @Consumes(MediaType.TEXT_PLAIN) + public void putAsync(String content) + throws ExecutionException, InterruptedException, TimeoutException { + CompletableFuture<?> future = template.requestBody("direct:putAsync", content, CompletableFuture.class); + future.get(5, TimeUnit.SECONDS); + } + + @Path("/putAll") + @POST + public void putAll() { + Map<String, String> body = CollectionHelper.mapOf("key-1", "value-1", "key-2", "value-2"); + template.sendBody("direct:putAll", body); + } + + @Path("/putAllAsync") + @POST + public void putAllAsync() + throws ExecutionException, InterruptedException, TimeoutException { + Map<String, String> body = CollectionHelper.mapOf("key-1", "value-1", "key-2", "value-2"); + CompletableFuture<?> future = template.requestBody("direct:putAllAsync", body, CompletableFuture.class); + future.get(5, TimeUnit.SECONDS); + } + + @Path("/putIdempotent") + @GET + public void putIdempotent() throws InterruptedException { + MockEndpoint mockEndpoint = camelContext.getEndpoint("mock:idempotentResult", MockEndpoint.class); + mockEndpoint.expectedMessageCount(1); + + String messageId = UUID.randomUUID().toString(); + try { + IntStream.of(1, 10).forEach(value -> { + Map<String, Object> headers = Map.of("MessageId", messageId); + template.sendBodyAndHeaders("direct:idempotent", "Message " + value, headers); + }); + + mockEndpoint.assertIsSatisfied(5000); + } finally { + mockEndpoint.reset(); + } + } + + @Path("/putIfAbsent") + @POST + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + public String putIfAbsent(@QueryParam("component") String component, String content) { + return template.requestBody("direct:putIfAbsent", content, String.class); + } + + @Path("/putIfAbsentAsync") + @POST + @Consumes(MediaType.TEXT_PLAIN) + public void putIfAbsentAsync(String content) + throws ExecutionException, InterruptedException, TimeoutException { + CompletableFuture<?> future = template.requestBody("direct:putIfAbsentAsync", content, CompletableFuture.class); + future.get(5, TimeUnit.SECONDS); + } + + @Path("/query") + @GET + @Produces(MediaType.TEXT_PLAIN) + @SuppressWarnings("unchecked") + public Response query() { + Map<String, Object> putOperationHeaders = Map.of( + InfinispanConstants.OPERATION, InfinispanOperation.PUT, + InfinispanConstants.KEY, "person", + InfinispanConstants.VALUE, new Person("Test", "Person")); + + template.sendBodyAndHeaders("infinispan:" + CACHE_NAME, null, putOperationHeaders); + + String query = "FROM person.Person WHERE firstName = 'Test'"; + InfinispanQueryBuilder builder = InfinispanQueryBuilder.create(query); + + Map<String, Object> headers = Map.of(InfinispanConstants.QUERY_BUILDER, builder); + + List<String> result = template.requestBodyAndHeaders("direct:query", null, headers, List.class); + if (result.isEmpty()) { + return Response.status(404).build(); + } + return Response.ok().entity(result.get(0)).build(); + } + + @Path("/remove") + @DELETE + public void remove() { + template.requestBody("direct:remove", null, String.class); + } + + @Path("/removeAsync") + @DELETE + public void removeAsync() + throws ExecutionException, InterruptedException, TimeoutException { + CompletableFuture<?> future = template.requestBody("direct:removeAsync", null, CompletableFuture.class); + future.get(5, TimeUnit.SECONDS); + } + + @Path("/replace") + @PATCH + @Consumes(MediaType.TEXT_PLAIN) + public void replace(String content) { + template.sendBody("direct:replace", content); + } + + @Path("/replaceAsync") + @PATCH + @Consumes(MediaType.TEXT_PLAIN) + public void replaceAsync(String content) + throws ExecutionException, InterruptedException, TimeoutException { + CompletableFuture<?> future = template.requestBody("direct:replaceAsync", content, CompletableFuture.class); + future.get(5, TimeUnit.SECONDS); + } + + @Path("/size") + @GET + @Produces(MediaType.TEXT_PLAIN) + public Integer size() { + return template.requestBody("direct:size", null, Integer.class); + } + + @Path("/stats") + @GET + @Produces(MediaType.TEXT_PLAIN) + public Integer stats() { + ServerStatistics statistics = template.requestBody("direct:stats", null, ServerStatistics.class); + return statistics.getIntStatistic(ServerStatistics.APPROXIMATE_ENTRIES); + } + + @POST + @Path("consumer/{routeId}/{enabled}") + public void manageRoute( + @PathParam("routeId") String routeId, + @PathParam("enabled") boolean enabled) throws Exception { + if (enabled) { + camelContext.getRouteController().startRoute(routeId); + } else { + camelContext.getRouteController().stopRoute(routeId); + } + } +} diff --git a/integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonRoutes.java b/integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonRoutes.java new file mode 100644 index 0000000000..ab0e221b9c --- /dev/null +++ b/integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonRoutes.java @@ -0,0 +1,198 @@ +/* + * 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.quarkus.component.infinispan.common; + +import org.apache.camel.AggregationStrategy; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.infinispan.InfinispanConstants; +import org.apache.camel.component.infinispan.InfinispanOperation; +import org.apache.camel.component.infinispan.remote.InfinispanRemoteAggregationRepository; +import org.apache.camel.component.infinispan.remote.InfinispanRemoteConfiguration; +import org.apache.camel.component.infinispan.remote.InfinispanRemoteIdempotentRepository; +import org.infinispan.client.hotrod.configuration.Configuration; + +import static org.apache.camel.quarkus.component.infinispan.common.InfinispanCommonResources.CACHE_NAME; + +public abstract class InfinispanCommonRoutes extends RouteBuilder { + public static final int COMPLETION_SIZE = 4; + public static final String CORRELATOR_HEADER = "CORRELATOR_HEADER"; + + @Override + public void configure() { + from("direct:clear") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.CLEAR) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .toF("infinispan:%s", CACHE_NAME); + + from("direct:clearAsync") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.CLEARASYNC) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .toF("infinispan:%s", CACHE_NAME); + + from("direct:compute") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.COMPUTE) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .toF("infinispan:%s?remappingFunction=#customMappingFunction", CACHE_NAME); + + from("direct:computeAsync") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.COMPUTEASYNC) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .toF("infinispan:%s?remappingFunction=#customMappingFunction", CACHE_NAME); + + from("direct:containsKey") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.CONTAINSKEY) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .toF("infinispan:%s", CACHE_NAME); + + from("direct:containsValue") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.CONTAINSVALUE) + .setHeader(InfinispanConstants.VALUE).body() + .toF("infinispan:%s", CACHE_NAME); + + from("direct:get") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.GET) + .toF("infinispan:%s", CACHE_NAME); + + from("direct:getOrDefault") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.GETORDEFAULT) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .setHeader(InfinispanConstants.DEFAULT_VALUE).constant("default-value") + .toF("infinispan:%s", CACHE_NAME); + + from("direct:put") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUT) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .setHeader(InfinispanConstants.VALUE).body() + .toF("infinispan:%s", CACHE_NAME); + + from("direct:putAsync") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUTASYNC) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .setHeader(InfinispanConstants.VALUE).body() + .toF("infinispan:%s", CACHE_NAME); + + from("direct:putAll") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUTALL) + .setHeader(InfinispanConstants.MAP).body() + .toF("infinispan:%s", CACHE_NAME); + + from("direct:putAllAsync") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUTALLASYNC) + .setHeader(InfinispanConstants.MAP).body() + .toF("infinispan:%s", CACHE_NAME); + + from("direct:putIfAbsent") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUTIFABSENT) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .setHeader(InfinispanConstants.VALUE).body() + .toF("infinispan:%s", CACHE_NAME); + + from("direct:putIfAbsentAsync") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUTIFABSENTASYNC) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .setHeader(InfinispanConstants.VALUE).body() + .toF("infinispan:%s", CACHE_NAME); + + from("direct:query") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.QUERY) + .toF("infinispan:%s", CACHE_NAME); + + from("direct:remove") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.REMOVE) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .toF("infinispan:%s", CACHE_NAME); + + from("direct:removeAsync") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.REMOVEASYNC) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .toF("infinispan:%s", CACHE_NAME); + + from("direct:replace") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.REPLACE) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .setHeader(InfinispanConstants.VALUE).body() + .toF("infinispan:%s", CACHE_NAME); + + from("direct:replaceAsync") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.REPLACEASYNC) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .setHeader(InfinispanConstants.VALUE).body() + .toF("infinispan:%s", CACHE_NAME); + + from("direct:size") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.SIZE) + .setHeader(InfinispanConstants.KEY).constant("the-key") + .toF("infinispan:%s", CACHE_NAME); + + from("direct:stats") + .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.STATS) + .toF("infinispan:%s", CACHE_NAME); + + fromF("infinispan:%s?eventTypes=CLIENT_CACHE_ENTRY_CREATED", CACHE_NAME) + .id("infinispan-events") + .autoStartup(false) + .to("mock:resultCreated"); + + from("direct:aggregation") + .aggregate(header(CORRELATOR_HEADER)) + .aggregationRepository(createAggregationRepository()) + .aggregationStrategy(createAggregationStrategy()) + .completionSize(COMPLETION_SIZE) + .to("mock:aggregationResult"); + + from("direct:idempotent") + .idempotentConsumer(header("MessageID"), createIdempotentRepository()) + .to("mock:idempotentResult"); + + fromF("infinispan:%s?customListener=#customListener", CACHE_NAME) + .id("infinispan-custom-listener") + .autoStartup(false) + .to("mock:resultCustomListener"); + } + + protected abstract Configuration getConfigurationBuilder(); + + protected abstract InfinispanRemoteConfiguration getConfiguration(); + + private InfinispanRemoteIdempotentRepository createIdempotentRepository() { + InfinispanRemoteConfiguration configuration = getConfiguration(); + InfinispanRemoteIdempotentRepository repository = new InfinispanRemoteIdempotentRepository(CACHE_NAME); + repository.setConfiguration(configuration); + return repository; + } + + private InfinispanRemoteAggregationRepository createAggregationRepository() { + InfinispanRemoteAggregationRepository aggregationRepository = new InfinispanRemoteAggregationRepository(CACHE_NAME); + InfinispanRemoteConfiguration configuration = getConfiguration(); + aggregationRepository.setConfiguration(configuration); + return aggregationRepository; + } + + private AggregationStrategy createAggregationStrategy() { + return (oldExchange, newExchange) -> { + if (oldExchange == null) { + return newExchange; + } else { + Integer n = newExchange.getIn().getBody(Integer.class); + Integer o = oldExchange.getIn().getBody(Integer.class); + Integer v = (o == null ? 0 : o) + (n == null ? 0 : n); + oldExchange.getIn().setBody(v, Integer.class); + return oldExchange; + } + }; + } +} diff --git a/integration-tests/infinispan/src/main/java/org/apache/camel/quarkus/component/infinispan/model/Person.java b/integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/model/Person.java similarity index 95% rename from integration-tests/infinispan/src/main/java/org/apache/camel/quarkus/component/infinispan/model/Person.java rename to integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/model/Person.java index 9902d83518..5cb0a10e9b 100644 --- a/integration-tests/infinispan/src/main/java/org/apache/camel/quarkus/component/infinispan/model/Person.java +++ b/integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/model/Person.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.infinispan.model; +package org.apache.camel.quarkus.component.infinispan.common.model; import java.util.Objects; diff --git a/integration-tests/infinispan/src/main/java/org/apache/camel/quarkus/component/infinispan/model/PersonSchema.java b/integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/model/PersonSchema.java similarity index 94% rename from integration-tests/infinispan/src/main/java/org/apache/camel/quarkus/component/infinispan/model/PersonSchema.java rename to integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/model/PersonSchema.java index 4569d616d2..a995930735 100644 --- a/integration-tests/infinispan/src/main/java/org/apache/camel/quarkus/component/infinispan/model/PersonSchema.java +++ b/integration-tests/infinispan-common/src/main/java/org/apache/camel/quarkus/component/infinispan/common/model/PersonSchema.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.infinispan.model; +package org.apache.camel.quarkus.component.infinispan.common.model; import org.infinispan.protostream.GeneratedSchema; import org.infinispan.protostream.annotations.AutoProtoSchemaBuilder; diff --git a/integration-tests/infinispan-common/src/test/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonServerTestResource.java b/integration-tests/infinispan-common/src/test/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonServerTestResource.java new file mode 100644 index 0000000000..383a77411e --- /dev/null +++ b/integration-tests/infinispan-common/src/test/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonServerTestResource.java @@ -0,0 +1,70 @@ +/* + * 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.quarkus.component.infinispan.common; + +import java.util.HashMap; +import java.util.Map; + +import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.BindMode; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.utility.TestcontainersConfiguration; + +public class InfinispanCommonServerTestResource implements QuarkusTestResourceLifecycleManager { + protected static final String USER = "camel"; + protected static final String PASS = "camel"; + private static final Logger LOGGER = LoggerFactory.getLogger(InfinispanCommonServerTestResource.class); + private static final String CONTAINER_IMAGE = System.getProperty("infinispan.container.image", "infinispan/server:14.0"); + private static final int HOTROD_PORT = 11222; + + private GenericContainer<?> container; + + @Override + public Map<String, String> start() { + LOGGER.info(TestcontainersConfiguration.getInstance().toString()); + + container = new GenericContainer<>(CONTAINER_IMAGE) + .withExposedPorts(HOTROD_PORT) + .withEnv("USER", USER) + .withEnv("PASS", PASS) + .withClasspathResourceMapping("infinispan.xml", "/user-config/infinispan.xml", BindMode.READ_ONLY) + .withCommand("-c", "/user-config/infinispan.xml") + .waitingFor(Wait.forListeningPort()); + + container.start(); + + return new HashMap<>(); + } + + @Override + public void stop() { + try { + if (container != null) { + container.stop(); + } + } catch (Exception e) { + // ignored + } + } + + protected String getServerList() { + return String.format("%s:%s", container.getHost(), container.getMappedPort(HOTROD_PORT)); + } +} diff --git a/integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanTest.java b/integration-tests/infinispan-common/src/test/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonTest.java similarity index 52% rename from integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanTest.java rename to integration-tests/infinispan-common/src/test/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonTest.java index 4e27f05239..96169c3738 100644 --- a/integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanTest.java +++ b/integration-tests/infinispan-common/src/test/java/org/apache/camel/quarkus/component/infinispan/common/InfinispanCommonTest.java @@ -14,139 +14,113 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.infinispan; +package org.apache.camel.quarkus.component.infinispan.common; -import java.util.stream.Stream; - -import io.quarkus.test.common.QuarkusTestResource; -import io.quarkus.test.junit.QuarkusTest; import io.restassured.RestAssured; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -@QuarkusTest -@QuarkusTestResource(InfinispanServerTestResource.class) -public class InfinispanTest { +public abstract class InfinispanCommonTest { @AfterEach public void afterEach() { - for (String componentName : componentNames()) { - RestAssured.with() - .queryParam("component", componentName) - .delete("/infinispan/clear") - .then() - .statusCode(204); + RestAssured.with() + .delete("/infinispan/clear") + .then() + .statusCode(204); - RestAssured.with() - .queryParam("component", componentName) - .get("/infinispan/get") - .then() - .statusCode(204); - } + RestAssured.with() + .get("/infinispan/get") + .then() + .statusCode(204); } - @ParameterizedTest - @MethodSource("componentNames") - public void aggregate(String componentName) { + @Test + public void aggregate() { RestAssured.with() - .queryParam("component", componentName) + .queryParam("component") .get("/infinispan/aggregate") .then() .statusCode(204); } @ParameterizedTest - @MethodSource("componentNamesWithSynchronicity") - public void clear(String componentName, boolean isAsync) { + @ValueSource(booleans = { false, true }) + public void clear(boolean isAsync) { RestAssured.with() - .queryParam("component", componentName) - .body("Hello " + componentName) + .body("Hello Camel Infinispan") .post("/infinispan/put") .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/get") .then() .statusCode(200) - .body(is("Hello " + componentName)); + .body(is("Hello Camel Infinispan")); RestAssured.with() - .queryParam("component", componentName) .delete(computePath("/infinispan/clear", isAsync)) .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/get") .then() .statusCode(204); } @ParameterizedTest - @MethodSource("componentNamesWithSynchronicity") - public void compute(String componentName, boolean isAsync) { + @ValueSource(booleans = { false, true }) + public void compute(boolean isAsync) { RestAssured.with() - .queryParam("component", componentName) .body("Initial value") .post("/infinispan/put") .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .post(computePath("/infinispan/compute", isAsync)) .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/get") .then() .statusCode(200) .body(is("Initial value-remapped")); } - @ParameterizedTest - @MethodSource("componentNames") - public void containsKey(String componentName) { + @Test + public void containsKey() { RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/containsKey") .then() .statusCode(200) .body(is("false")); RestAssured.with() - .queryParam("component", componentName) - .body("Hello " + componentName) + .body("Hello Camel Infinispan") .post("/infinispan/put") .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/containsKey") .then() .statusCode(200) .body(is("true")); } - @ParameterizedTest - @MethodSource("componentNames") - public void containsValue(String componentName) { + @Test + public void containsValue() { String value = "test-value"; RestAssured.with() - .queryParam("component", componentName) .queryParam("value", value) .get("/infinispan/containsValue") .then() @@ -154,14 +128,12 @@ public class InfinispanTest { .body(is("false")); RestAssured.with() - .queryParam("component", componentName) .body(value) .post("/infinispan/put") .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .queryParam("value", value) .get("/infinispan/containsValue") .then() @@ -169,135 +141,104 @@ public class InfinispanTest { .body(is("true")); } - @ParameterizedTest - @MethodSource("componentNames") - public void customListener(String componentName) { + @Test + public void customListener() { RestAssured.with() - .queryParam("component", componentName) - .post("/infinispan/consumer/" + componentName + "-custom-listener/true") + .post("/infinispan/consumer/infinispan-custom-listener/true") .then() .statusCode(204); try { - String mockEndpointUri = componentName.equals("infinispan") ? "mock:camelResultCustomListener" - : "mock:quarkusResultCustomListener"; RestAssured.with() - .queryParam("component", componentName) - .queryParam("mockEndpointUri", mockEndpointUri) - .body("Hello " + componentName) + .queryParam("mockEndpointUri", "mock:resultCustomListener") + .body("Hello Camel Infinispan") .get("/infinispan/event/verify") .then() .statusCode(204); } finally { RestAssured.with() - .queryParam("component", componentName) - .post("/infinispan/consumer/" + componentName + "-custom-listener/false") + .post("/infinispan/consumer/infinispan-custom-listener/false") .then() .statusCode(204); } } - @ParameterizedTest - @MethodSource("componentNames") - public void events(String componentName) { + @Test + public void events() { RestAssured.with() - .queryParam("component", componentName) - .post("/infinispan/consumer/" + componentName + "-events/true") + .post("/infinispan/consumer/infinispan-events/true") .then() .statusCode(204); try { - String mockEndpointUri = componentName.equals("infinispan") ? "mock:camelResultCreated" - : "mock:quarkusResultCreated"; RestAssured.with() - .queryParam("component", componentName) - .queryParam("mockEndpointUri", mockEndpointUri) - .body("Hello " + componentName) + .queryParam("mockEndpointUri", "mock:resultCreated") + .body("Hello Camel Infinispan") .get("/infinispan/event/verify") .then() .statusCode(204); } finally { RestAssured.with() - .queryParam("component", componentName) - .post("/infinispan/consumer/" + componentName + "-events/false") + .post("/infinispan/consumer/infinispan-events/false") .then() .statusCode(204); } } - @ParameterizedTest - @MethodSource("componentNames") - public void getOrDefault(String componentName) { + @Test + public void getOrDefault() { RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/getOrDefault") .then() .statusCode(200) .body(is("default-value")); RestAssured.with() - .queryParam("component", componentName) - .body("Hello " + componentName) + .body("Hello Camel Infinispan") .post("/infinispan/put") .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/getOrDefault") .then() .statusCode(200) - .body(is("Hello " + componentName)); + .body(is("Hello Camel Infinispan")); } - @ParameterizedTest - @MethodSource("componentNames") - public void idempotent(String componentName) { + @Test + public void idempotent() { RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/putIdempotent") .then() .statusCode(204); } - @Test - public void inspect() { - RestAssured.when() - .get("/infinispan/inspect") - .then().body( - "hosts", is(notNullValue()), - "cache-manager", is("none")); - } - @ParameterizedTest - @MethodSource("componentNamesWithSynchronicity") - public void put(String componentName, boolean isAsync) { + @ValueSource(booleans = { false, true }) + public void put(boolean isAsync) { RestAssured.with() - .queryParam("component", componentName) - .body("Hello " + componentName) + .body("Hello Camel Infinispan") .post(computePath("/infinispan/put", isAsync)) .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/get") .then() .statusCode(200) - .body(is("Hello " + componentName)); + .body(is("Hello Camel Infinispan")); } @ParameterizedTest - @MethodSource("componentNamesWithSynchronicity") - public void putAll(String componentName, boolean isAsync) { + @ValueSource(booleans = { false, true }) + public void putAll(boolean isAsync) { RestAssured.with() - .queryParam("component", componentName) .post(computePath("/infinispan/putAll", isAsync)) .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .queryParam("key", "key-1") .get("/infinispan/get") .then() @@ -305,7 +246,6 @@ public class InfinispanTest { .body(is("value-1")); RestAssured.with() - .queryParam("component", componentName) .queryParam("key", "key-2") .get("/infinispan/get") .then() @@ -314,146 +254,126 @@ public class InfinispanTest { } @ParameterizedTest - @MethodSource("componentNamesWithSynchronicity") - public void putIfAbsent(String componentName, boolean isAsync) { + @ValueSource(booleans = { false, true }) + public void putIfAbsent(boolean isAsync) { RestAssured.with() - .queryParam("component", componentName) - .body("Hello " + componentName) + .body("Hello Camel Infinispan") .post(computePath("/infinispan/putIfAbsent", isAsync)) .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/get") .then() .statusCode(200) - .body(is("Hello " + componentName)); + .body(is("Hello Camel Infinispan")); RestAssured.with() - .queryParam("component", componentName) .body("An alternative value") .post(computePath("/infinispan/putIfAbsent", isAsync)) .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/get") .then() .statusCode(200) - .body(is("Hello " + componentName)); + .body(is("Hello Camel Infinispan")); } - @ParameterizedTest - @MethodSource("componentNames") - public void query(String componentName) { + @Test + public void query() { RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/query") .then() .statusCode(200); } @ParameterizedTest - @MethodSource("componentNamesWithSynchronicity") - public void remove(String componentName, boolean isAsync) { + @ValueSource(booleans = { false, true }) + public void remove(boolean isAsync) { RestAssured.with() - .queryParam("component", componentName) - .body("Hello " + componentName) + .body("Hello Camel Infinispan") .post(computePath("/infinispan/put", isAsync)) .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .delete(computePath("/infinispan/remove", isAsync)) .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) + .get("/infinispan/get") .then() .statusCode(204); } @ParameterizedTest - @MethodSource("componentNamesWithSynchronicity") - public void replace(String componentName, boolean isAsync) { + @ValueSource(booleans = { false, true }) + public void replace(boolean isAsync) { RestAssured.with() - .queryParam("component", componentName) - .body("Hello " + componentName) + .body("Hello Camel Infinispan") .post(computePath("/infinispan/put", isAsync)) .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/get") .then() .statusCode(200) - .body(is("Hello " + componentName)); + .body(is("Hello Camel Infinispan")); RestAssured.with() - .queryParam("component", componentName) .body("replaced cache value") .patch(computePath("/infinispan/replace", isAsync)) .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/get") .then() .statusCode(200) .body(is("replaced cache value")); } - @ParameterizedTest - @MethodSource("componentNames") - public void size(String componentName) { + @Test + public void size() { RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/size") .then() .statusCode(200) .body(is("0")); RestAssured.with() - .queryParam("component", componentName) - .body("Hello " + componentName) + .body("Hello Camel Infinispan") .post("/infinispan/put") .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/size") .then() .statusCode(200) .body(is("1")); } - @ParameterizedTest - @MethodSource("componentNames") - public void stats(String componentName) { + @Test + public void stats() { RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/stats") .then() .statusCode(200) .body(is("0")); RestAssured.with() - .queryParam("component", componentName) - .body("Hello " + componentName) + .body("Hello Camel Infinispan") .post("/infinispan/put") .then() .statusCode(204); RestAssured.with() - .queryParam("component", componentName) .get("/infinispan/stats") .then() .statusCode(200) @@ -466,19 +386,4 @@ public class InfinispanTest { } return path; } - - public static String[] componentNames() { - return new String[] { - "infinispan", - "infinispan-quarkus" - }; - } - - public static Stream<Arguments> componentNamesWithSynchronicity() { - return Stream.of( - Arguments.of("infinispan", false), - Arguments.of("infinispan-quarkus", false), - Arguments.of("infinispan", true), - Arguments.of("infinispan-quarkus", true)); - } } diff --git a/integration-tests/infinispan/src/test/resources/infinispan.xml b/integration-tests/infinispan-common/src/test/resources/infinispan.xml similarity index 81% rename from integration-tests/infinispan/src/test/resources/infinispan.xml rename to integration-tests/infinispan-common/src/test/resources/infinispan.xml index 60acf4789f..a8cd049188 100644 --- a/integration-tests/infinispan/src/test/resources/infinispan.xml +++ b/integration-tests/infinispan-common/src/test/resources/infinispan.xml @@ -18,10 +18,10 @@ --> <infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="urn:infinispan:config:13.0 https://infinispan.org/schemas/infinispan-config-13.0.xsd - urn:infinispan:server:13.0 https://infinispan.org/schemas/infinispan-server-13.0.xsd" - xmlns="urn:infinispan:config:13.0" - xmlns:server="urn:infinispan:server:13.0"> + xsi:schemaLocation="urn:infinispan:config:14.0 https://infinispan.org/schemas/infinispan-config-14.0.xsd + urn:infinispan:server:14.0 https://infinispan.org/schemas/infinispan-server-14.0.xsd" + xmlns="urn:infinispan:config:14.0" + xmlns:server="urn:infinispan:server:14.0"> <cache-container name="default" statistics="true"> <metrics accurate-size="true"/> @@ -31,17 +31,13 @@ <authorization/> </security> - <!-- Used by tests where camel-infinispan manages its own cache container --> - <local-cache name="camel"> - </local-cache> - - <!-- Used by tests where camel-infinispan uses the Quarkus managed cache container --> - <local-cache name="quarkus"> + <local-cache name="camel-infinispan"> + <encoding media-type="application/x-protostream" /> </local-cache> </cache-container> - <server xmlns="urn:infinispan:server:13.0"> + <server xmlns="urn:infinispan:server:14.0"> <interfaces> <interface name="public"> <inet-address value="${infinispan.bind.address:127.0.0.1}"/> diff --git a/integration-tests/infinispan/pom.xml b/integration-tests/infinispan-quarkus-client/pom.xml similarity index 57% copy from integration-tests/infinispan/pom.xml copy to integration-tests/infinispan-quarkus-client/pom.xml index bca76cd9a0..631329c664 100644 --- a/integration-tests/infinispan/pom.xml +++ b/integration-tests/infinispan-quarkus-client/pom.xml @@ -26,26 +26,14 @@ <relativePath>../../poms/build-parent-it/pom.xml</relativePath> </parent> - <artifactId>camel-quarkus-integration-test-infinispan</artifactId> - <name>Camel Quarkus :: Integration Tests :: Infinispan</name> + <artifactId>camel-quarkus-integration-test-infinispan-quarkus-client</artifactId> + <name>Camel Quarkus :: Integration Tests :: Infinispan Quarkus Client</name> <description>Integration tests for Camel Infinispan component</description> <dependencies> <dependency> <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-infinispan</artifactId> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-log</artifactId> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-direct</artifactId> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-mock</artifactId> + <artifactId>camel-quarkus-integration-test-infinispan-common</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> @@ -67,6 +55,12 @@ <artifactId>rest-assured</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-integration-test-infinispan-common</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>testcontainers</artifactId> @@ -123,58 +117,6 @@ </activation> <dependencies> <!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory --> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-direct-deployment</artifactId> - <version>${project.version}</version> - <type>pom</type> - <scope>test</scope> - <exclusions> - <exclusion> - <groupId>*</groupId> - <artifactId>*</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-infinispan-deployment</artifactId> - <version>${project.version}</version> - <type>pom</type> - <scope>test</scope> - <exclusions> - <exclusion> - <groupId>*</groupId> - <artifactId>*</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-log-deployment</artifactId> - <version>${project.version}</version> - <type>pom</type> - <scope>test</scope> - <exclusions> - <exclusion> - <groupId>*</groupId> - <artifactId>*</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-mock-deployment</artifactId> - <version>${project.version}</version> - <type>pom</type> - <scope>test</scope> - <exclusions> - <exclusion> - <groupId>*</groupId> - <artifactId>*</artifactId> - </exclusion> - </exclusions> - </dependency> </dependencies> </profile> <profile> @@ -188,22 +130,6 @@ <skipTests>true</skipTests> </properties> </profile> - <profile> - <id>jdk17-build</id> - <activation> - <jdk>[17,)</jdk> - </activation> - <build> - <plugins> - <plugin> - <artifactId>maven-surefire-plugin</artifactId> - <configuration> - <argLine>--add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.util.concurrent=ALL-UNNAMED</argLine> - </configuration> - </plugin> - </plugins> - </build> - </profile> </profiles> </project> diff --git a/integration-tests/infinispan-quarkus-client/src/main/java/org/apache/camel/quarkus/component/infinispan/InfinispanQuarkusClientRoutes.java b/integration-tests/infinispan-quarkus-client/src/main/java/org/apache/camel/quarkus/component/infinispan/InfinispanQuarkusClientRoutes.java new file mode 100644 index 0000000000..7f4c291606 --- /dev/null +++ b/integration-tests/infinispan-quarkus-client/src/main/java/org/apache/camel/quarkus/component/infinispan/InfinispanQuarkusClientRoutes.java @@ -0,0 +1,68 @@ +/* + * 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.quarkus.component.infinispan; + +import java.util.Set; + +import org.apache.camel.CamelContext; +import org.apache.camel.component.infinispan.remote.InfinispanRemoteComponent; +import org.apache.camel.component.infinispan.remote.InfinispanRemoteConfiguration; +import org.apache.camel.quarkus.component.infinispan.common.InfinispanCommonRoutes; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; +import org.infinispan.client.hotrod.RemoteCacheManager; +import org.infinispan.client.hotrod.configuration.Configuration; +import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; +import org.infinispan.commons.marshall.ProtoStreamMarshaller; + +public class InfinispanQuarkusClientRoutes extends InfinispanCommonRoutes { + + @Override + protected Configuration getConfigurationBuilder() { + Config config = ConfigProvider.getConfig(); + ConfigurationBuilder clientBuilder = new ConfigurationBuilder(); + String[] hostParts = config.getValue("quarkus.infinispan-client.server-list", String.class).split(":"); + + clientBuilder.addServer() + .host(hostParts[0]) + .port(Integer.parseInt(hostParts[1])); + + clientBuilder + .security() + .authentication() + .username(config.getValue("quarkus.infinispan-client.auth-username", String.class)) + .password(config.getValue("quarkus.infinispan-client.auth-password", String.class)) + .serverName(config.getValue("quarkus.infinispan-client.auth-server-name", String.class)) + .saslMechanism(config.getValue("quarkus.infinispan-client.sasl-mechanism", String.class)) + .realm(config.getValue("quarkus.infinispan-client.auth-realm", String.class)) + .marshaller(new ProtoStreamMarshaller()); + + return clientBuilder.build(); + } + + @Override + protected InfinispanRemoteConfiguration getConfiguration() { + CamelContext camelContext = getCamelContext(); + InfinispanRemoteComponent component = camelContext.getComponent("infinispan", InfinispanRemoteComponent.class); + InfinispanRemoteConfiguration configuration = component.getConfiguration().clone(); + configuration.setCacheContainerConfiguration(getConfigurationBuilder()); + Set<RemoteCacheManager> beans = camelContext.getRegistry().findByType(RemoteCacheManager.class); + RemoteCacheManager cacheManager = beans.iterator().next(); + configuration.setCacheContainer(cacheManager); + return configuration; + } +} diff --git a/integration-tests/infinispan-quarkus-client/src/main/resources/application.properties b/integration-tests/infinispan-quarkus-client/src/main/resources/application.properties new file mode 100644 index 0000000000..d07b4f4fef --- /dev/null +++ b/integration-tests/infinispan-quarkus-client/src/main/resources/application.properties @@ -0,0 +1,20 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +quarkus.infinispan-client.devservices.enabled=false + +# Required by InfinispanRemoteAggregationRepository +quarkus.camel.native.reflection.serialization-enabled=true diff --git a/integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanIT.java b/integration-tests/infinispan-quarkus-client/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanQuarkusClientIT.java similarity index 92% copy from integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanIT.java copy to integration-tests/infinispan-quarkus-client/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanQuarkusClientIT.java index 25a4208dc0..f100fd6ea4 100644 --- a/integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanIT.java +++ b/integration-tests/infinispan-quarkus-client/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanQuarkusClientIT.java @@ -19,5 +19,5 @@ package org.apache.camel.quarkus.component.infinispan; import io.quarkus.test.junit.QuarkusIntegrationTest; @QuarkusIntegrationTest -public class InfinispanIT extends InfinispanTest { +public class InfinispanQuarkusClientIT extends InfinispanQuarkusClientTest { } diff --git a/integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanIT.java b/integration-tests/infinispan-quarkus-client/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanQuarkusClientTest.java similarity index 54% copy from integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanIT.java copy to integration-tests/infinispan-quarkus-client/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanQuarkusClientTest.java index 25a4208dc0..7852e71263 100644 --- a/integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanIT.java +++ b/integration-tests/infinispan-quarkus-client/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanQuarkusClientTest.java @@ -16,8 +16,25 @@ */ package org.apache.camel.quarkus.component.infinispan; -import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import org.apache.camel.quarkus.component.infinispan.common.InfinispanCommonTest; +import org.junit.jupiter.api.Test; -@QuarkusIntegrationTest -public class InfinispanIT extends InfinispanTest { +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; + +@QuarkusTest +@QuarkusTestResource(InfinispanServerTestResource.class) +public class InfinispanQuarkusClientTest extends InfinispanCommonTest { + + @Test + public void inspect() { + RestAssured.when() + .get("/infinispan/inspect") + .then().body( + "hosts", is("none"), + "cache-manager", notNullValue()); + } } diff --git a/integration-tests/infinispan-quarkus-client/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanServerTestResource.java b/integration-tests/infinispan-quarkus-client/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanServerTestResource.java new file mode 100644 index 0000000000..f92c42e3da --- /dev/null +++ b/integration-tests/infinispan-quarkus-client/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanServerTestResource.java @@ -0,0 +1,42 @@ +/* + * 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.quarkus.component.infinispan; + +import java.util.Map; + +import org.apache.camel.quarkus.component.infinispan.common.InfinispanCommonServerTestResource; +import org.infinispan.commons.util.OS; + +public class InfinispanServerTestResource extends InfinispanCommonServerTestResource { + + @Override + public Map<String, String> start() { + Map<String, String> config = super.start(); + config.put("quarkus.infinispan-client.server-list", getServerList()); + config.put("quarkus.infinispan-client.auth-username", USER); + config.put("quarkus.infinispan-client.auth-password", PASS); + config.put("quarkus.infinispan-client.auth-realm", "default"); + config.put("quarkus.infinispan-client.sasl-mechanism", "DIGEST-MD5"); + config.put("quarkus.infinispan-client.auth-server-name", "infinispan"); + + if (OS.getCurrentOs().equals(OS.MAC_OS) || OS.getCurrentOs().equals(OS.WINDOWS)) { + config.put("quarkus.infinispan-client.client-intelligence", "BASIC"); + } + + return config; + } +} diff --git a/integration-tests/infinispan/pom.xml b/integration-tests/infinispan/pom.xml index bca76cd9a0..add5e8dd6a 100644 --- a/integration-tests/infinispan/pom.xml +++ b/integration-tests/infinispan/pom.xml @@ -33,20 +33,9 @@ <dependencies> <dependency> <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-infinispan</artifactId> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-log</artifactId> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-direct</artifactId> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-mock</artifactId> + <artifactId>camel-quarkus-integration-test-infinispan-common</artifactId> </dependency> + <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-resteasy</artifactId> @@ -67,6 +56,12 @@ <artifactId>rest-assured</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-integration-test-infinispan-common</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>testcontainers</artifactId> @@ -123,58 +118,6 @@ </activation> <dependencies> <!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory --> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-direct-deployment</artifactId> - <version>${project.version}</version> - <type>pom</type> - <scope>test</scope> - <exclusions> - <exclusion> - <groupId>*</groupId> - <artifactId>*</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-infinispan-deployment</artifactId> - <version>${project.version}</version> - <type>pom</type> - <scope>test</scope> - <exclusions> - <exclusion> - <groupId>*</groupId> - <artifactId>*</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-log-deployment</artifactId> - <version>${project.version}</version> - <type>pom</type> - <scope>test</scope> - <exclusions> - <exclusion> - <groupId>*</groupId> - <artifactId>*</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-mock-deployment</artifactId> - <version>${project.version}</version> - <type>pom</type> - <scope>test</scope> - <exclusions> - <exclusion> - <groupId>*</groupId> - <artifactId>*</artifactId> - </exclusion> - </exclusions> - </dependency> </dependencies> </profile> <profile> diff --git a/integration-tests/infinispan/src/main/java/InfinispanRoutes.java b/integration-tests/infinispan/src/main/java/InfinispanRoutes.java new file mode 100644 index 0000000000..7c9e26c8da --- /dev/null +++ b/integration-tests/infinispan/src/main/java/InfinispanRoutes.java @@ -0,0 +1,75 @@ +/* + * 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. + */ + +import java.util.Map; + +import jakarta.inject.Named; +import jakarta.ws.rs.Produces; +import org.apache.camel.component.infinispan.remote.InfinispanRemoteConfiguration; +import org.apache.camel.quarkus.component.infinispan.common.InfinispanCommonRoutes; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; +import org.infinispan.client.hotrod.configuration.Configuration; +import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; +import org.infinispan.commons.marshall.ProtoStreamMarshaller; +import org.infinispan.commons.util.OS; + +import static org.infinispan.client.hotrod.impl.ConfigurationProperties.CLIENT_INTELLIGENCE; +import static org.infinispan.client.hotrod.impl.ConfigurationProperties.MARSHALLER; + +public class InfinispanRoutes extends InfinispanCommonRoutes { + + @Produces + @Named("additionalConfig") + Map<String, String> additionalInfinispanConfig() { + Map<String, String> config = Map.of(MARSHALLER, ProtoStreamMarshaller.class.getName()); + if (OS.getCurrentOs().equals(OS.MAC_OS) || OS.getCurrentOs().equals(OS.WINDOWS)) { + config.put(CLIENT_INTELLIGENCE, "BASIC"); + } + return config; + } + + @Override + protected Configuration getConfigurationBuilder() { + Config config = ConfigProvider.getConfig(); + ConfigurationBuilder clientBuilder = new ConfigurationBuilder(); + String[] hostParts = config.getValue("camel.component.infinispan.hosts", String.class).split(":"); + + clientBuilder.addServer() + .host(hostParts[0]) + .port(Integer.parseInt(hostParts[1])); + + clientBuilder + .security() + .authentication() + .username(config.getValue("camel.component.infinispan.username", String.class)) + .password(config.getValue("camel.component.infinispan.password", String.class)) + .serverName(config.getValue("camel.component.infinispan.security-server-name", String.class)) + .saslMechanism(config.getValue("camel.component.infinispan.sasl-mechanism", String.class)) + .realm(config.getValue("camel.component.infinispan.security-realm", String.class)) + .marshaller(new ProtoStreamMarshaller()); + + return clientBuilder.build(); + } + + @Override + protected InfinispanRemoteConfiguration getConfiguration() { + InfinispanRemoteConfiguration configuration = new InfinispanRemoteConfiguration(); + configuration.setCacheContainerConfiguration(getConfigurationBuilder()); + return configuration; + } +} diff --git a/integration-tests/infinispan/src/main/java/org/apache/camel/quarkus/component/infinispan/InfinispanResources.java b/integration-tests/infinispan/src/main/java/org/apache/camel/quarkus/component/infinispan/InfinispanResources.java deleted file mode 100644 index 79823b038a..0000000000 --- a/integration-tests/infinispan/src/main/java/org/apache/camel/quarkus/component/infinispan/InfinispanResources.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * 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.quarkus.component.infinispan; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import jakarta.json.Json; -import jakarta.json.JsonObject; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.DELETE; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.PATCH; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.PathParam; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.QueryParam; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; -import org.apache.camel.CamelContext; -import org.apache.camel.ProducerTemplate; -import org.apache.camel.component.infinispan.InfinispanConstants; -import org.apache.camel.component.infinispan.InfinispanQueryBuilder; -import org.apache.camel.component.infinispan.remote.InfinispanRemoteComponent; -import org.apache.camel.component.mock.MockEndpoint; -import org.apache.camel.quarkus.component.infinispan.model.Person; -import org.apache.camel.util.CollectionHelper; -import org.infinispan.client.hotrod.RemoteCacheManager; -import org.infinispan.client.hotrod.ServerStatistics; - -import static org.apache.camel.quarkus.component.infinispan.InfinispanRoutes.CORRELATOR_HEADER; - -@Path("/infinispan") -@ApplicationScoped -public class InfinispanResources { - public static final String CACHE_NAME_CAMEL = "camel"; - public static final String CACHE_NAME_QUARKUS = "quarkus"; - - @Inject - RemoteCacheManager cacheManager; - - @Inject - ProducerTemplate template; - - @Inject - CamelContext camelContext; - - @Path("/inspect") - @GET - @Produces(MediaType.APPLICATION_JSON) - public JsonObject inspectCamelInfinispanClientConfiguration() { - InfinispanRemoteComponent component = camelContext.getComponent("infinispan", InfinispanRemoteComponent.class); - - return Json.createObjectBuilder() - .add("hosts", component.getConfiguration().getHosts()) - .add("cache-manager", Objects.toString(component.getConfiguration().getCacheContainer(), "none")) - .build(); - } - - @Path("/aggregate") - @GET - public void aggregate(@QueryParam("component") String component) throws InterruptedException { - String mockEndpointUri = component.equals("infinispan") ? "mock:camelAggregationResult" - : "mock:quarkusAggregationResult"; - MockEndpoint mockEndpoint = camelContext.getEndpoint(mockEndpointUri, MockEndpoint.class); - mockEndpoint.expectedMessageCount(2); - mockEndpoint.expectedBodiesReceived(1 + 3 + 4 + 5, 6 + 7 + 20 + 21); - - try { - String uri = component.equals("infinispan") ? "direct:camelAggregation" : "direct:quarkusAggregation"; - Map<String, Object> headers = getCommonHeaders(component); - headers.put(CORRELATOR_HEADER, CORRELATOR_HEADER); - - Stream.of(1, 3, 4, 5, 6, 7, 20, 21).forEach(value -> template.sendBodyAndHeaders(uri, value, headers)); - - mockEndpoint.assertIsSatisfied(15000); - } finally { - mockEndpoint.reset(); - } - } - - @Path("/clear") - @DELETE - public void clear(@QueryParam("component") String component) { - Map<String, Object> headers = getCommonHeaders(component); - template.sendBodyAndHeaders("direct:clear", null, headers); - } - - @Path("/clearAsync") - @DELETE - public void clearAsync(@QueryParam("component") String component) - throws ExecutionException, InterruptedException, TimeoutException { - Map<String, Object> headers = getCommonHeaders(component); - CompletableFuture<?> future = template.requestBodyAndHeaders("direct:clearAsync", null, headers, - CompletableFuture.class); - future.get(5, TimeUnit.SECONDS); - } - - @Path("/compute") - @POST - public void compute(@QueryParam("component") String component) { - Map<String, Object> headers = getCommonHeaders(component); - template.sendBodyAndHeaders("direct:compute", null, headers); - } - - @Path("/computeAsync") - @POST - public void computeAsync(@QueryParam("component") String component) - throws ExecutionException, InterruptedException, TimeoutException { - Map<String, Object> headers = getCommonHeaders(component); - CompletableFuture<?> future = template.requestBodyAndHeaders("direct:computeAsync", null, headers, - CompletableFuture.class); - future.get(5, TimeUnit.SECONDS); - } - - @Path("/containsKey") - @GET - @Produces(MediaType.TEXT_PLAIN) - public Boolean containsKey(@QueryParam("component") String component) { - Map<String, Object> headers = getCommonHeaders(component); - return template.requestBodyAndHeaders("direct:containsKey", null, headers, Boolean.class); - } - - @Path("/containsValue") - @GET - @Produces(MediaType.TEXT_PLAIN) - public Boolean containsValue(@QueryParam("component") String component, @QueryParam("value") String value) { - Map<String, Object> headers = getCommonHeaders(component); - return template.requestBodyAndHeaders("direct:containsValue", value, headers, Boolean.class); - } - - @Path("/event/verify") - @GET - public void listener( - @QueryParam("component") String component, - @QueryParam("mockEndpointUri") String mockEndpointUri, - String content) throws InterruptedException { - MockEndpoint mockEndpoint = camelContext.getEndpoint(mockEndpointUri, MockEndpoint.class); - mockEndpoint.expectedMessageCount(1); - mockEndpoint.message(0).header(InfinispanConstants.EVENT_TYPE).isEqualTo("CLIENT_CACHE_ENTRY_CREATED"); - mockEndpoint.message(0).header(InfinispanConstants.CACHE_NAME).isNotNull(); - mockEndpoint.message(0).header(InfinispanConstants.KEY).isEqualTo("the-key"); - - try { - Map<String, Object> headers = getCommonHeaders(component); - template.sendBodyAndHeaders("direct:put", content, headers); - mockEndpoint.assertIsSatisfied(5000); - } finally { - mockEndpoint.reset(); - } - } - - @Path("/get") - @GET - @Produces(MediaType.TEXT_PLAIN) - public String get(@QueryParam("component") String component, @QueryParam("key") String key) { - Map<String, Object> headers = getCommonHeaders(component); - headers.put(InfinispanConstants.KEY, Objects.requireNonNullElse(key, "the-key")); - return template.requestBodyAndHeaders("direct:get", null, headers, String.class); - } - - @Path("/getOrDefault") - @GET - @Produces(MediaType.TEXT_PLAIN) - public String getOrDefault(@QueryParam("component") String component) { - Map<String, Object> headers = getCommonHeaders(component); - return template.requestBodyAndHeaders("direct:getOrDefault", null, headers, String.class); - } - - @Path("/put") - @POST - @Consumes(MediaType.TEXT_PLAIN) - @Produces(MediaType.TEXT_PLAIN) - public String put(@QueryParam("component") String component, String content) { - Map<String, Object> headers = getCommonHeaders(component); - return template.requestBodyAndHeaders("direct:put", content, headers, String.class); - } - - @Path("/putAsync") - @POST - @Consumes(MediaType.TEXT_PLAIN) - public void putAsync(@QueryParam("component") String component, String content) - throws ExecutionException, InterruptedException, TimeoutException { - Map<String, Object> headers = getCommonHeaders(component); - CompletableFuture<?> future = template.requestBodyAndHeaders("direct:putAsync", content, headers, - CompletableFuture.class); - future.get(5, TimeUnit.SECONDS); - } - - @Path("/putAll") - @POST - public void putAll(@QueryParam("component") String component) { - Map<String, String> body = CollectionHelper.mapOf("key-1", "value-1", "key-2", "value-2"); - Map<String, Object> headers = getCommonHeaders(component); - template.sendBodyAndHeaders("direct:putAll", body, headers); - } - - @Path("/putAllAsync") - @POST - public void putAllAsync(@QueryParam("component") String component) - throws ExecutionException, InterruptedException, TimeoutException { - Map<String, String> body = CollectionHelper.mapOf("key-1", "value-1", "key-2", "value-2"); - Map<String, Object> headers = getCommonHeaders(component); - CompletableFuture<?> future = template.requestBodyAndHeaders("direct:putAllAsync", body, headers, - CompletableFuture.class); - future.get(5, TimeUnit.SECONDS); - } - - @Path("/putIdempotent") - @GET - public void putIdempotent(@QueryParam("component") String component) throws InterruptedException { - String mockEndpointUri = component.equals("infinispan") ? "mock:camelResultIdempotent" : "mock:quarkusResultIdempotent"; - MockEndpoint mockEndpoint = camelContext.getEndpoint(mockEndpointUri, MockEndpoint.class); - mockEndpoint.expectedMessageCount(1); - - String messageId = UUID.randomUUID().toString(); - String uri = component.equals("infinispan") ? "direct:camelIdempotent" : "direct:quarkusIdempotent"; - try { - IntStream.of(1, 10).forEach(value -> { - Map<String, Object> headers = getCommonHeaders(component); - headers.put("MessageId", messageId); - template.sendBodyAndHeaders(uri, "Message " + value, headers); - }); - - mockEndpoint.assertIsSatisfied(5000); - } finally { - mockEndpoint.reset(); - } - } - - @Path("/putIfAbsent") - @POST - @Consumes(MediaType.TEXT_PLAIN) - @Produces(MediaType.TEXT_PLAIN) - public String putIfAbsent(@QueryParam("component") String component, String content) { - Map<String, Object> headers = getCommonHeaders(component); - return template.requestBodyAndHeaders("direct:putIfAbsent", content, headers, String.class); - } - - @Path("/putIfAbsentAsync") - @POST - @Consumes(MediaType.TEXT_PLAIN) - public void putIfAbsentAsync(@QueryParam("component") String component, String content) - throws ExecutionException, InterruptedException, TimeoutException { - Map<String, Object> headers = getCommonHeaders(component); - CompletableFuture<?> future = template.requestBodyAndHeaders("direct:putIfAbsentAsync", content, headers, - CompletableFuture.class); - future.get(5, TimeUnit.SECONDS); - } - - @Path("/query") - @GET - @Produces(MediaType.TEXT_PLAIN) - @SuppressWarnings("unchecked") - public Response query(@QueryParam("component") String component) { - Map<String, Object> headers = getCommonHeaders(component); - String cacheName = (String) headers.get("cacheName"); - - cacheManager.getCache(cacheName).put("person", new Person("Test", "Person")); - - String query = "FROM person.Person WHERE firstName = 'Test'"; - InfinispanQueryBuilder builder = InfinispanQueryBuilder.create(query); - - headers.put(InfinispanConstants.QUERY_BUILDER, builder); - - List<String> result = template.requestBodyAndHeaders("direct:query", null, headers, List.class); - if (result.isEmpty()) { - return Response.status(404).build(); - } - return Response.ok().entity(result.get(0)).build(); - } - - @Path("/remove") - @DELETE - public void remove(@QueryParam("component") String component) { - Map<String, Object> headers = getCommonHeaders(component); - template.requestBodyAndHeaders("direct:remove", null, headers, String.class); - } - - @Path("/removeAsync") - @DELETE - public void removeAsync(@QueryParam("component") String component) - throws ExecutionException, InterruptedException, TimeoutException { - Map<String, Object> headers = getCommonHeaders(component); - CompletableFuture<?> future = template.requestBodyAndHeaders("direct:removeAsync", null, headers, - CompletableFuture.class); - future.get(5, TimeUnit.SECONDS); - } - - @Path("/replace") - @PATCH - @Consumes(MediaType.TEXT_PLAIN) - public void replace(@QueryParam("component") String component, String content) { - Map<String, Object> headers = getCommonHeaders(component); - template.sendBodyAndHeaders("direct:replace", content, headers); - } - - @Path("/replaceAsync") - @PATCH - @Consumes(MediaType.TEXT_PLAIN) - public void replaceAsync(@QueryParam("component") String component, String content) - throws ExecutionException, InterruptedException, TimeoutException { - Map<String, Object> headers = getCommonHeaders(component); - CompletableFuture<?> future = template.requestBodyAndHeaders("direct:replaceAsync", content, headers, - CompletableFuture.class); - future.get(5, TimeUnit.SECONDS); - } - - @Path("/size") - @GET - @Produces(MediaType.TEXT_PLAIN) - public Integer size(@QueryParam("component") String component) { - Map<String, Object> headers = getCommonHeaders(component); - return template.requestBodyAndHeaders("direct:size", null, headers, Integer.class); - } - - @Path("/stats") - @GET - @Produces(MediaType.TEXT_PLAIN) - public Integer stats(@QueryParam("component") String component) { - Map<String, Object> headers = getCommonHeaders(component); - ServerStatistics statistics = template.requestBodyAndHeaders("direct:stats", null, headers, ServerStatistics.class); - return statistics.getIntStatistic(ServerStatistics.APPROXIMATE_ENTRIES); - } - - @POST - @Path("consumer/{routeId}/{enabled}") - public void manageRoute( - @PathParam("routeId") String routeId, - @PathParam("enabled") boolean enabled) throws Exception { - if (enabled) { - camelContext.getRouteController().startRoute(routeId); - } else { - camelContext.getRouteController().stopRoute(routeId); - } - } - - private Map<String, Object> getCommonHeaders(String componentName) { - Map<String, Object> headers = new HashMap<>(); - headers.put("component", componentName); - - if (componentName.equals("infinispan")) { - headers.put("cacheName", CACHE_NAME_CAMEL); - } else { - headers.put("cacheName", CACHE_NAME_QUARKUS); - } - - return headers; - } -} diff --git a/integration-tests/infinispan/src/main/java/org/apache/camel/quarkus/component/infinispan/InfinispanRoutes.java b/integration-tests/infinispan/src/main/java/org/apache/camel/quarkus/component/infinispan/InfinispanRoutes.java deleted file mode 100644 index 967e9c1051..0000000000 --- a/integration-tests/infinispan/src/main/java/org/apache/camel/quarkus/component/infinispan/InfinispanRoutes.java +++ /dev/null @@ -1,305 +0,0 @@ -/* - * 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.quarkus.component.infinispan; - -import java.nio.charset.StandardCharsets; -import java.util.Set; -import java.util.function.BiFunction; - -import jakarta.inject.Named; -import org.apache.camel.AggregationStrategy; -import org.apache.camel.CamelContext; -import org.apache.camel.builder.RouteBuilder; -import org.apache.camel.component.infinispan.InfinispanConstants; -import org.apache.camel.component.infinispan.InfinispanOperation; -import org.apache.camel.component.infinispan.remote.InfinispanRemoteAggregationRepository; -import org.apache.camel.component.infinispan.remote.InfinispanRemoteComponent; -import org.apache.camel.component.infinispan.remote.InfinispanRemoteComponentConfigurer; -import org.apache.camel.component.infinispan.remote.InfinispanRemoteConfiguration; -import org.apache.camel.component.infinispan.remote.InfinispanRemoteCustomListener; -import org.apache.camel.component.infinispan.remote.InfinispanRemoteIdempotentRepository; -import org.eclipse.microprofile.config.Config; -import org.eclipse.microprofile.config.ConfigProvider; -import org.infinispan.client.hotrod.RemoteCacheManager; -import org.infinispan.client.hotrod.annotation.ClientCacheEntryCreated; -import org.infinispan.client.hotrod.annotation.ClientListener; -import org.infinispan.client.hotrod.configuration.Configuration; -import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; -import org.infinispan.client.hotrod.event.ClientCacheEntryCreatedEvent; -import org.infinispan.commons.marshall.StringMarshaller; - -import static org.apache.camel.quarkus.component.infinispan.InfinispanResources.CACHE_NAME_CAMEL; -import static org.apache.camel.quarkus.component.infinispan.InfinispanResources.CACHE_NAME_QUARKUS; - -public class InfinispanRoutes extends RouteBuilder { - public static final int COMPLETION_SIZE = 4; - public static final String CORRELATOR_HEADER = "CORRELATOR_HEADER"; - - @Override - public void configure() { - from("direct:clear") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.CLEAR) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .toD("${header.component}:${header.cacheName}"); - - from("direct:clearAsync") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.CLEARASYNC) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .toD("${header.component}:${header.cacheName}"); - - from("direct:compute") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.COMPUTE) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .toD("${header.component}:${header.cacheName}?remappingFunction=#customMappingFunction"); - - from("direct:computeAsync") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.COMPUTEASYNC) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .toD("${header.component}:${header.cacheName}?remappingFunction=#customMappingFunction"); - - from("direct:containsKey") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.CONTAINSKEY) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .toD("${header.component}:${header.cacheName}"); - - from("direct:containsValue") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.CONTAINSVALUE) - .setHeader(InfinispanConstants.VALUE).body() - .toD("${header.component}:${header.cacheName}"); - - from("direct:get") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.GET) - .toD("${header.component}:${header.cacheName}"); - - from("direct:getOrDefault") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.GETORDEFAULT) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .setHeader(InfinispanConstants.DEFAULT_VALUE).constant("default-value") - .toD("${header.component}:${header.cacheName}"); - - from("direct:put") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUT) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .setHeader(InfinispanConstants.VALUE).body() - .toD("${header.component}:${header.cacheName}"); - - from("direct:putAsync") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUTASYNC) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .setHeader(InfinispanConstants.VALUE).body() - .toD("${header.component}:${header.cacheName}"); - - from("direct:putAll") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUTALL) - .setHeader(InfinispanConstants.MAP).body() - .toD("${header.component}:${header.cacheName}"); - - from("direct:putAllAsync") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUTALLASYNC) - .setHeader(InfinispanConstants.MAP).body() - .toD("${header.component}:${header.cacheName}"); - - from("direct:putIfAbsent") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUTIFABSENT) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .setHeader(InfinispanConstants.VALUE).body() - .toD("${header.component}:${header.cacheName}"); - - from("direct:putIfAbsentAsync") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.PUTIFABSENTASYNC) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .setHeader(InfinispanConstants.VALUE).body() - .toD("${header.component}:${header.cacheName}"); - - from("direct:query") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.QUERY) - .toD("${header.component}:${header.cacheName}"); - - from("direct:remove") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.REMOVE) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .toD("${header.component}:${header.cacheName}"); - - from("direct:removeAsync") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.REMOVEASYNC) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .toD("${header.component}:${header.cacheName}"); - - from("direct:replace") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.REPLACE) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .setHeader(InfinispanConstants.VALUE).body() - .toD("${header.component}:${header.cacheName}"); - - from("direct:replaceAsync") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.REPLACEASYNC) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .setHeader(InfinispanConstants.VALUE).body() - .toD("${header.component}:${header.cacheName}"); - - from("direct:size") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.SIZE) - .setHeader(InfinispanConstants.KEY).constant("the-key") - .toD("${header.component}:${header.cacheName}"); - - from("direct:stats") - .setHeader(InfinispanConstants.OPERATION).constant(InfinispanOperation.STATS) - .toD("${header.component}:${header.cacheName}"); - - from("infinispan:camel?eventTypes=CLIENT_CACHE_ENTRY_CREATED") - .id("infinispan-events") - .autoStartup(false) - .to("mock:camelResultCreated"); - - from("direct:camelAggregation") - .aggregate(header(CORRELATOR_HEADER)) - .aggregationRepository(createAggregationRepository("infinispan")) - .aggregationStrategy(createAggregationStrategy()) - .completionSize(COMPLETION_SIZE) - .to("mock:camelAggregationResult"); - - from("direct:quarkusAggregation") - .aggregate(header(CORRELATOR_HEADER)) - .aggregationRepository(createAggregationRepository("infinispan-quarkus")) - .aggregationStrategy(createAggregationStrategy()) - .completionSize(COMPLETION_SIZE) - .to("mock:quarkusAggregationResult"); - - from("direct:camelIdempotent") - .idempotentConsumer(header("MessageID"), createIdempotentRepository("infinispan")) - .to("mock:camelResultIdempotent"); - - from("direct:quarkusIdempotent") - .idempotentConsumer(header("MessageID"), createIdempotentRepository("infinispan-quarkus")) - .to("mock:quarkusResultIdempotent"); - - from("infinispan-quarkus:quarkus?eventTypes=CLIENT_CACHE_ENTRY_CREATED") - .id("infinispan-quarkus-events") - .autoStartup(false) - .to("mock:quarkusResultCreated"); - - from("infinispan:camel?customListener=#customListener") - .id("infinispan-custom-listener") - .autoStartup(false) - .to("mock:camelResultCustomListener"); - - from("infinispan-quarkus:quarkus?customListener=#customListener") - .id("infinispan-quarkus-custom-listener") - .autoStartup(false) - .to("mock:quarkusResultCustomListener"); - } - - @Named("infinispan-quarkus") - public InfinispanRemoteComponent infinispanQuarkus() { - // This component will have its cacheContainer option autowired to use the one created by the Quarkus Infinispan extension - return new InfinispanRemoteComponent(); - } - - @Named("infinispan-quarkus-component") - public InfinispanRemoteComponentConfigurer quarkusInfinispanConfigurer() { - return new InfinispanRemoteComponentConfigurer(); - } - - @Named("customMappingFunction") - public BiFunction<String, String, String> mappingFunction() { - return (k, v) -> v + "-remapped"; - } - - @Named("customListener") - public InfinispanRemoteCustomListener customListener() { - return new CustomListener(); - } - - private InfinispanRemoteIdempotentRepository createIdempotentRepository(String componentName) { - String cacheName = componentName.equals("infinispan") ? CACHE_NAME_CAMEL : CACHE_NAME_QUARKUS; - InfinispanRemoteConfiguration configuration = getConfiguration(componentName); - InfinispanRemoteIdempotentRepository repository = new InfinispanRemoteIdempotentRepository(cacheName); - repository.setConfiguration(configuration); - return repository; - } - - private InfinispanRemoteAggregationRepository createAggregationRepository(String componentName) { - String cacheName = componentName.equals("infinispan") ? CACHE_NAME_CAMEL : CACHE_NAME_QUARKUS; - InfinispanRemoteAggregationRepository aggregationRepository = new InfinispanRemoteAggregationRepository(cacheName); - InfinispanRemoteConfiguration configuration = getConfiguration(componentName); - aggregationRepository.setConfiguration(configuration); - return aggregationRepository; - } - - private InfinispanRemoteConfiguration getConfiguration(String componentName) { - CamelContext camelContext = getCamelContext(); - InfinispanRemoteComponent component = camelContext.getComponent(componentName, InfinispanRemoteComponent.class); - InfinispanRemoteConfiguration configuration = component.getConfiguration().clone(); - configuration.setCacheContainerConfiguration(getConfigurationBuilder()); - Set<RemoteCacheManager> beans = camelContext.getRegistry().findByType(RemoteCacheManager.class); - RemoteCacheManager cacheManager = beans.iterator().next(); - configuration.setCacheContainer(cacheManager); - return configuration; - } - - private Configuration getConfigurationBuilder() { - Config config = ConfigProvider.getConfig(); - ConfigurationBuilder clientBuilder = new ConfigurationBuilder(); - String[] hostParts = config.getValue("quarkus.infinispan-client.server-list", String.class).split(":"); - - clientBuilder.addServer() - .host(hostParts[0]) - .port(Integer.parseInt(hostParts[1])); - - clientBuilder - .security() - .authentication() - .username(config.getValue("quarkus.infinispan-client.auth-username", String.class)) - .password(config.getValue("quarkus.infinispan-client.auth-password", String.class)) - .serverName(config.getValue("quarkus.infinispan-client.auth-server-name", String.class)) - .saslMechanism(config.getValue("quarkus.infinispan-client.sasl-mechanism", String.class)) - .realm(config.getValue("quarkus.infinispan-client.auth-realm", String.class)) - .marshaller(new StringMarshaller(StandardCharsets.UTF_8)); - - return clientBuilder.build(); - } - - private AggregationStrategy createAggregationStrategy() { - return (oldExchange, newExchange) -> { - if (oldExchange == null) { - return newExchange; - } else { - Integer n = newExchange.getIn().getBody(Integer.class); - Integer o = oldExchange.getIn().getBody(Integer.class); - Integer v = (o == null ? 0 : o) + (n == null ? 0 : n); - oldExchange.getIn().setBody(v, Integer.class); - return oldExchange; - } - }; - } - - @ClientListener - static final class CustomListener extends InfinispanRemoteCustomListener { - - @ClientCacheEntryCreated - public void entryCreated(ClientCacheEntryCreatedEvent<?> event) { - if (isAccepted(event.getType())) { - getEventProcessor().processEvent( - event.getType().toString(), - getCacheName(), - event.getKey(), - null, - null); - } - } - } -} diff --git a/integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanIT.java b/integration-tests/infinispan/src/test/java/InfinispanIT.java similarity index 94% rename from integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanIT.java rename to integration-tests/infinispan/src/test/java/InfinispanIT.java index 25a4208dc0..3f9b0daaaf 100644 --- a/integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanIT.java +++ b/integration-tests/infinispan/src/test/java/InfinispanIT.java @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.camel.quarkus.component.infinispan; import io.quarkus.test.junit.QuarkusIntegrationTest; diff --git a/integration-tests/infinispan/src/test/java/InfinispanServerTestResource.java b/integration-tests/infinispan/src/test/java/InfinispanServerTestResource.java new file mode 100644 index 0000000000..e60b099eb9 --- /dev/null +++ b/integration-tests/infinispan/src/test/java/InfinispanServerTestResource.java @@ -0,0 +1,40 @@ +/* + * 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. + */ + +import java.util.Map; + +import org.apache.camel.quarkus.component.infinispan.common.InfinispanCommonServerTestResource; + +public class InfinispanServerTestResource extends InfinispanCommonServerTestResource { + + @Override + public Map<String, String> start() { + Map<String, String> config = super.start(); + + config.put("camel.component.infinispan.autowired-enabled", "false"); + config.put("camel.component.infinispan.hosts", getServerList()); + config.put("camel.component.infinispan.username", USER); + config.put("camel.component.infinispan.password", PASS); + config.put("camel.component.infinispan.secure", "true"); + config.put("camel.component.infinispan.security-realm", "default"); + config.put("camel.component.infinispan.sasl-mechanism", "DIGEST-MD5"); + config.put("camel.component.infinispan.security-server-name", "infinispan"); + config.put("camel.component.infinispan.configuration-properties", "#additionalConfig"); + + return config; + } +} diff --git a/integration-tests/infinispan/src/test/java/InfinispanTest.java b/integration-tests/infinispan/src/test/java/InfinispanTest.java new file mode 100644 index 0000000000..c363e71e70 --- /dev/null +++ b/integration-tests/infinispan/src/test/java/InfinispanTest.java @@ -0,0 +1,44 @@ +/* + * 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. + */ + +import io.quarkus.test.common.QuarkusTestResource; +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import org.apache.camel.quarkus.component.infinispan.common.InfinispanCommonTest; +import org.eclipse.microprofile.config.ConfigProvider; +import org.junit.jupiter.api.Disabled; + +import static org.hamcrest.Matchers.is; + +@QuarkusTest +@QuarkusTestResource(InfinispanServerTestResource.class) +public class InfinispanTest extends InfinispanCommonTest { + public void inspect() { + String hosts = ConfigProvider.getConfig().getValue("camel.component.infinispan.hosts", String.class); + RestAssured.when() + .get("/infinispan/inspect") + .then().body( + "hosts", is(hosts), + "cache-manager", is("none")); + } + + @Disabled + @Override + public void query() { + super.query(); + } +} diff --git a/integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanServerTestResource.java b/integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanServerTestResource.java deleted file mode 100644 index 0f229ec59c..0000000000 --- a/integration-tests/infinispan/src/test/java/org/apache/camel/quarkus/component/infinispan/InfinispanServerTestResource.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.quarkus.component.infinispan; - -import java.util.Map; - -import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; -import org.apache.camel.util.CollectionHelper; -import org.apache.commons.lang3.SystemUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testcontainers.containers.BindMode; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.wait.strategy.Wait; -import org.testcontainers.utility.TestcontainersConfiguration; - -public class InfinispanServerTestResource implements QuarkusTestResourceLifecycleManager { - private static final Logger LOGGER = LoggerFactory.getLogger(InfinispanServerTestResource.class); - private static final String CONTAINER_IMAGE = System.getProperty("infinispan.container.image", "infinispan/server:13.0"); - private static final int HOTROD_PORT = 11222; - private static final String USER = "camel"; - private static final String PASS = "camel"; - - private GenericContainer<?> container; - - @Override - public Map<String, String> start() { - LOGGER.info(TestcontainersConfiguration.getInstance().toString()); - - try { - container = new GenericContainer<>(CONTAINER_IMAGE) - .withExposedPorts(HOTROD_PORT) - .withEnv("USER", USER) - .withEnv("PASS", PASS) - .withClasspathResourceMapping("infinispan.xml", "/user-config/infinispan.xml", BindMode.READ_ONLY) - .withCommand("-c", "/user-config/infinispan.xml") - .waitingFor(Wait.forListeningPort()); - - container.start(); - - String serverList = String.format("%s:%s", container.getHost(), - container.getMappedPort(HOTROD_PORT)); - - // Create 2 sets of configuration to test scenarios: - // - Quarkus Infinispan client bean being autowired into the Camel Infinispan component - // - Component configuration where the Infinispan client is managed by Camel (E.g Infinispan client autowiring disabled) - Map<String, String> result = CollectionHelper.mapOf( - // quarkus - "quarkus.infinispan-client.server-list", serverList, - "quarkus.infinispan-client.auth-username", USER, - "quarkus.infinispan-client.auth-password", PASS, - "quarkus.infinispan-client.auth-realm", "default", - "quarkus.infinispan-client.sasl-mechanism", "DIGEST-MD5", - "quarkus.infinispan-client.auth-server-name", "infinispan", - // camel - "camel.component.infinispan.autowired-enabled", "false", - "camel.component.infinispan.hosts", serverList, - "camel.component.infinispan.username", USER, - "camel.component.infinispan.password", PASS, - "camel.component.infinispan.secure", "true", - "camel.component.infinispan.security-realm", "default", - "camel.component.infinispan.sasl-mechanism", "DIGEST-MD5", - "camel.component.infinispan.security-server-name", - "infinispan"); - if (SystemUtils.IS_OS_MAC || SystemUtils.IS_OS_WINDOWS) { - /* Fix for https://github.com/apache/camel-quarkus/issues/2840 */ - result.put("quarkus.infinispan-client.client-intelligence", "BASIC"); - } - return result; - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - public void stop() { - try { - if (container != null) { - container.stop(); - } - } catch (Exception e) { - // ignored - } - } -} diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 73bde9a35d..f6fb866f22 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -111,7 +111,9 @@ <module>headersmap</module> <module>hl7</module> <module>http</module> - <module>infinispan</module> + <module>infinispan</module> + <module>infinispan-common</module> + <module>infinispan-quarkus-client</module> <module>influxdb</module> <module>jackson-avro</module> <module>jackson-protobuf</module> diff --git a/poms/bom-test/pom.xml b/poms/bom-test/pom.xml index e22046db8f..78b177fe13 100644 --- a/poms/bom-test/pom.xml +++ b/poms/bom-test/pom.xml @@ -188,6 +188,17 @@ <version>${camel-quarkus.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-integration-test-infinispan-common</artifactId> + <version>${camel-quarkus.version}</version> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-integration-test-infinispan-common</artifactId> + <version>${camel-quarkus.version}</version> + <type>test-jar</type> + </dependency> <dependency> <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-integration-test-messaging-common</artifactId> diff --git a/tooling/scripts/test-categories.yaml b/tooling/scripts/test-categories.yaml index 937b91a79d..5658ae216b 100644 --- a/tooling/scripts/test-categories.yaml +++ b/tooling/scripts/test-categories.yaml @@ -22,6 +22,7 @@ group-01: - google-storage - http - infinispan + - infinispan-quarkus-client - jcache - jms-artemis-client - jsch diff --git a/tooling/scripts/validate-github-workflows.groovy b/tooling/scripts/validate-github-workflows.groovy index cab11d1e44..2b3bddc049 100644 --- a/tooling/scripts/validate-github-workflows.groovy +++ b/tooling/scripts/validate-github-workflows.groovy @@ -33,6 +33,7 @@ final Set<String> executedBaseNames = [] as Set // Add any ignored itest modules here. Or prefix the module name with '#' to disable it final List<String> excludedModules = [ + 'infinispan-common', 'messaging', 'nats' ] as List