Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make cache2k-api and cache2k-core OSGi compatible #83

Open
cruftex opened this issue Apr 3, 2018 · 8 comments
Open

Make cache2k-api and cache2k-core OSGi compatible #83

cruftex opened this issue Apr 3, 2018 · 8 comments
Labels
Milestone

Comments

@cruftex
Copy link
Member

@cruftex cruftex commented Apr 3, 2018

In the event of reorganizing the jar files (#80), it would make sense to have proper OSGi bundle information on the api and impl jar. The problem is that the API needs to find its implementation. I did some experiments via the SPI mediator OSGi support, but not luck.

For OSGi users cache2k-osgi-all was available which bundled together the API and application classes. With development of 2.0 I am dropping this, to avoid the additional jars claiming the same packages.

Maybe someone with OSGi experience can take a look?

@cruftex cruftex added this to the v1.6 milestone Jul 17, 2018
@cruftex cruftex changed the title Make cache2k-api and cache2k-impl OSGi compatible Make cache2k-api and cache2k-core OSGi compatible Aug 23, 2018
@cruftex cruftex removed this from the v1.6 milestone Sep 17, 2018
@cruftex cruftex added this to the v2.x milestone Oct 13, 2020
@cruftex cruftex added the help wanted label Oct 13, 2020
cruftex added a commit that referenced this issue Oct 13, 2020
@roggenbrot
Copy link

@roggenbrot roggenbrot commented Oct 27, 2020

Which OSGI SPI implementation did you use? Apache Aries?

@cruftex
Copy link
Member Author

@cruftex cruftex commented Oct 27, 2020

You can find the OSGi bundle and tests used for cache2k 1.4 and 1.6 here:
https://github.com/cache2k/cache2k/tree/service-1.4/cache2k-osgi-all
https://github.com/cache2k/cache2k/tree/service-1.4/test-osgi

I didn't experiment with Aries.

Maybe the bnd SPI annotations are worth a try:
https://bnd.bndtools.org/chapters/240-spi-annotations.html

@roggenbrot
Copy link

@roggenbrot roggenbrot commented Oct 28, 2020

Bnd tools will just generate the manifest entries for you (Require-Capability, Provide-Capability), but you will still need a implementation for the OSGi ServiceLoader Mediator specification, which is not supported out of the box on most OSGI frameworkx (Felix, Equinox).

The only implementation I know is Apache Aries Spy-Fly.

This is also the reason why ServiceLoader are not very "popular" in the OSGI world, since they need additional installed bundles and trying to solve the same problems as OSGI, only worse.

That's the reason why most of the people I know working with OSGI try to avoid them.

I've took a quick look at the code, but since caching is not my sweet spot, I don't know if all the things are required the way they are currently implemented (e.g. ServiceLoader in static initalizer).

Problem is, that some of them don't play nice with OSGI the way they current are if you really want to have api/core as own bundles (with own classloaders)

@cruftex
Copy link
Member Author

@cruftex cruftex commented Oct 28, 2020

@roggenbrot Thanks for you input!

Problem is, that some of them don't play nice with OSGI the way they current are if you really want to have api/core as own bundles (with own classloaders)

That's not the intention. Basically, api, core, and the extensions jmx, xml, jcache, micrometer would all have the same lifetime, and are singletons.

I've took a quick look at the code, but since caching is not my sweet spot, I don't know if all the things are required the way they are currently implemented (e.g. ServiceLoader in static initalizer).

With the service loader its possible to enable a feature automatically when the jar is present. When cache2k-config is added the cache looks for a configuration file cache2k.xml. Maybe that works for OSGi, it actually can use a classloader provided by the application.

To play well with JPMS/JigSaw I separated config and JMX, so cache2k-core only depends on core java.

The service loader is used in the static initializer for Graal support. Graal executes the static initializer during image build and saves a heap image as well.

Options I see at the moment:

  • Drop the separate API jar and combine core and api and add bundle descriptors
  • Keep existing jars, but provide a cache2k-osgi-all for OSGi users which bundles together everything.
    The bundle would contain config and JMX as well. We had that approach before. I don't have any feedback
    whether somebody used that actually.
  • and/or Reducue service loader usage
  • and/or use OSGi service location when available instead of service loader

I think its best to wait until somebody really wants to use cache2k version 2 in their OSGi project and then see about their requirements.

@cruftex
Copy link
Member Author

@cruftex cruftex commented Oct 28, 2020

Keep existing jars, but provide a cache2k-osgi-all for OSGi users which bundles together everything.
The bundle would contain config and JMX as well. We had that approach before. I don't have any feedback
whether somebody used that actually.

Another idea: Since the cache2k modules are more fine grain then a bundle, maybe it would be more natural that every OSGi project builds a specific cache2k bundle with the needed features. And here we would just provide a template/example for that.

@roggenbrot
Copy link

@roggenbrot roggenbrot commented Oct 29, 2020

The service loader is used in the static initializer for Graal support. Graal executes the static initializer during image build and saves a heap image as well.

Mmmm ok. I'm not familar with Graal or AOT. But the static initializer makes a OSGI service approach more or less impossible.

I've created a fork and changed the code to use services instead of service loader in OSGI environments. It's just a quick rewrite and a lot of things are missing (Thread safety, Null safety .....) and i haven't run any tests but I think it should work this way.

master...roggenbrot:83-osgi-compatibility

Drop the separate API jar and combine core and api and add bundle descriptors

Should it be possible for others to implement their own Cache2kCoreProvider? If not, separate bundles are rocket science (Just my 5 cents).

If this should be possible, have you ever thought about what should happen if there are more then one registered Cache2kCoreProvider implementations?

Sometimes multiple versions of the same jar/bundles are deployed in OSGI environments and imported via semantic version imports.

Sometimes it's quiet handy to use a newer version of a library in one bundle without refactoring other bundles, that still depends on the old version (or without package the newer version into the jar.)

So in OSGI environments it's possible to have multiple Cache2kCoreProvider services, even without a custom Cache2kCoreProvider implementation.

Or what about multiple implementations of Cache2kCoreProvider in ServiceLoader environments?
Isn't it coincidence which available implementation the service loader will use (last, first ....)?. Is the order on every start of the application the same?

I'm not familiar with ServiceLoader, but in OSGI start order of bundles are not guaranteed as long as you don't add BundleDependency or use start levels, which most people try to (and should) avoid.

@cruftex
Copy link
Member Author

@cruftex cruftex commented Oct 31, 2020

@roggenbrot Cool, thanks for the example code!

If this should be possible, have you ever thought about what should happen if there are more then one registered Cache2kCoreProvider implementations?
Or what about multiple implementations of Cache2kCoreProvider in ServiceLoader environments?

About the separate API, you find some thoughts here:
#80 (comment)

Once there is a need for different providers, we can think how to resolve conflicts.

"The API finds core provider" seems pretty straight forward. Probably, the extensions get tricky.

cache2k-config needs to find the configuration file cache2k.xml for the respective user. There could be different ones
in an OSGi environment. I pass on the classloader from CacheManager.getInstance(classloader). Not sure whether this is sufficient and expected like this for OSGi users.

For cache2k-jmx I'd actually like to enable registering JMX beans, if the jar is included. However, in an OSGi environment there might be multiple cache users one depending on JMX and others not. The bundle would be always there. So enabling JMX once the bundle is loaded is wrong. How to resolve this? Maybe check whether the extension is in the user/application classpath?

@cruftex
Copy link
Member Author

@cruftex cruftex commented Nov 2, 2020

For cache2k-jmx I'd actually like to enable registering JMX beans, if the jar is included.

BTW: I needed to let that sit for a while. I decided now that a feature, like JMX support, needs to be enabled explicitly, which means there is no automatism when the jar is present. So I can get rid of most service loader usage in the extension jars.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants