Quarkus: JCache (JSR 107) Extension

Created on 6 Jul 2019  Â·  26Comments  Â·  Source: quarkusio/quarkus

Description
The JCache JSR (JSR-107) Quarkus Extension

Implementation ideas
One of Infinispan or Hazelcast implementations will be enough on the first step.

arecache kinenhancement triagduplicate

Most helpful comment

There are multiple issues at stake here ranging from the technical to the legal.

First off, I think we should avoid the JCache annotations if possible, as it is unlikely they can be evolved to support additional use cases. We should opt either for a Quarkus-specific solution (low effort, more freedom) or for something more ambitious (Microprofile Caching ?).
As @ben-manes says, we can still support JCache, but only through a compatibility layer rather than having it influence our implementation choices.

Aside from the "locking get" (I also happen to dislike Spring Cache's use of the term "synchronized" here) a useful @Cacheable annotation should also have a read-timeout (as caching may not always be local) as well as encouraging non-blocking patterns (although simply detecting that the annotated method returns a CompletionStage should be enough).

All 26 comments

+1 but I'd rather love to see an EhCache implementation as it's a widely used cache implementation with a nice API and a lot of people use it.
Maybe we need a JCache implementation where we can plugged in multiple cache provider so we can cover more use cases:

  • local cache (EhCache are the most used)
  • distributed caching (with JGroups for ex)
  • remote caching (client/server like Hazelcast and Infinispan)
  • ...

@gsmet Is there already someone working on such a cache extension?

I'd be very interested in contributing to Quarkus by submitting a new extension (it would be my first one) but I'm not a cache expert (only a regular user) so I'm wondering if this subject would be a good one.

I think it would be an interesting addition.

Our choice of implementation would be Infinispan I suppose as we find it to be a good compromise for local and remote caching.

What would be interesting too would be to have caching annotations to automatically cache the result of a bean method - similar to what Spring has with the @Cacheable annotation.

/cc @Sanne

@gsmet JSR 107 already defines how the cache abstraction should be. And there are JCache Annotations and Events already defined. Also there are many local or remote JCache provider implementations (Infinispan, hazelcast, eh-cache). Because of that, i suggested JSR107 extension instead of specific cache vendor extension. In my opinion we should stick with the spec and the first provider supported can be Infinispan.

JCache Annotations.
javax.cache.annotation.CacheDefaults
javax.cache.annotation.CacheKey
javax.cache.annotation.CacheResult
javax.cache.annotation.CacheValue
javax.cache.annotation.CachePut
javax.cache.annotation.CacheRemove
javax.cache.annotation.CacheRemoveAll

Ah I didn’t know JCache had a set of annotations, I only used the cache abstraction in the Hibernate ORM context.

I agree with everything you said.

@anadollu do you plan to work on this or can @gwenneg give it a go?

Hello,

It was on my todo list also :) but I'm very busy at the moment ...

I really love to see a JCache extension that, based on annotations, allow
to easily implement a cache layer on top of existing methods. It should not
be too complicated to build with CDI interceptors.

There is already a cache implementation on Quarkus for Hibernate
second-level cache (https://quarkus.io/guides/hibernate-orm-guide#caching),
don't know if we need to make those two functionalities works together but
it's worth looking into it (it's based on Cafeine : it's the first time I
heard about this framework). EhCache also implement the Hibernate
second-level cache API so making both works together will allow to avoid
one dependency !

What I really love will be to have the choice of caching implemenatipn, so
the extension should be as agnostic as possible to the cache
implementation, and Quarkus should allow multiple implementations (starting
with Infinispan and EhCache should be OK as infinispan is aleady integrated
in Quarks and EhCache is IMHO the most used cache implementation in Java).
It's very important beause some cache allow different topology (local heap,
local off-heap, remote, distributed) with different performance/capacity
caracteristics ...

This extention needs to be able to be 100% configurable via
application.properties for simple use case (TTL, nb of elements, global
size for example) and allow optional fine grained configuration via it's
standard configuration file (ehcache.xlm for example).

Regards,

Loïc

Le dim. 14 juil. 2019 à 17:13, Guillaume Smet notifications@github.com a
écrit :

@anadollu https://github.com/anadollu do you plan to work on this or
can @gwenneg https://github.com/gwenneg give it a go?

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/quarkusio/quarkus/issues/3128?email_source=notifications&email_token=AAN4DALD5GDBHMT4KTFM2KTP7M7A3A5CNFSM4H6TRQRKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODZ4HK7I#issuecomment-511210877,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAN4DAOMRZT37G4UEVZIEQDP7M7A3ANCNFSM4H6TRQRA
.

@gwenneg I think you can start on this if you want.

My proposal would be to do it step by step:

  • implement the interceptor layer based on the JCache annotations backed by Infinispan: I think this one only would already be a quite significant work
  • see if we can configure the caches via Quarkus: note that the configuration exposed by JCache is quite limited: you can't set a limit to the number of objects cached for instance
  • then see how we could support plugging other implementations: there's a good chance we will only support one implementation in Quarkus core itself but we plan to push a Quarkus platform with user contributed extensions.

Probably good to share an early branch so that other interested people can step up and help.

@gsmet Ok I'll start working on this in the next days and share a branch this next week.

@gwenneg take a look at the Hibernate Validator extension to know how to deal with interceptors.

