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

New Sample: Spring Boot 3 + Ehcache 3 XML config with Spring Bean Wiring #32

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

mathieucarbou
Copy link
Member

@mathieucarbou mathieucarbou commented Jul 28, 2023

Depends on ehcache/ehcache3#3190

This sample is a PoC for an upcoming spring-boot-ehcache3 (or ehcache3-spring-boot ?) module that will automatically configure Spring Boot Caching with Ehcache / JCache (@EnableCaching), and at the same time allow spring beans to be used within the Ehcache XML configuration.

How to run this sample:

  1. Requires: Java 17
  2. You must first get an API key at https://freecurrencyapi.com/
  3. Build: ./mvnw package
  4. Run: ./target/spring-boot-ehcache-0.0.1-SNAPSHOT.jar --app.freecurrencyapi.key=<your-api-key>
  5. Open your browser at http://localhost:8080/
  6. Execute some currency conversion
  7. Look at the logs below
  8. Look at Spring Boot actuator endpoints at http://localhost:8080/actuator to see the metrics and caches and verify
    that the caching works.

@mathieucarbou mathieucarbou changed the title New Sample: Spring Boot 3 + Ehcache 3 Bean Wiring + JCache XML Config… New Sample: Spring Boot 3 + Ehcache 3 Bean Wiring from Spring + JCache XML Config Jul 28, 2023
@mathieucarbou mathieucarbou self-assigned this Jul 31, 2023
</expiry>
<listeners>
<listener>
<class>com.example.springbootehcache.caching.CacheEventRedirect</class>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a spring beans containing some @Autowire and depending on Spring injection


<cache alias="currencies">
<key-type>java.lang.String</key-type>
<value-type serializer="com.example.springbootehcache.caching.CurrenciesSerializer">java.util.ArrayList</value-type>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The serialiser is a spring beans containing some @Autowire and depending on Spring injection

@ConditionalOnMissingBean(value = org.springframework.cache.CacheManager.class, name = "cacheResolver")
@EnableConfigurationProperties(CacheProperties.class)
@ConditionalOnProperty("spring.cache.jcache.config")
public class EhcachejCacheSpringConfiguration implements BeanClassLoaderAware, BeanFactoryAware {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class would go in a spring-boot-ehcache module and will allow an automatic Ehcache wiring in Spring Boot.

@mathieucarbou mathieucarbou changed the title New Sample: Spring Boot 3 + Ehcache 3 Bean Wiring from Spring + JCache XML Config New Sample: Spring Boot 3 + Ehcache 3 XML config with Spring Bean Wiring Jul 31, 2023
}

private CacheManager createCacheManager(CacheProperties cacheProperties, InstantiatorService delegate) throws IOException {
CachingProvider cachingProvider = getCachingProvider(cacheProperties.getJcache().getProvider());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're in "Ehcache-land" at this point (or we know we're not and can avoid any more work), why not just cast the CachingProvider to a implementation specific type and pass the services that way? Then we could do things in a much safer way rather than having to pass things through a properties object?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are not: here, we do exactly like the spring boot code is doing, which is creating a jsr CacheManager based on a potentially provided and customised CacheProperties, and then customise the created jsr CacheManager.

The only Ehcache related thing is setting this ehcache.service.instantiatorService for the JSR provider implementation.

Spring is providing the config URI and jsr properties. And we cannot call directly Ehcache implementation EhcacheCachingProvider.getCacheManager(uri, configuration, properties) because it would mean we have to duplicate the Ehcahe internal code to parse the configuration from a URI or provide a default one (ConfigSupplier code). And the ConfigSupplier class is not even publicly usable.

@Bean
@ConditionalOnMissingBean
public InstantiatorService instantiatorService() {
return new DefaultInstantiatorService();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me what the right sequence of delegation is here. Right now we're saying:

BeanFactory first, then, if available, the users InstantiatorService bean otherwise the DefaultInstantiatorService.

Would this be better?

The users InstantiatorService bean (if available), otherwise the beanFactory delegating to the DefaultInstantiatorService

Also, what about if the user has tried to override the instantiator service using the Ehcache dependency mechanism? Should it then be:

The users InstantiatorService bean (if available), otherwise the beanFactory delegating to the service found using the Ehcache system?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proposition in the middle makes sense from a spring boot perspective:

  @Bean
  @ConditionalOnMissingBean
  public InstantiatorService instantiatorService() {
    return new SpringBootInstantiatorService();
  }

If a user provides its own InstantiatorService, it will be used (and user is then responsible of the wiring), otherwise we use the spring wired one

If a user tries to override the service in Ehcache and he uses spring boot, I guess Ehcache will complain because it will see 2 instantiator services right ? One from the user, one from spring boot. And this is OK because the user is using Ehcache in a spring boot app so he should provide his instantiator from spring as a normal configured bean.

… + AOP + Metrics + Prometheus + Actuator + Vaadin
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants