Skip to content

Commit

Permalink
Adds infinispan caches configuration resource build property
Browse files Browse the repository at this point in the history
  • Loading branch information
karesti committed Apr 23, 2023
1 parent d5e1e0e commit d7842f9
Show file tree
Hide file tree
Showing 16 changed files with 370 additions and 68 deletions.
22 changes: 16 additions & 6 deletions docs/src/main/asciidoc/infinispan-client-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -169,14 +169,24 @@ to create it on first access, use one of the following properties:

[source,properties]
----
quarkus.infinispan-client.cache.books.configuration-uri=cacheConfig.json <1>
quarkus.infinispan-client.cache.magazine.configuration=<distributed-cache><encoding media-type="application/x-protostream"/></distributed-cache> <2>
quarkus.infinispan-client.cache.magazine.configuration=<distributed-cache><encoding media-type="application/x-protostream"/></distributed-cache> <1>
quarkus.infinispan-client.cache.books.configuration-resource=booksDistributedCache.json <2>
quarkus.infinispan-client.cache.authors.configuration-uri=/file/authorsIndexedCache.yaml <3>
----
<1> The file name located under the `resources` folder that contains the configuration of the 'books' cache
<2> The configuration in xml of the 'magazine' (yaml and json are also supported)
<1> The configuration in xml of the 'magazine' (yaml and json are also supported)
<2> The file name located under the `resources` folder that contains the configuration of the 'books' cache
<3> A provided file URI. The file URI can also be a file under resources

If both `configuration-uri` and `configuration` are configured for the same cache with the same Quarkus profile,
`configuration-uri` gets preference over `configuration`.
If `configuration-resource`, `configuration` and `configuration-uri` are configured for the same cache with
the same Quarkus profile, `configuration-uri` gets the highest preference, over `configuration-resource` and `configuration`.
`configuration-resource` gets preference over `configuration`.

[WARNING]
====
The `configuration-resource` is build time property and the file will be included in the native build automatically.
`configuration-uri` can also point to a file under the `resources` folder. However, the file won't be automatically included
in the native executable, unless you configure the property `quarkus.native.resources.includes`.
====

