diff --git a/bom/application/pom.xml b/bom/application/pom.xml
index 512f855a2247c..e544ab24d8c3e 100644
--- a/bom/application/pom.xml
+++ b/bom/application/pom.xml
@@ -131,8 +131,8 @@
5.9.1
1.5.0
6.14.2
- 13.0.11.Final
- 4.4.3.Final
+ 14.0.9.Final
+ 4.6.2.Final
2.9.3
4.1.86.Final
1.8.0
@@ -5214,6 +5214,11 @@
${smallrye-reactive-messaging.version}
+
+ org.infinispan
+ infinispan-api
+ ${infinispan.version}
+
org.infinispan
infinispan-core
diff --git a/docs/src/main/asciidoc/infinispan-client.adoc b/docs/src/main/asciidoc/infinispan-client.adoc
index 1e80e747e91dc..ea113be059537 100644
--- a/docs/src/main/asciidoc/infinispan-client.adoc
+++ b/docs/src/main/asciidoc/infinispan-client.adoc
@@ -44,9 +44,9 @@ This command adds the following dependency to your build file:
.build.gradle
----
implementation 'io.quarkus:quarkus-infinispan-client'
-annotationProcessor 'org.infinispan.protostream:protostream-processor:4.5.0.Final' <1>
+annotationProcessor 'org.infinispan.protostream:protostream-processor:4.5.1.Final' <1>
----
-<1> Mandatory in the gradle build to enable the generation of the files in the annotation based serialization
+<1> Mandatory in the Gradle build to enable the generation of the files in the annotation based serialization
== Configuring the Infinispan client
@@ -100,7 +100,7 @@ to create it on first access, use one of the following properties:
[source,properties]
----
-quarkus.infinispan-client.cache.books.configuration-uri=cacheConfig.xml <1>
+quarkus.infinispan-client.cache.books.configuration-uri=cacheConfig.json <1>
quarkus.infinispan-client.cache.magazine.configuration= <2>
----
<1> The file name located under the `resources` folder that contains the configuration of the 'books' cache
@@ -109,15 +109,42 @@ quarkus.infinispan-client.cache.magazine.configuration=
----
+.JSON
+[source,json,options="nowrap",subs=attributes+,role="secondary"]
+----
+{
+ "distributed-cache": {
+ "encoding": {
+ "media-type": "application/x-protostream"
+ }
+ }
+}
+----
+
+.YAML
+[source,yaml,options="nowrap",subs=attributes+,role="secondary"]
+----
+distributedCache:
+ encoding:
+ mediaType: "application/x-protostream"
+----
+
=== Authentication mechanisms
You can use the following authentication mechanisms with the Infinispan client:
@@ -130,10 +157,7 @@ Other authentication mechanisms, such as SCRAM and GSSAPI, are not yet verified
You can find more information on configuring authentication in https://infinispan.org/docs/stable/titles/hotrod_java/hotrod_java.html#hotrod_endpoint_auth-hotrod-client-configuration[Hot Rod Endpoint Authentication Mechanisms].
-[NOTE]
-====
-You must configure authentication in the `hotrod-client.properties` file if you use Dependency Injection.
-====
+NOTE: You must configure authentication in the `hotrod-client.properties` file if you use Dependency Injection.
== Serialization (Key Value types support)
@@ -267,10 +291,12 @@ interface BookStoreSchema extends GeneratedSchema {
----
[TIP]
+====
Protostream provides default Protobuf mappers for commonly used types as `BigDecimal`, included in the `org.infinispan.protostream.types` package.
+====
So in this case we will automatically generate the marshaller and schemas for the included classes and
-place them in the schema package automatically. The package does not have to be provided, but if you use Infinispan query capabilities, you must know the generated package.
+place them in the schema package automatically. The package does not have to be provided, but if you use Infinispan search capabilities, you must know the generated package.
NOTE: In Quarkus the `schemaFileName` and `schemaFilePath` attributes should NOT be set on the `AutoProtoSchemaBuilder` annotation. Setting either attributes causes native runtime errors.
@@ -439,7 +465,8 @@ the field, constructor or method. In the below code we utilize field and constru
this.remoteCacheManager = remoteCacheManager;
}
- @Inject @Remote("myCache")
+ @Inject
+ @Remote("myCache")
RemoteCache cache;
RemoteCacheManager remoteCacheManager;
@@ -470,23 +497,97 @@ for Kubernetes deployments, Infinispan Console,
https://infinispan.org/docs/stable/titles/rest/rest.html#rest_v2_protobuf_schemas[REST API] or the
https://infinispan.org/docs/stable/titles/encoding/encoding.html#registering-sci-remote-caches_marshalling[Hot Rod Java Client].
-
== Querying
-The Infinispan client supports both indexed and non-indexed querying as long as the
+The Infinispan client supports both indexed and non-indexed search as long as the
`ProtoStreamMarshaller` is configured above. This allows the user to query based on the
-properties of the proto schema.
+properties of the proto schema. *Indexed queries are preferred for performance reasons*.
+
+.XML
+[source,xml,options="nowrap",subs=attributes+,role="primary"]
+----
+
+
+
+
+ book_sample.Book
+
+
+
+----
+
+.JSON
+[source,json,options="nowrap",subs=attributes+,role="secondary"]
+----
+{
+ "books": {
+ "distributed-cache": {
+ ...
+ "indexing": {
+ "enabled": true,
+ "storage": "filesystem",
+ "startupMode": "PURGE",
+ "indexed-entities": [
+ "book_sample.Book"
+ ]
+ }
+ }
+ }
+}
+----
+
+.YAML
+[source,yaml,options="nowrap",subs=attributes+,role="secondary"]
+----
+distributedCache:
+ # other configuration
+ indexing:
+ enabled: "true"
+ storage: "filesystem"
+ startupMode: "PURGE"
+ indexedEntities:
+ - "book_sample.Book"
+----
Query builds upon the proto definitions you can configure when setting up the `ProtoStreamMarshaller`.
Either method of Serialization above will automatically register the schema with the server at
startup, meaning that you will automatically gain the ability to query objects stored in the
remote Infinispan Server.
-You can read more about https://infinispan.org/docs/stable/titles/developing/developing.html#creating_ickle_queries-querying[querying] in the Infinispan documentation.
+.Book.java
+[source,java]
+----
+@Indexed <1>
+public class Book {
+
+ @ProtoFactory
+ public Book(String title, String description, int publicationYear, Set authors) {
+ ...
+ }
+
+ @ProtoField(number = 1)
+ @Text <2>
+ public String getTitle() {
+ return title;
+ }
+
+ @ProtoField(number = 2)
+ @Keyword(projectable = true, sortable = true, normalizer = "lowercase", indexNullAs = "unnamed", norms = false) <3>
+ public String getDescription() {
+ return description;
+ }
+ ...
+----
+<1> `@Indexed` annotation makes the POJO indexable
+<2> `@Basic` annotation is used for indexed fields without any special transformation
+<3> `@Keyword` annotation is used to apply a normalizer to a text field
You can use either the Query DSL or the Ickle Query language with the Quarkus Infinispan client
extension.
+NOTE: You can read more about https://infinispan.org/docs/stable/titles/query/query.html[querying] in the Infinispan documentation.
+
+
== Counters
Infinispan also has a notion of counters and the Quarkus Infinispan client supports them out of
diff --git a/extensions/infinispan-client/deployment/pom.xml b/extensions/infinispan-client/deployment/pom.xml
index ba865f639aaaf..003671c759694 100644
--- a/extensions/infinispan-client/deployment/pom.xml
+++ b/extensions/infinispan-client/deployment/pom.xml
@@ -84,6 +84,10 @@
org.apache.logging.log4j
log4j-core
+
+ org.slf4j
+ jcl-over-slf4j
+
org.glassfish
javax.json
diff --git a/extensions/infinispan-client/runtime/pom.xml b/extensions/infinispan-client/runtime/pom.xml
index ce7a828f9cc7e..31b0e1818f749 100644
--- a/extensions/infinispan-client/runtime/pom.xml
+++ b/extensions/infinispan-client/runtime/pom.xml
@@ -86,6 +86,10 @@
opentelemetry-api
+
+ org.infinispan
+ infinispan-api
+
org.infinispan
infinispan-remote-query-client
diff --git a/independent-projects/enforcer-rules/src/main/resources/enforcer-rules/quarkus-banned-dependencies.xml b/independent-projects/enforcer-rules/src/main/resources/enforcer-rules/quarkus-banned-dependencies.xml
index 805b934d866db..9c37d9cf628d4 100644
--- a/independent-projects/enforcer-rules/src/main/resources/enforcer-rules/quarkus-banned-dependencies.xml
+++ b/independent-projects/enforcer-rules/src/main/resources/enforcer-rules/quarkus-banned-dependencies.xml
@@ -98,8 +98,9 @@
org.apache.tomcat.embed:tomcat-embed-core
org.jboss.modules:jboss-modules
-
- org.javassist:javassist
+
+
@@ -107,4 +108,4 @@
-
\ No newline at end of file
+
diff --git a/integration-tests/infinispan-client/src/main/java/io/quarkus/it/infinispan/client/Book.java b/integration-tests/infinispan-client/src/main/java/io/quarkus/it/infinispan/client/Book.java
index ca404a8f7985c..45dfc48c3a002 100644
--- a/integration-tests/infinispan-client/src/main/java/io/quarkus/it/infinispan/client/Book.java
+++ b/integration-tests/infinispan-client/src/main/java/io/quarkus/it/infinispan/client/Book.java
@@ -4,12 +4,16 @@
import java.util.Objects;
import java.util.Set;
+import org.infinispan.api.annotations.indexing.Indexed;
+import org.infinispan.api.annotations.indexing.Keyword;
+import org.infinispan.api.annotations.indexing.Text;
import org.infinispan.protostream.annotations.ProtoFactory;
import org.infinispan.protostream.annotations.ProtoField;
/**
* @author William Burns
*/
+@Indexed
public class Book {
private final String title;
private final String description;
@@ -29,11 +33,13 @@ public Book(String title, String description, int publicationYear, Set a
}
@ProtoField(number = 1)
+ @Text
public String getTitle() {
return title;
}
@ProtoField(number = 2)
+ @Keyword(projectable = true, sortable = true, normalizer = "lowercase", indexNullAs = "unnamed", norms = false)
public String getDescription() {
return description;
}
diff --git a/integration-tests/infinispan-client/src/main/java/io/quarkus/it/infinispan/client/TestServlet.java b/integration-tests/infinispan-client/src/main/java/io/quarkus/it/infinispan/client/TestServlet.java
index 7352e9f637d16..c75e6cf594091 100644
--- a/integration-tests/infinispan-client/src/main/java/io/quarkus/it/infinispan/client/TestServlet.java
+++ b/integration-tests/infinispan-client/src/main/java/io/quarkus/it/infinispan/client/TestServlet.java
@@ -4,16 +4,19 @@
import java.util.Collections;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
+import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -25,11 +28,14 @@
import org.infinispan.counter.api.CounterConfiguration;
import org.infinispan.counter.api.CounterManager;
import org.infinispan.counter.api.CounterType;
+import org.infinispan.counter.api.Storage;
import org.infinispan.counter.api.StrongCounter;
+import org.infinispan.counter.api.WeakCounter;
import org.infinispan.query.dsl.Query;
import org.infinispan.query.dsl.QueryFactory;
import io.quarkus.infinispan.client.Remote;
+import io.smallrye.common.annotation.Blocking;
@Path("/test")
public class TestServlet {
@@ -111,16 +117,38 @@ public String ickleQueryAuthorSurname(@PathParam("id") String name) {
.collect(Collectors.joining(",", "[", "]"));
}
+ @Path("counter/{id}")
+ @POST
+ @Produces(MediaType.TEXT_PLAIN)
+ @Blocking
+ public boolean defineCounter(@PathParam("id") String id, @QueryParam("type") String type,
+ @QueryParam("storage") String storage) {
+ cacheSetup.ensureStarted();
+ CounterConfiguration configuration = counterManager.getConfiguration(id);
+ if (configuration == null) {
+ configuration = CounterConfiguration.builder(CounterType.valueOf(type)).storage(Storage.valueOf(storage)).build();
+ return counterManager.defineCounter(id, configuration);
+ }
+ return true;
+ }
+
@Path("incr/{id}")
@GET
@Produces(MediaType.TEXT_PLAIN)
+ @Blocking
public CompletionStage incrementCounter(@PathParam("id") String id) {
cacheSetup.ensureStarted();
CounterConfiguration configuration = counterManager.getConfiguration(id);
if (configuration == null) {
- configuration = CounterConfiguration.builder(CounterType.BOUNDED_STRONG).build();
- counterManager.defineCounter(id, configuration);
+ return CompletableFuture.completedFuture(0L);
}
+
+ if (configuration.type() == CounterType.WEAK) {
+ WeakCounter weakCounter = counterManager.getWeakCounter(id);
+ weakCounter.sync().increment();
+ return CompletableFuture.completedFuture(weakCounter.getValue());
+ }
+
StrongCounter strongCounter = counterManager.getStrongCounter(id);
return strongCounter.incrementAndGet();
}
diff --git a/integration-tests/infinispan-client/src/main/resources/application.properties b/integration-tests/infinispan-client/src/main/resources/application.properties
index 3754896fb54dd..5a02e6e32f971 100644
--- a/integration-tests/infinispan-client/src/main/resources/application.properties
+++ b/integration-tests/infinispan-client/src/main/resources/application.properties
@@ -1,4 +1,5 @@
quarkus.infinispan-client.cache.default.configuration-uri=cacheConfig.xml
+quarkus.infinispan-client.cache.books.configuration-uri=booksIndexedConfig.json
quarkus.infinispan-client.cache.magazine.configuration=
quarkus.infinispan-client.cache.default.near-cache-mode=INVALIDATED
quarkus.infinispan-client.cache.default.near-cache-max-entries=2
@@ -6,4 +7,4 @@ quarkus.infinispan-client.cache.default.near-cache-use-bloom-filter=false
quarkus.infinispan-client.cache.magazine.near-cache-mode=INVALIDATED
quarkus.infinispan-client.cache.magazine.near-cache-max-entries=2
quarkus.infinispan-client.cache.magazine.near-cache-use-bloom-filter=false
-quarkus.native.resources.includes=cacheConfig.xml
\ No newline at end of file
+quarkus.native.resources.includes=cacheConfig.xml,booksIndexedConfig.json
diff --git a/integration-tests/infinispan-client/src/main/resources/booksIndexedConfig.json b/integration-tests/infinispan-client/src/main/resources/booksIndexedConfig.json
new file mode 100644
index 0000000000000..6f515612766d4
--- /dev/null
+++ b/integration-tests/infinispan-client/src/main/resources/booksIndexedConfig.json
@@ -0,0 +1,16 @@
+{
+ "distributed-cache": {
+ "statistics": true,
+ "encoding": {
+ "media-type": "application/x-protostream"
+ },
+ "indexing": {
+ "enabled": true,
+ "storage": "filesystem",
+ "startup-mode": "Purge",
+ "indexed-entities": [
+ "book_sample.Book"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/integration-tests/infinispan-client/src/test/java/io/quarkus/it/infinispan/client/InfinispanClientFunctionalityTest.java b/integration-tests/infinispan-client/src/test/java/io/quarkus/it/infinispan/client/InfinispanClientFunctionalityTest.java
index 9de116a8d3964..57dd0a9291bf2 100644
--- a/integration-tests/infinispan-client/src/test/java/io/quarkus/it/infinispan/client/InfinispanClientFunctionalityTest.java
+++ b/integration-tests/infinispan-client/src/test/java/io/quarkus/it/infinispan/client/InfinispanClientFunctionalityTest.java
@@ -3,6 +3,8 @@
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.infinispan.counter.api.CounterType;
+import org.infinispan.counter.api.Storage;
import org.junit.jupiter.api.Test;
import io.quarkus.test.junit.QuarkusTest;
@@ -32,8 +34,30 @@ public void testIckleQuery() {
@Test
public void testCounterIncrement() {
- String initialValue = RestAssured.when().get("test/incr/somevalue").body().print();
- String nextValue = RestAssured.when().get("test/incr/somevalue").body().print();
+ RestAssured.given()
+ .queryParam("type", CounterType.BOUNDED_STRONG)
+ .queryParam("storage", Storage.VOLATILE)
+ .post("test/counter/strong-1").body().print();
+
+ RestAssured.given()
+ .queryParam("type", CounterType.WEAK)
+ .queryParam("storage", Storage.VOLATILE)
+ .post("test/counter/weak-1").body().print();
+
+ RestAssured.given()
+ .queryParam("type", CounterType.UNBOUNDED_STRONG)
+ .queryParam("storage", Storage.PERSISTENT)
+ .post("test/counter/strong-2").body().print();
+
+ assertCounterIncrement("strong-1");
+ assertCounterIncrement("weak-1");
+ assertCounterIncrement("strong-2");
+ }
+
+ private void assertCounterIncrement(String counterName) {
+ String initialValue = RestAssured.given()
+ .get("test/incr/" + counterName).body().print();
+ String nextValue = RestAssured.when().get("test/incr/" + counterName).body().print();
assertEquals(Integer.parseInt(initialValue) + 1, Integer.parseInt(nextValue));
}
diff --git a/jakarta/rewrite.yml b/jakarta/rewrite.yml
index f1c0c9c319d3a..a0dcbc485b0b6 100644
--- a/jakarta/rewrite.yml
+++ b/jakarta/rewrite.yml
@@ -849,12 +849,6 @@ type: specs.openrewrite.org/v1beta/recipe
name: io.quarkus.infinispan
displayName: Adjust Infinispan version and dependencies
recipeList:
- - org.openrewrite.maven.ChangePropertyValue:
- key: infinispan.version
- newValue: 14.0.0.Final
- - org.openrewrite.maven.ChangePropertyValue:
- key: infinispan.protostream.version
- newValue: 4.5.0.Final
- org.openrewrite.maven.ChangeManagedDependencyGroupIdAndArtifactId:
oldGroupId: org.infinispan
oldArtifactId: infinispan-core