diff --git a/infinispan/README.adoc b/infinispan/README.adoc
index acd5b34ff..dc9aa813f 100644
--- a/infinispan/README.adoc
+++ b/infinispan/README.adoc
@@ -5,6 +5,11 @@
This example demonstrates how you can use Camel-Infinispan Starter component. The example is really simple: put a key/value pair in a remote cache and get the same key.
This example starts an Infinispan server with Infinispan Docker Image, so it can run OOTB.
+`camel infra run infinispan` only provisions the "default" cache-container on the server, it does not
+create a cache inside it. So the application itself creates the "default" cache on startup, via the
+`RemoteCacheManager` bean in `InfinispanConfiguration`, the same approach Camel's own Infinispan test
+suite uses (`RemoteCacheManager#administration().getOrCreateCache(...)`).
+
=== Build and test
You can build this example using:
@@ -23,6 +28,10 @@ You can run this example using:
And you should see output in the console.
+By default, the example connects to `localhost:11222` with the `admin`/`password` credentials that
+`camel infra run infinispan` uses. To point at a different server, set the `INFINISPAN_HOST`,
+`INFINISPAN_PORT`, `INFINISPAN_USERNAME` and `INFINISPAN_PASSWORD` environment variables.
+
=== Help and contributions
If you hit any problem using Camel or have some feedback, then please
diff --git a/infinispan/pom.xml b/infinispan/pom.xml
index f0fcf7f85..0bb3d7914 100644
--- a/infinispan/pom.xml
+++ b/infinispan/pom.xml
@@ -66,12 +66,6 @@
camel-infinispan-starter
-
- org.testcontainers
- testcontainers
- ${testcontainers-version}
-
-
org.springframework.boot
@@ -83,6 +77,12 @@
camel-test-spring-junit6
test
+
+ org.apache.camel
+ camel-test-infra-infinispan
+ ${project.version}
+ test
+
diff --git a/infinispan/src/main/java/org/apache/camel/example/springboot/infinispan/InfinispanConfiguration.java b/infinispan/src/main/java/org/apache/camel/example/springboot/infinispan/InfinispanConfiguration.java
new file mode 100644
index 000000000..4cfe275c2
--- /dev/null
+++ b/infinispan/src/main/java/org/apache/camel/example/springboot/infinispan/InfinispanConfiguration.java
@@ -0,0 +1,59 @@
+/*
+ * 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.example.springboot.infinispan;
+
+import org.infinispan.client.hotrod.RemoteCacheManager;
+import org.infinispan.configuration.cache.CacheMode;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class InfinispanConfiguration {
+
+ public static final String CACHE_NAME = "default";
+
+ /**
+ * camel infra run infinispan only provisions the "default" cache-container, not a cache inside it, so the
+ * cache must be created on first connect. Camel autowires this bean into infinispan:// endpoints by type.
+ */
+ @Bean
+ public RemoteCacheManager cacheContainer(
+ @Value("${infinispan.host}") String host,
+ @Value("${infinispan.port}") int port,
+ @Value("${infinispan.username}") String username,
+ @Value("${infinispan.password}") String password) {
+
+ org.infinispan.client.hotrod.configuration.ConfigurationBuilder clientBuilder
+ = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder();
+ clientBuilder.addServer().host(host).port(port);
+ clientBuilder.security().authentication()
+ .username(username)
+ .password(password)
+ .serverName("infinispan")
+ .saslMechanism("SCRAM-SHA-512")
+ .realm("default");
+
+ RemoteCacheManager cacheManager = new RemoteCacheManager(clientBuilder.build());
+ cacheManager.administration().getOrCreateCache(
+ CACHE_NAME,
+ new org.infinispan.configuration.cache.ConfigurationBuilder()
+ .clustering().cacheMode(CacheMode.DIST_SYNC).build());
+ return cacheManager;
+ }
+}
diff --git a/infinispan/src/main/resources/application.properties b/infinispan/src/main/resources/application.properties
index 1978656c1..cc110d1ba 100644
--- a/infinispan/src/main/resources/application.properties
+++ b/infinispan/src/main/resources/application.properties
@@ -17,9 +17,12 @@
camel.main.name=Infinispan
camel.main.run-controller=true
-camel.component.infinispan.hosts=localhost:11222
-camel.component.infinispan.username=admin
-camel.component.infinispan.password=password
-camel.component.infinispan.security-server-name=infinispan
-camel.component.infinispan.secure=true
+
+# Connection details for the RemoteCacheManager bean built in InfinispanConfiguration.
+# Not under the camel.* prefix: the manager is supplied to the infinispan component as a
+# bean (autowired by type), so these are plain Spring properties, not Camel component config.
+infinispan.host=${INFINISPAN_HOST:localhost}
+infinispan.port=${INFINISPAN_PORT:11222}
+infinispan.username=${INFINISPAN_USERNAME:admin}
+infinispan.password=${INFINISPAN_PASSWORD:password}
diff --git a/infinispan/src/test/java/org/apache/camel/example/springboot/infinispan/ApplicationTest.java b/infinispan/src/test/java/org/apache/camel/example/springboot/infinispan/ApplicationTest.java
index 01a6a7531..76f899234 100644
--- a/infinispan/src/test/java/org/apache/camel/example/springboot/infinispan/ApplicationTest.java
+++ b/infinispan/src/test/java/org/apache/camel/example/springboot/infinispan/ApplicationTest.java
@@ -1,88 +1,63 @@
+/*
+ * 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.example.springboot.infinispan;
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.infra.infinispan.services.InfinispanService;
+import org.apache.camel.test.infra.infinispan.services.InfinispanServiceFactory;
import org.apache.camel.test.spring.junit6.CamelSpringBootTest;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.junit.jupiter.api.extension.RegisterExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
-import org.testcontainers.containers.BindMode;
-import org.testcontainers.containers.GenericContainer;
-import org.testcontainers.containers.output.OutputFrame;
-import org.testcontainers.containers.output.Slf4jLogConsumer;
-import org.testcontainers.containers.wait.strategy.Wait;
-
-import com.github.dockerjava.api.command.CreateContainerCmd;
-import com.github.dockerjava.api.model.ExposedPort;
-import com.github.dockerjava.api.model.PortBinding;
-import com.github.dockerjava.api.model.Ports;
-
-import java.util.function.Consumer;
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
@CamelSpringBootTest
@SpringBootTest(classes = Application.class)
final class ApplicationTest {
- private static final Logger LOG = LoggerFactory.getLogger(ApplicationTest.class);
-
- private static final String CONTAINER_IMAGE = "quay.io/infinispan/server:15.2.1.Final";
-
- private static GenericContainer> container;
-
- @Autowired
- private ProducerTemplate producerTemplate;
-
- @Autowired
- private CamelContext camelContext;
-
- private static String host = "localhost";
-
- private static Integer port = 11222;
-
- private static String name = "infinispan";
-
- private static String username = "admin";
-
- private static String password = "password";
-
- private ApplicationTest() {
- }
-
- @BeforeAll
- public static void initContainer() {
- LOG.info("start infinispan docker container");
- final Consumer cmd = e -> {
- e.getHostConfig().withPortBindings(new PortBinding(Ports.Binding.bindPort(port),
- new ExposedPort(port)));
-
- };
- final Logger containerLog = LoggerFactory.getLogger("container." + name);
- final Consumer logConsumer = new Slf4jLogConsumer(containerLog);
-
- container = new GenericContainer<>(CONTAINER_IMAGE).withNetworkAliases(name)
- .withEnv("USER", username).withEnv("PASS", password)
- .withLogConsumer(logConsumer)
- .withClasspathResourceMapping("infinispan.xml", "/user-config/infinispan.xml",
- BindMode.READ_ONLY)
- .withCommand("-c", "/user-config/infinispan.xml").withExposedPorts(port)
- .withCreateContainerCmdModifier(cmd).waitingFor(Wait.forListeningPort())
- .waitingFor(Wait.forLogMessage(".*Infinispan.*Server.*started.*", 1));
- container.start();
- }
-
- @Test
- public void shouldPopulateCache() throws Exception {
- final MockEndpoint mock = camelContext.getEndpoint("mock:result", MockEndpoint.class);
- mock.expectedMessageCount(1);
- producerTemplate.sendBody("direct:test", null);
- mock.assertIsSatisfied();
- Assertions.assertEquals("test", mock.getExchanges().get(0).getIn().getBody(String.class));
- }
+ @RegisterExtension
+ static InfinispanService service = InfinispanServiceFactory.createSingletonInfinispanService();
+
+ @DynamicPropertySource
+ static void infinispanProperties(DynamicPropertyRegistry registry) {
+ registry.add("infinispan.host", service::host);
+ registry.add("infinispan.port", service::port);
+ registry.add("infinispan.username", service::username);
+ registry.add("infinispan.password", service::password);
+ }
+
+ @Autowired
+ private ProducerTemplate producerTemplate;
+
+ @Autowired
+ private CamelContext camelContext;
+
+ @Test
+ void shouldPopulateCache() throws Exception {
+ final MockEndpoint mock = camelContext.getEndpoint("mock:result", MockEndpoint.class);
+ mock.expectedMessageCount(1);
+ producerTemplate.sendBody("direct:test", null);
+ mock.assertIsSatisfied();
+ Assertions.assertEquals("test", mock.getExchanges().get(0).getIn().getBody(String.class));
+ }
}
diff --git a/infinispan/src/test/resources/infinispan.xml b/infinispan/src/test/resources/infinispan.xml
deleted file mode 100644
index ee9522176..000000000
--- a/infinispan/src/test/resources/infinispan.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-