0

I'm using Ehcache as buffer to pass data for all the clients connected to a WebSocket(Spring).

CacheEventListener implementation:

public class CacheListener implements CacheEventListener<ArrayList, MeasurementPoint> {

    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate; //<-- This is null at runtime

    @Override
    public void onEvent(CacheEvent<? extends ArrayList, ? extends MeasurementPoint> cacheEvent) {
        simpMessagingTemplate.convertAndSend("/topic/measurementsPoints", cacheEvent.getNewValue());
    }
}

Ehcache configuration xml:

config
        xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
        xmlns='http://www.ehcache.org/v3'
        xsi:schemaLocation="
            http://www.ehcache.org/v3
            http://www.ehcache.org/schema/ehcache-core-3.7.xsd">
    <!-- Default cache template -->
    <cache-template name="default">
        <resources>
            <heap>1000</heap>
            <offheap unit="MB">10</offheap>
        </resources>
    </cache-template>

    <cache alias="measurementsCache" uses-template="default">
        <key-type>java.util.ArrayList</key-type>
        <value-type>br.com.petrobras.risersupervisory.model.MeasurementPoint</value-type>
        <listeners>
            <listener>
                <class>br.com.petrobras.risersupervisory.framework.CacheListener</class>
                <event-firing-mode>ASYNCHRONOUS</event-firing-mode>
                <event-ordering-mode>UNORDERED</event-ordering-mode>
                <events-to-fire-on>CREATED</events-to-fire-on>
                <events-to-fire-on>UPDATED</events-to-fire-on>
            </listener>
        </listeners>
    </cache>
</config>

I've tried to follow some tutorials, but all of them use a log library or System.out.println inside the CacheEventListener implementation.

Is there any way I can autowire a @Service(Spring) inside CacheEventListener? Is this implementation wrong? I could not find a single example of people using @Autowired inside CacheEventListener.

Obs: Not just SimpMessagingTemplate is null during runtime. I've tried autowire a custom class too and the result was the same.

Obs2: After searching for spring boot logs, I believe CacheEventListener is been binded to the cache before spring boot finishes loading. Not sure if this is the problem.

1 Answers1

1

Obs2: After searching for spring boot logs, I believe CacheEventListener is been binded to the cache before spring boot finishes loading. Not sure if this is the problem.

This hints at your issue, you can't inject spring beans into non-spring managed object instances. You can use a simple class to give you static access to the spring context to load a bean described here.

@Component
public class SpringContext implements ApplicationContextAware {
 
private static ApplicationContext context;
 
  public static <T extends Object> T getBean(Class<T> beanClass) {
    return context.getBean(beanClass);
  }
 
  @Override
  public void setApplicationContext(ApplicationContext context) throws BeansException 
  {
     
    // store ApplicationContext reference to access required beans later on
    SpringContext.context = context;
  }
}

SpringContext.getBean(YourBean.class);

You may still have an issue if you attempt to do this before the spring context is initialised. It's worth mentioning that spring-boot supports ehcache 3.x via the org.springframework.boot:spring-boot-starter-cache dependency. I don't know if this suits your purpose but it may be easier if ehcache is integrated with spring.

Hopey One
  • 1,681
  • 5
  • 10