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.

  • Can you try to annotate your CacheListener with @Component anotation? it would enable dependency injection with Autowired – Benjamin Caure Dec 15 '20 at 22:53
  • @BenjaminCaure I've added `@Component` to CacheListener class (the one that implements CacheEventListener), but simpMessagingTemplate is still null, unfortunately. – Thiago Carvalho Dec 15 '20 at 23:08
  • The `CacheListener` isn't controlled by Spring, and as such won't get injected. – M. Deinum Dec 16 '20 at 07:05
  • Thanks for the clarification @M.Deinum, I didn't know that. I've followed the tutorial indicated by Hopey One and it solved the problem. – Thiago Carvalho Dec 17 '20 at 07:44

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,474
  • 3
  • 9