|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: 'Quarkus and Infinispan: winner combo' |
| 4 | +date: 2024-06-06 |
| 5 | +tags: ['infinispan', 'cache'] |
| 6 | +synopsis: 'Infinispan extension updates from Quarkus 3.9, 3.10 and 3.11' |
| 7 | +author: karesti |
| 8 | +--- |
| 9 | + |
| 10 | +Infinispan 15.0 has been recently released, bringing along a wave of enhancements that |
| 11 | +Quarkus has also embraced. Let's dive into this blog post to spotlight the significant |
| 12 | +updates and improvements for both Infinispan and Quarkus. |
| 13 | + |
| 14 | +== Serialization API improvements |
| 15 | + |
| 16 | +Infinispan can handle various serialization formats, but Protobuf stands out as the most |
| 17 | +compatible one, offering full access to all Infinispan Cache features. It's supported through |
| 18 | +the Protostream library. With Protostream 5, you not only get support for Protobuf 3 but also |
| 19 | +a more straightforward and user-friendly API. |
| 20 | + |
| 21 | +=== @Proto |
| 22 | + |
| 23 | +Using the `@Proto` annotation alone is sufficient to serialize a class, enum, or record with |
| 24 | +Protostream. If you want to be more specific about what needs to be serialized, you can still |
| 25 | +use the `@Protofield` annotation. However, a default schema setup will be automatically handled |
| 26 | +for you with just a single annotation. This feature comes in handy, especially when your |
| 27 | +schema undergoes frequent changes, and you need to refresh data frequently. |
| 28 | + |
| 29 | +[source, java] |
| 30 | +---- |
| 31 | +@Proto |
| 32 | +public record Author(String name, String surname) { |
| 33 | +} |
| 34 | +---- |
| 35 | + |
| 36 | +=== @ProtoSchema |
| 37 | + |
| 38 | +The annotation used to define the schema has been renamed to `@ProtoSchema`. |
| 39 | +So now, instead of `@AutoProtoSchemaBuilder`, you would use `@ProtoSchema` for specifying the schema. |
| 40 | +This helps clarify its purpose and usage. |
| 41 | + |
| 42 | +[source, java] |
| 43 | +---- |
| 44 | +@ProtoSchema(includeClasses = { Book.class, Author.class }, schemaPackageName = "book_sample") |
| 45 | +interface BookStoreSchema extends GeneratedSchema { |
| 46 | +} |
| 47 | +---- |
| 48 | + |
| 49 | +=== Programmatic definition of schemas |
| 50 | + |
| 51 | +If you need to define the schema programmatically, Protostream 5 now offers an API for |
| 52 | +that purpose. This allows you to define the schema dynamically in your code as needed. |
| 53 | + |
| 54 | +[source, java] |
| 55 | +---- |
| 56 | +@Produces |
| 57 | +Schema magazineSchema() { |
| 58 | + return new Schema.Builder("magazine.proto") |
| 59 | + .packageName("magazine_sample") |
| 60 | + .addMessage("Magazine") |
| 61 | + .addField(Type.Scalar.STRING, "name", 1) |
| 62 | + .addField(Type.Scalar.INT32, "publicationYear", 2) |
| 63 | + .addField(Type.Scalar.INT32, "publicationMonth", 3) |
| 64 | + .addRepeatedField(Type.Scalar.STRING, "stories", 4) |
| 65 | + .build(); |
| 66 | +} |
| 67 | +---- |
| 68 | + |
| 69 | +Moreover, the `MessageMarshaller` class, which was previously planned for deprecation and removal, |
| 70 | +has been reinstated and can continue to be safely used for implementing custom marshalling. |
| 71 | + |
| 72 | + |
| 73 | +== Support for mocks |
| 74 | +Before Quarkus 3.9, because of the Search API, it wasn't possible to mock |
| 75 | +`RemoteCache` beans using `@QuarkusTest` and `@QuarkusMock` due to their `Singleton` scope. |
| 76 | +However, starting from Quarkus 3.9, their scope has been changed to `ApplicationScoped`, |
| 77 | +enabling full mocking for tests. |
| 78 | + |
| 79 | +Additionally, there have been enhancements in the Search API. |
| 80 | +Now, we can directly perform searches using methods exposed in the `RemoteCache` interface. |
| 81 | + |
| 82 | +[source, java] |
| 83 | +---- |
| 84 | +@Inject |
| 85 | +@Remote("books") |
| 86 | +RemoteCache<String, Book> booksCache; <1> |
| 87 | +
|
| 88 | +... |
| 89 | +
|
| 90 | +Query<Book> query = booksCache.query("from book_sample.Book b where b.authors.name like '%" + name + "%'"); <2> |
| 91 | +List<Book> list = query.execute().list(); <3> |
| 92 | +---- |
| 93 | +<1> Books cache is injected |
| 94 | +<2> Use `query` method directly on the books cache |
| 95 | +<3> Retrieve the list as usual |
| 96 | + |
| 97 | +== Infinispan Cache extension |
| 98 | +Starting from Quarkus 3.11, the caching annotations in the Infinispan Cache |
| 99 | +extension have been deprecated. Infinispan now offers a new cache extension. |
| 100 | + |
| 101 | +By swapping out the `quarkus-cache` dependency with `quarkus-infinispan-cache`, |
| 102 | +you can utilize `@CacheResult`, `@CacheInvalidate`, and `@CacheInvalidateAll` annotations |
| 103 | +from the `quarkus-cache` extension, while storing the data in the Infinispan Server. |
| 104 | + |
| 105 | +[source, java] |
| 106 | +---- |
| 107 | + @GET |
| 108 | + @Path("/{country}/{city}/{name}") |
| 109 | + @CacheResult(cacheName = "fruits") |
| 110 | + public ExpensiveFruitsResponse getExpensiveFruitsResponse(@PathParam("country") @CacheKey String country, |
| 111 | + @PathParam("city") @CacheKey String city, |
| 112 | + @PathParam("name") @CacheKey String name, |
| 113 | + @QueryParam("metadata") String metadata) { |
| 114 | + invocations.incrementAndGet(); |
| 115 | + String id = UUID.randomUUID().toString(); |
| 116 | + String description = String.format("Fruit in city %s, with name %s", city, name); |
| 117 | + return new ExpensiveFruitsResponse(id, description, metadata); |
| 118 | + } |
| 119 | +---- |
| 120 | + |
| 121 | +Read all about it in the https://quarkus.io/guides/cache-infinispan-reference[Infinispan Cache Extension Guide] |
| 122 | + |
| 123 | +== Infinispan and Quarkus LangChain4j Integration |
| 124 | +Now, you can use Infinispan as an Embedding Store in the Quarkus LangChain4j extension. |
| 125 | +Infinispan has full text features thanks to a special integration with Hibernate Search. |
| 126 | +Plus, starting from Hibernate Search 7.1, Vector Search is supported. This means you can use the |
| 127 | +Infinispan Server as an Embedding Storage for your LLM applications. |
| 128 | +Read all about it in the https://docs.quarkiverse.io/quarkus-langchain4j/dev/infinispan-store.html[documentation]. |
| 129 | + |
| 130 | +== Come Join Us |
| 131 | + |
| 132 | +We value your feedback a lot so please report bugs, ask for improvements... Let's build something great together! |
| 133 | + |
| 134 | +If you are a Quarkus user or just curious, don't be shy and join our welcoming community: |
| 135 | + |
| 136 | + * provide feedback on https://github.com/quarkusio/quarkus/issues[GitHub]; |
| 137 | + * craft some code and https://github.com/quarkusio/quarkus/pulls[push a PR]; |
| 138 | + * discuss with us on https://quarkusio.zulipchat.com/[Zulip] and on the https://groups.google.com/d/forum/quarkus-dev[mailing list]; |
| 139 | + * ask your questions on https://stackoverflow.com/questions/tagged/quarkus[Stack Overflow]. |
0 commit comments