[TIP]
====
Expand Down
12 changes: 12 additions & 0 deletions extensions/infinispan-client/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,18 @@
<artifactId>quarkus-kubernetes-service-binding-spi</artifactId>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-server-testdriver-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
import io.quarkus.deployment.builditem.NativeImageFeatureBuildItem;
import io.quarkus.deployment.builditem.SystemPropertyBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageConfigBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
import io.quarkus.deployment.builditem.nativeimage.NativeImageSecurityProviderBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
Expand Down Expand Up @@ -192,6 +193,7 @@ InfinispanPropertiesBuildItem setup(ApplicationArchivesBuildItem applicationArch
BuildProducer<NativeImageConfigBuildItem> nativeImageConfig,
BuildProducer<InfinispanClientNameBuildItem> infinispanClientNames,
MarshallingBuildItem marshallingBuildItem,
BuildProducer<NativeImageResourceBuildItem> resourceBuildItem,
CombinedIndexBuildItem applicationIndexBuildItem) throws ClassNotFoundException, IOException {

feature.produce(new FeatureBuildItem(Feature.INFINISPAN_CLIENT));
Expand All @@ -211,12 +213,19 @@ InfinispanPropertiesBuildItem setup(ApplicationArchivesBuildItem applicationArch
sslNativeSupport.produce(new ExtensionSslNativeSupportBuildItem(Feature.INFINISPAN_CLIENT));
nativeImageSecurityProviders.produce(new NativeImageSecurityProviderBuildItem(SASL_SECURITY_PROVIDER));

// add per cache file config
handlePerCacheFileConfig(infinispanClientsBuildTimeConfig.defaultInfinispanClient, resourceBuildItem, hotDeployment);
for (InfinispanClientBuildTimeConfig config : infinispanClientsBuildTimeConfig.namedInfinispanClients.values()) {
handlePerCacheFileConfig(config, resourceBuildItem, hotDeployment);
}

Map<String, Properties> propertiesMap = new HashMap<>();
IndexView index = applicationIndexBuildItem.getIndex();

// named and default
Set<String> allClientNames = infinispanClientNames(applicationIndexBuildItem, infinispanClientNames);
allClientNames.addAll(infinispanClientsBuildTimeConfig.getInfinispanNamedClientConfigNames());
allClientNames.add(DEFAULT_INFINISPAN_CLIENT_NAME);
for (String clientName : allClientNames) {
Properties properties = loadHotrodProperties(clientName, reflectiveClass, marshallingBuildItem);
propertiesMap.put(clientName, properties);
Expand Down Expand Up @@ -310,6 +319,17 @@ InfinispanPropertiesBuildItem setup(ApplicationArchivesBuildItem applicationArch
return new InfinispanPropertiesBuildItem(propertiesMap);
}

private void handlePerCacheFileConfig(InfinispanClientBuildTimeConfig config,
BuildProducer<NativeImageResourceBuildItem> resourceBuildItem,
BuildProducer<HotDeploymentWatchedFileBuildItem> hotDeployment) {
for (InfinispanClientBuildTimeConfig.RemoteCacheConfig cacheConfig : config.cache.values()) {
if (cacheConfig.configurationResource.isPresent()) {
resourceBuildItem.produce(new NativeImageResourceBuildItem(cacheConfig.configurationResource.get()));
hotDeployment.produce(new HotDeploymentWatchedFileBuildItem(cacheConfig.configurationResource.get()));
}
}
}

@BuildStep
@Record(ExecutionTime.STATIC_INIT)
BeanContainerListenerBuildItem build(InfinispanRecorder recorder, InfinispanPropertiesBuildItem builderBuildItem) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.quarkus.infinispan.client.deployment;

import static org.assertj.core.api.Assertions.assertThat;

import jakarta.inject.Inject;

import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.client.hotrod.configuration.ClientIntelligence;
import org.infinispan.client.hotrod.configuration.Configuration;
import org.infinispan.client.hotrod.configuration.NearCacheMode;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;

public class InfinispanConfigurationSetupTest {
@Inject
RemoteCacheManager remoteCacheManager;

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withEmptyApplication()
.withConfigurationResource("cache-config-application.properties")
.withApplicationRoot((jar) -> jar
.addAsResource("distributed-cache-config.xml")
.addAsResource("local-cache-config.xml"));

@Test
public void infinispanConnectionConfiguration() {
assertThat(remoteCacheManager).isNotNull();
Configuration configuration = remoteCacheManager.getConfiguration();
assertThat(configuration.servers().size()).isEqualTo(1);
assertThat(configuration.servers().get(0).host()).isEqualTo("cluster1");
assertThat(configuration.servers().get(0).port()).isEqualTo(31000);
assertThat(configuration.tracingPropagationEnabled()).isFalse();
assertThat(configuration.clientIntelligence()).isEqualTo(ClientIntelligence.BASIC);
assertThat(configuration.security().authentication().enabled()).isTrue();
assertThat(configuration.security().authentication().saslMechanism()).isEqualTo("BASIC");
assertThat(configuration.security().authentication().serverName()).isEqualTo("custom-server-name");
assertThat(configuration.security().ssl().enabled()).isTrue();
assertThat(configuration.security().ssl().trustStorePassword()).isEqualTo("trust-pass".toCharArray());
assertThat(configuration.security().ssl().trustStoreFileName()).isEqualTo("custom-trust-store");
assertThat(configuration.security().ssl().trustStoreType()).isEqualTo("JCEKS");
assertThat(configuration.security().ssl().provider()).isEqualTo("SSL_prov");
assertThat(configuration.security().ssl().protocol()).isEqualTo("SSL_protocol");
assertThat(configuration.security().ssl().ciphers()).containsExactlyInAnyOrder("SSL_cipher1", "SSL_cipher2");

assertThat(configuration.remoteCaches().get("cache1").configuration()).isEqualTo("<replicated-cache/>");
assertThat(configuration.remoteCaches().get("cache1").nearCacheBloomFilter()).isTrue();
assertThat(configuration.remoteCaches().get("cache1").nearCacheMaxEntries()).isEqualTo(100);
assertThat(configuration.remoteCaches().get("cache1").nearCacheMode()).isEqualTo(NearCacheMode.INVALIDATED);

assertThat(configuration.remoteCaches().get("cache2").configuration()).isEqualTo("<distributed-cache/>");
assertThat(configuration.remoteCaches().get("cache2").nearCacheBloomFilter()).isFalse();
assertThat(configuration.remoteCaches().get("cache2").nearCacheMaxEntries()).isEqualTo(-1);
assertThat(configuration.remoteCaches().get("cache2").nearCacheMode()).isEqualTo(NearCacheMode.DISABLED);

assertThat(configuration.remoteCaches().get("cache3").configuration()).isEqualTo("<local-cache/>");

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.quarkus.infinispan.client.deployment;

import static org.assertj.core.api.Assertions.assertThat;

import jakarta.inject.Inject;

import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.client.hotrod.configuration.ClientIntelligence;
import org.infinispan.client.hotrod.configuration.Configuration;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;

public class InfinispanDefaultMinimalConfigurationTest {
@Inject
RemoteCacheManager remoteCacheManager;

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withEmptyApplication()
.withConfigurationResource("minimal-application.properties");

@Test
public void infinispanConnectionConfiguration() {
assertThat(remoteCacheManager).isNotNull();
Configuration configuration = remoteCacheManager.getConfiguration();
assertThat(configuration.servers().size()).isEqualTo(1);
assertThat(configuration.servers().get(0).host()).isEqualTo("cluster1");
assertThat(configuration.servers().get(0).port()).isEqualTo(31000);
assertThat(configuration.tracingPropagationEnabled()).isTrue();
assertThat(configuration.clientIntelligence()).isEqualTo(ClientIntelligence.HASH_DISTRIBUTION_AWARE);
assertThat(configuration.remoteCaches()).isEmpty();
assertThat(configuration.security().authentication().enabled()).isTrue();
assertThat(configuration.security().authentication().saslMechanism()).isEqualTo("DIGEST-MD5");
assertThat(configuration.security().ssl().enabled()).isFalse();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.quarkus.infinispan.client.deployment;

import static org.assertj.core.api.Assertions.assertThat;

import jakarta.inject.Inject;

import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.client.hotrod.configuration.Configuration;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.infinispan.client.InfinispanClientName;
import io.quarkus.test.QuarkusUnitTest;

public class MultipleNamedInfinispanConfigurationSetupTest {
@Inject
RemoteCacheManager remoteCacheManager;

@Inject
@InfinispanClientName("another")
RemoteCacheManager anotherRemoteCacheManager;

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withEmptyApplication()
.withConfigurationResource("multiple-cache-config-application.properties")
.withApplicationRoot((jar) -> jar
.addAsResource("distributed-cache-config.xml")
.addAsResource("local-cache-config.xml"));

@Test
public void infinispanMultipleConnectionsConfiguration() {
assertThat(remoteCacheManager).isNotNull();
assertThat(anotherRemoteCacheManager).isNotNull();

Configuration configuration = remoteCacheManager.getConfiguration();
assertThat(configuration.servers().size()).isEqualTo(1);
assertThat(configuration.servers().get(0).host()).isEqualTo("cluster1");
assertThat(configuration.servers().get(0).port()).isEqualTo(31000);
assertThat(configuration.remoteCaches().get("cache3").configuration()).isEqualTo("<local-cache/>");

Configuration anotherConfiguration = anotherRemoteCacheManager.getConfiguration();
assertThat(anotherConfiguration.servers().size()).isEqualTo(1);
assertThat(anotherConfiguration.servers().get(0).host()).isEqualTo("cluster2");
assertThat(anotherConfiguration.servers().get(0).port()).isEqualTo(41000);
assertThat(anotherConfiguration.remoteCaches().get("cache4").configuration()).isEqualTo("<local-cache/>");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# don't run any server with test containers. this config is used to test the configuration mapping
quarkus.infinispan-client.devservices.enabled=false
quarkus.infinispan-client.use-schema-registration=false

quarkus.infinispan-client.hosts=cluster1:31000
quarkus.infinispan-client.username=infinispan
quarkus.infinispan-client.password=secret
quarkus.infinispan-client.tracing.propagation.enabled=false
quarkus.infinispan-client.client-intelligence=BASIC
quarkus.infinispan-client.sasl-mechanism=BASIC
quarkus.infinispan-client.auth-realm=infiniRealm
quarkus.infinispan-client.auth-server-name=custom-server-name
quarkus.infinispan-client.trust-store=custom-trust-store
quarkus.infinispan-client.trust-store-password=trust-pass
quarkus.infinispan-client.trust-store-type=JCEKS
quarkus.infinispan-client.ssl-provider=SSL_prov
quarkus.infinispan-client.ssl-protocol=SSL_protocol
quarkus.infinispan-client.ssl-ciphers=SSL_cipher1,SSL_cipher2

# cache 1 config
quarkus.infinispan-client.cache.cache1.configuration=<replicated-cache/>
quarkus.infinispan-client.cache.cache1.near-cache-use-bloom-filter=true
quarkus.infinispan-client.cache.cache1.near-cache-max-entries=100
quarkus.infinispan-client.cache.cache1.near-cache-mode=INVALIDATED

# cache 2 config (configuration-resource over configuration)
quarkus.infinispan-client.cache.cache2.configuration=<replicated-cache/>
quarkus.infinispan-client.cache.cache2.configuration-resource=distributed-cache-config.xml

# cache 3 config (configuration-uri over configuration-resource and configuration)
quarkus.infinispan-client.cache.cache3.configuration=<replicated-cache/>
quarkus.infinispan-client.cache.cache3.configuration-resource=distributed-cache-config.xml
quarkus.infinispan-client.cache.cache3.configuration-uri=local-cache-config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<distributed-cache/>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<local-cache/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# don't run any server with test containers. this config is used to test the configuration mapping
quarkus.infinispan-client.devservices.enabled=false
quarkus.infinispan-client.use-schema-registration=false

quarkus.infinispan-client.hosts=cluster1:31000
quarkus.infinispan-client.username=infinispan
quarkus.infinispan-client.password=secret
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# don't run any server with test containers. this config is used to test the configuration mapping
quarkus.infinispan-client.devservices.enabled=false
quarkus.infinispan-client.devservices.another.enabled=false
quarkus.infinispan-client.use-schema-registration=false
quarkus.infinispan-client.another.use-schema-registration=false

quarkus.infinispan-client.hosts=cluster1:31000
quarkus.infinispan-client.username=infinispan
quarkus.infinispan-client.password=secret

quarkus.infinispan-client.another.hosts=cluster2:41000
quarkus.infinispan-client.another.username=another-infinispan
quarkus.infinispan-client.another.password=another-secret

# cache 3 config (configuration-uri over configuration-resource and configuration)
quarkus.infinispan-client.cache.cache3.configuration-resource=distributed-cache-config.xml
quarkus.infinispan-client.cache.cache3.configuration-uri=local-cache-config.xml

# cache 4 config (only present in another and build time config)
quarkus.infinispan-client.another.cache.cache4.configuration-resource=local-cache-config.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.quarkus.infinispan.client.runtime;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

Expand All @@ -14,8 +16,11 @@ public class InfinispanClientBuildTimeConfig {

/**
* Sets the bounded entry count for near cache. If this value is 0 or less near cache is disabled.
*
* @deprecated use per cache configuration for near cache max entries
*/
@ConfigItem
@Deprecated
public int nearCacheMaxEntries;

/**
Expand All @@ -24,6 +29,26 @@ public class InfinispanClientBuildTimeConfig {
@ConfigItem
public Optional<String> marshallerClass;

/**
* Configures caches build time config from the client with the provided configuration.
*/
@ConfigItem
public Map<String, InfinispanClientBuildTimeConfig.RemoteCacheConfig> cache = new HashMap<>();

@ConfigGroup
public static class RemoteCacheConfig {

// @formatter:off
/**
* Cache configuration file in XML, JSON or YAML is defined in build time to create the cache on first access.
* An example of the user defined property. cacheConfig.xml file is located in the 'resources' folder:
* quarkus.infinispan-client.cache.bookscache.configuration-resource=cacheConfig.xml
*/
// @formatter:on
@ConfigItem
public Optional<String> configurationResource;
}

/**
* Configuration for DevServices. DevServices allows Quarkus to automatically start an Infinispan Server in dev and test
* mode.
Expand Down Expand Up @@ -60,7 +85,7 @@ public int hashCode() {

@Override
public String toString() {
return "InfinispanClientBuildTimeConfig{" +
"nearCacheMaxEntries=" + nearCacheMaxEntries + '}';
return "InfinispanClientBuildTimeConfig{" + "nearCacheMaxEntries=" + nearCacheMaxEntries + ", marshallerClass="
+ marshallerClass + ", cache=" + cache + ", devService=" + devService + '}';
}
}
Loading

0 comments on commit d7842f9

Please sign in to comment.