0

I have a spring boot project which serves as a library (packaged jar file) to some other project. I am trying yo configure caffeine cache that will refresh asynchronously after request is made to the service.

pom.xml (includes) :

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
</dependency>

My configuration class :

@EnableCaching
@Configuration
public class CaffeineCacheConfig {

@Bean
public CacheManager cacheManager(){
    CaffeineCacheManager cacheManager = new CaffeineCacheManager("userStories", "features");
    cacheManager.setCaffeine(caffeineCacheBuilder());
    cacheManager.setAllowNullValues(false);
    return cacheManager;
}

Caffeine<Object, Object> caffeineCacheBuilder() {
    return Caffeine.newBuilder()
            .initialCapacity(100)
            .maximumSize(500)
            .refreshAfterWrite(1, TimeUnit.MINUTES)
            .weakKeys()
            .recordStats();
}
}

DAO layer (needs caching here) :

@Component
@EnableCaching
@CacheConfig(cacheNames = {"userStories"})
public class UserStoryDaoImpl implements IUserStoryDao {

@Override
@Cacheable
public List<UserStory> getUserStoriesForProjectAndRelease(UserDto userDto, Set<Integer> reportProjectId, int releaseId) {
    return new ArrayList(); //slow and low performing method that returns a list
}

DAO layer (needs caching here as well) :

@Component
@EnableCaching
@CacheConfig(cacheNames = {"features"})
public class FeatureDaoImpl implements IFeatureDao {

@Override
@Cacheable
public List<Features> geFeaturesForProjectAndRelease(UserDto userDto, Set<Integer> reportProjectId, int releaseId) {
    return new ArrayList(); //slow and low performing method that returns a list
}
}

I am getting below error stack while running this setup:

2020-03-31 16:55:46,020 ERROR web.context.ContextLoader     - Context initialization failed [localhost-startStop-1] {}
java.lang.NullPointerException
    at org.springframework.context.annotation.AutoProxyRegistrar.registerBeanDefinitions(AutoProxyRegistrar.java:62)
    at org.springframework.context.annotation.ConfigurationClassParser.processImport(ConfigurationClassParser.java:385)
    at org.springframework.context.annotation.ConfigurationClassParser.processImport(ConfigurationClassParser.java:377)
    at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:205)
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:164)
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:130)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:287)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:225)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:632)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:461)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:410)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:112)
    at com.intland.codebeamer.context.CodeBeamerContextListener.lambda$contextInitialized$1(CodeBeamerContextListener.java:117)
    at com.intland.codebeamer.context.CodeBeamerContextListener.logExecutionTime(CodeBeamerContextListener.java:148)
    at com.intland.codebeamer.context.CodeBeamerContextListener.contextInitialized(CodeBeamerContextListener.java:117)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4699)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5165)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:743)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:719)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:714)
    at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1125)
    at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1859)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
2020-03-31 16:55:46,070 INFO  codebeamer.context.CodeBeamerContextListener     - Context - Destroyed [localhost-startStop-1] {}
2020-03-31 16:55:46,132 WARN  context.support.XmlWebApplicationContext     - Exception thrown from ApplicationListener handling ContextClosedEvent [localhost-startStop-1] {}
java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: Root WebApplicationContext: startup date [Tue Mar 31 16:55:35 IST 2020]; root of context hierarchy
    at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:347)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:334)
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1051)
    at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:1012)
    at org.springframework.web.context.ContextLoader.closeWebApplicationContext(ContextLoader.java:586)
    at org.springframework.web.context.ContextLoaderListener.contextDestroyed(ContextLoaderListener.java:143)
    at com.intland.codebeamer.context.CodeBeamerContextListener.contextDestroyed(CodeBeamerContextListener.java:128)
    at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4746)
    at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5403)
    at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:743)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:719)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:714)
    at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1125)
    at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1859)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
2020-03-31 16:55:46,132 WARN  context.support.XmlWebApplicationContext     - Exception thrown from LifecycleProcessor on context close [localhost-startStop-1] {}
java.lang.IllegalStateException: LifecycleProcessor not initialized - call 'refresh' before invoking lifecycle methods via the context: Root WebApplicationContext: startup date [Tue Mar 31 16:55:35 IST 2020]; root of context hierarchy
    at org.springframework.context.support.AbstractApplicationContext.getLifecycleProcessor(AbstractApplicationContext.java:360)
    at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1059)
    at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:1012)
    at org.springframework.web.context.ContextLoader.closeWebApplicationContext(ContextLoader.java:586)
    at org.springframework.web.context.ContextLoaderListener.contextDestroyed(ContextLoaderListener.java:143)
    at com.intland.codebeamer.context.CodeBeamerContextListener.contextDestroyed(CodeBeamerContextListener.java:128)
    at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4746)
    at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5403)
    at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:226)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:743)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:719)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:714)
    at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1125)
    at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1859)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

Not sure what is missing in the setup?

djm.im
  • 3,295
  • 4
  • 30
  • 45
Einstein_AB
  • 396
  • 5
  • 22

2 Answers2

1

Start with removing @EnableCaching from @Component classes - keep it only on @Configuration.

Not sure about @CacheConfig, normally you can configure cache name in @Cacheable.

I have previous experience with your idea. The problem here is that refreshing cache needs a method to do the refresh - a method which would produce an up-to-date value based on the key. It's tricky to implement such method when key is based on multiple parameters from the method signature. Also this means that value loading mechanism should be implemented twice: in the annotated method and in the reloader.

stepio
  • 865
  • 2
  • 9
  • 22
0

I have fixed it to add the next line to the application properties:

cache.ttl=60
Procrastinator
  • 2,526
  • 30
  • 27
  • 36