N.B. the Quarkus team is aiming for an "opinionated" approach, so that we can focus on a smaller set of moving parts in terms of dependencies and actually support an high quality integration among _all_ dependencies.
While it's ok to make as many extensions as you want outside of the "core Quarkus" repository, we will want to pick (and recommend, document, etc..) a single implementation for each use case.

_Take this also as a way for us that we won't be able to shift blame of any bugs to the implementation maintainer, we better make really good choices ;-)_

That said I agree that we could have a different implementation per each use case as @loicmathieu suggested, quoting him:

local cache (EhCache are the most used)
distributed caching (with JGroups for ex)
remote caching (client/server like Hazelcast and Infinispan)

however since we already discussed this (and work has already started on these) they will be:

  • Caffeine based for local caches
  • Infinispan based for client/server caches
  • no "distributed caching" at the moment - we'll see if there is more demand, and in case it will be Infinispan based too.

cc/ @emmanuelbernard @galderz @tristantarrant

@gwenneg if you want to start working on this, that's awesome! But I would love if you could please focus on local caching, using Caffeine for the first iteration ?

@Sanne Ok, I'll do that.

fyi,

JCache annotations have quirks you should be aware of before using.

  • Mostly incompatible with other JCache features (CacheWriter, CacheLoader, CacheEntryListener, etc).
  • Allows for query storms on a cache miss (@CacheResult is a non-blocking load)
  • Silently creates anonymous, unbounded caches if the cache name was not configured explicitly.

These can be worked around, but may require reimplementing parts of the spec. JCache is useful for integrations but can also be fairly limiting. For application code, I recommend using a native caching library's APIs instead (biased as author of Caffeine) as more straightforward and flexible. Of course, integration into a framework like Hibernate, JCache is nice since any provider can be plugged in for basic support.

hi @ben-manes , great to see you commenting as well!

I totally agree. In fact I tried to push back on JCache during a previous design meeting, and discussed such limitations with @galderz - he's the caching expert on the team: implemented the Hibernate caching layer w/o using JCache but rather using a thin layer from Infinispan code as adapter (and to reuse some welltested code we already had), but mostly based on Caffeine.

But since there seems widespread interest in such annotations for general purpose usage, or perhaps something similarly easy to use, I don't feel like pushing back entirely on this "we want JCache" initiative.

Best outcome would be to find a good compromise: not necessarily constrained by all spec details - at least in first iterations - but using it to possibly advance the standards. Not sure exactly how to get there but those points you mentioned certainly bother me.

Regarding the query storms problem specifically; I haven't had the time to work on this but I was thinking that we should be able to make this a blocking load? Consider we'll base our implementation on Caffeine, I really think that having the ability to swap implementation is a non-goal (especially for such reasons).

thanks!

Thanks @Sanne. I agree with not blocking users from getting their work done, and if that means supporting JCache then that's great. I was mostly meaning to warn users from expecting too much from it, as I think it is mostly bad for application code. That doesn't mean not supporting it here, just perhaps not evangelizing it when added. JCache is great for simple integrations between frameworks.

JCache has an odd design choice where implementation details are explicitly stated within the JavaDoc / GoogleDoc. This means certain decisions that should be provider-specific have to emulate the lead's implementation (directly based on Ehcache). There is a bit of leeway with @CacheResult as it explicit says the steps is Cache#get followed by a compute, but I think that compute could be done in a Cache#invoke without violating the spec (but may fail the TCK due to its brittleness). The request to generalize the spec or strengthen the RI to be atomic CacheResult was rejected (https://github.com/jsr107/RI/issues/45).

There are multiple issues at stake here ranging from the technical to the legal.

First off, I think we should avoid the JCache annotations if possible, as it is unlikely they can be evolved to support additional use cases. We should opt either for a Quarkus-specific solution (low effort, more freedom) or for something more ambitious (Microprofile Caching ?).
As @ben-manes says, we can still support JCache, but only through a compatibility layer rather than having it influence our implementation choices.

Aside from the "locking get" (I also happen to dislike Spring Cache's use of the term "synchronized" here) a useful @Cacheable annotation should also have a read-timeout (as caching may not always be local) as well as encouraging non-blocking patterns (although simply detecting that the annotated method returns a CompletionStage should be enough).

As seen from the comments above, there's a general consensus that we'd want to have annotation-drive n caching for application data, but JCache falls short here. With this in mind, I've created a separate issue (#3306) where we can decide what these annotations should look like, their behaviour and expectations. For #3306, we want to build the minimum set of annotations with the least amount of configuration to enable applications to cache their own data easily.

@gwenneg, since you were starting to work on this issue, I've assigned #3306 to you so that you can direct your efforts in that direction.

Thanks @galderz and thank you all for your advice and ideas. It's really great having so many caching experts involved in this subject!

@gsmet I've created an extension locally with a temp name, but it would be nice if I could rename it with its final name. Do you have any idea about this?

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you!
We are doing this automatically to ensure out-of-date issues does not stay around indefinitely.
If you believe this issue is still relevant please put a comment on it on why and if it truly needs to stay request or add 'pinned' label.

PR #3394 is still open.

Closing this in favor of https://github.com/quarkusio/quarkus/issues/3306 . No need for 2 issues.

Did not notice the other issue. Let's close :-)

N.B. for the record the other issue isn't aiming at JSR-107 compliance. But I'm fine closing this one, as I was recommending against it: as I explained during design meetings, the spec is enforcing several aspects which are not really optimal nor "modern" anymore.

Thanks for the precision, will be useful if someone stumbles upon this particular issue.

Was this page helpful?
0 / 5 - 0 ratings