Example using CachingEventSourcingRepository with a cache

1,039 views
Skip to first unread message

Viggo Navarsete

unread,
Sep 3, 2013, 2:52:55 PM9/3/13
to axonfr...@googlegroups.com
Hi,

can someone show an example using CachingEventSourcingRepository, including the setup of a cache (Spring wiring..) I see it mentioned in the documentation, but hard to find a concrete example of it (maybe also add it to the documentation when documented here?;) )

Thanks in advance:)

Regards,
Viggo

Allard Buijze

unread,
Sep 4, 2013, 3:12:53 AM9/4/13
to Axon Framework Users
Hi Viggo,

cache configuration is a feature under improvement currently (see http://issues.axonframework.org/youtrack/issue/AXON-81)

This is how you can configure an EhCache using Spring:

    <axon:event-sourcing-repository id="myCachedRepository" cache-ref="myCache" 
                                    aggregate-type="com.mycompany.MyAggregate"/>

    <bean id="myCache" class="net.sf.ehcache.jcache.JCache">
        <constructor-arg>
            <bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
                <property name="cacheName" value="myCacheName"/>
                <!-- whatever properties required for EhCache -->
            </bean>
        </constructor-arg>
    </bean>

Cheers,

Allard


--
You received this message because you are subscribed to the Google Groups "Axon Framework Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to axonframewor...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Viggo Navarsete

unread,
Sep 4, 2013, 4:19:26 AM9/4/13
to axonfr...@googlegroups.com
Hi,

I tried your example, also adding various dependencies to pom.xml, but ended up with this:
"Error creating bean with name 'myCache' defined in class path resource [spring-context.xml]: Unsatisfied dependency expressed through constructor argument with index 1 of type [net.sf.ehcache.jcache.JCacheManager]: Ambiguous constructor argument types - did you specify the correct bean references as constructor arguments?"

from pom.xml:
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache-core</artifactId>
            <version>2.6.6</version>
        </dependency>
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache-jcache</artifactId>
            <version>1.5.0-0.5</version>
        </dependency> 

Any clue?

Allard Buijze

unread,
Sep 4, 2013, 4:43:44 AM9/4/13
to Axon Framework Users
Perhaps you need to do something like 
    <axon:event-sourcing-repository id="testCacheRepository" cache-ref="mockCache" lock-manager="nullLockManager"
                                    aggregate-factory="mockFactory"
                                    event-bus="eventBus" event-store="eventStore" conflict-resolver="conflictResolver">
        <axon:snapshotter-trigger event-count-threshold="50" snapshotter-ref="snapshotter"/>
    </axon:event-sourcing-repository>

    <bean id="myCache" class="net.sf.ehcache.jcache.JCache">
        <constructor-arg>
            <bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
                <property name="cacheName" value="myCacheName"/>
                <property name="cacheManager">
                    <bean class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
                        <!-- ... config -->
                    </bean>
                </property>
                <!-- whatever properties required for EhCache -->
            </bean>
        </constructor-arg>
    </bean>
    
I must have a proper working sample somewhere. When I have time, I will look it up.

Cheers,

Allard

Viggo Navarsete

unread,
Sep 4, 2013, 5:06:54 AM9/4/13
to axonfr...@googlegroups.com
Thanks Allard, then I'll be waiting for an update from you:) Could you also at the same time check the version of the dependencies so they're not the source for problems:)

Cheers,
Viggo

Allard Buijze

unread,
Sep 4, 2013, 5:48:19 AM9/4/13
to Axon Framework Users
This is what I could find in an actual project:

dependencies:
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache-jcache</artifactId>
            <version>1.2</version>
        </dependency>
        <!--Updated from version 2.3.0-->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache-core</artifactId>
            <version>2.5.1</version>
        </dependency>

Spring config:
    <bean id="gameCache" class="net.sf.ehcache.jcache.JCache">
        <constructor-arg>
            <bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
                <property name="cacheName" value="gameCache"/>
                <property name="cacheManager" ref="gameCacheManager"/>
            </bean>
        </constructor-arg>
    </bean>

    <bean id="gameCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="cacheManagerName" value="gameCacheManager"/>
        <property name="configLocation" value="classpath:/gameCache.xml"/>
    </bean>

The repository just references the gameCache bean.

Gamecache.xml:
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         name="gameCacheManager"
         updateCheck="false">

    <diskStore path="java.io.tmpdir"/>

    <defaultCache
            eternal="false"
            timeToLiveSeconds="30000"
            timeToIdleSeconds="300"
            maxElementsInMemory="1000"
            memoryStoreEvictionPolicy="LFU"
            overflowToDisk="false"/>

    <cache
            name="gameCache"
            eternal="false"
            timeToLiveSeconds="30000"
            timeToIdleSeconds="300"
            maxElementsInMemory="10000"
            memoryStoreEvictionPolicy="LFU"
            overflowToDisk="false"/>

</ehcache>

Cheers,

Allard

Viggo Navarsete

unread,
Sep 4, 2013, 7:09:47 AM9/4/13
to axonfr...@googlegroups.com
Thanks Allard!

I applied your example to my application and it worked:) I have a Runner creating a PurchaseOrder with a command, and then update the PurchaseOrder with 4 other command (resulting in a total of 5 events), I loop this 100000 times, and the first time it took 37 seconds, next time it took 55 seconds, then it took 104 second, and then I got this one:
04 sep 2013 13:00:04 ERROR SimpleCommandBus - Processing of a ConfirmTransportVolumCommand resulted in an exception: 
net.sf.ehcache.CacheException: java.io.EOFException
at net.sf.ehcache.store.disk.DiskStorageFactory.retrieve(DiskStorageFactory.java:939)
at net.sf.ehcache.store.disk.Segment.decode(Segment.java:167)
at net.sf.ehcache.store.disk.Segment.put(Segment.java:444)
at net.sf.ehcache.store.disk.DiskStore.put(DiskStore.java:477)
at net.sf.ehcache.store.FrontEndCacheTier.put(FrontEndCacheTier.java:257)
at net.sf.ehcache.Cache.putInternal(Cache.java:1489)
at net.sf.ehcache.Cache.put(Cache.java:1417)
at net.sf.ehcache.Cache.put(Cache.java:1382)
at net.sf.ehcache.jcache.JCache.put(JCache.java:637)
at net.sf.ehcache.jcache.JCache.put(JCache.java:606)
at org.axonframework.eventsourcing.CachingEventSourcingRepository$CacheUpdatingUnitOfWorkListener.afterCommit(CachingEventSourcingRepository.java:152)
at org.axonframework.unitofwork.UnitOfWorkListenerCollection.afterCommit(UnitOfWorkListenerCollection.java:65)
at org.axonframework.unitofwork.DefaultUnitOfWork.notifyListenersAfterCommit(DefaultUnitOfWork.java:230)
at org.axonframework.unitofwork.DefaultUnitOfWork.doCommit(DefaultUnitOfWork.java:145)
at org.axonframework.unitofwork.NestableUnitOfWork.commit(NestableUnitOfWork.java:51)
at org.axonframework.commandhandling.SimpleCommandBus.doDispatch(SimpleCommandBus.java:137)
at org.axonframework.commandhandling.SimpleCommandBus.doDispatch(SimpleCommandBus.java:103)
at org.axonframework.commandhandling.SimpleCommandBus.dispatch(SimpleCommandBus.java:70)
at org.axonframework.commandhandling.gateway.AbstractCommandGateway.sendAndForget(AbstractCommandGateway.java:78)
at org.axonframework.commandhandling.gateway.GatewayProxyFactory$DispatchOnInvocationHandler.invoke(GatewayProxyFactory.java:391)
at org.axonframework.commandhandling.gateway.GatewayProxyFactory$DispatchOnInvocationHandler.invoke(GatewayProxyFactory.java:351)
at org.axonframework.commandhandling.gateway.GatewayProxyFactory$FireAndForget.invoke(GatewayProxyFactory.java:554)
at org.axonframework.commandhandling.gateway.GatewayProxyFactory$NullOnTimeout.invoke(GatewayProxyFactory.java:459)
at org.axonframework.commandhandling.gateway.GatewayProxyFactory$NullOnInterrupted.invoke(GatewayProxyFactory.java:477)
at org.axonframework.commandhandling.gateway.GatewayProxyFactory$WrapNonDeclaredCheckedExceptions.invoke(GatewayProxyFactory.java:434)
at org.axonframework.commandhandling.gateway.GatewayProxyFactory$GatewayInvocationHandler.invoke(GatewayProxyFactory.java:334)
at com.sun.proxy.$Proxy10.send(Unknown Source)
at com.navarsete.stand012.wholesaler.PurchaseOrderRunner.run(PurchaseOrderRunner.java:47)
at com.navarsete.stand012.wholesaler.PurchaseOrderRunner.main(PurchaseOrderRunner.java:30)
Caused by: java.io.EOFException
at java.io.RandomAccessFile.readFully(RandomAccessFile.java:416)
at java.io.RandomAccessFile.readFully(RandomAccessFile.java:394)
at net.sf.ehcache.store.disk.DiskStorageFactory.read(DiskStorageFactory.java:372)
at net.sf.ehcache.store.disk.DiskStorageFactory.retrieve(DiskStorageFactory.java:937)
... 28 more
2055050 in 68 seconds
DETAILS:

So a couple of observations:
1. Using the cache, it's MUCH faster, think I measured the same round without caching and it took nearly 3 minutes! (now 37 seconds, at least the first time).
2. Any clue why it's getting slower and slower, and eventually fails?

Cheers,
Viggo

Viggo Navarsete

unread,
Sep 4, 2013, 7:31:30 AM9/4/13
to axonfr...@googlegroups.com
1st run: 37 seconds
2nd run: 55 seconds
3rd run: 104 seconds
4th run: crash
5th run: 89 seconds
6th run: 74 seconds
7th run: crash

Allard Buijze

unread,
Sep 4, 2013, 9:02:51 AM9/4/13
to Axon Framework Users
Hi Viggo,

I notice that you're using disk storage for the cache. That kind of beats the purpose of the cache. When you store information on disk, you're generally better off using snapshots.
Since the disk store seems to be running out of disk space, what kind of information do you store in your aggregate? Is there a list in there getting bigger? That might explain the times for storing the data becoming longer (since it needs to serialize more data each time).

Cheers,

Allard


--

Viggo Navarsete

unread,
Sep 4, 2013, 3:21:52 PM9/4/13
to axonfr...@googlegroups.com
Thanks for feedback and advices Allard:)

I'm still a newbie to CQRS and Axon in general, so all best practices are highly appreciated:)

Do you mean to have both a cache and a snapshotter applied  to the event sourcing repository, like this:

   <axon:event-sourcing-repository id="purchaseOrderRepository" 
                                    aggregate-type="com.foo.PurchaseOrder"
                                    event-bus="eventBus"
                                    event-store="eventStore"
                                    cache-ref="myCache">
        <axon:snapshotter-trigger event-count-threshold="50" snapshotter-ref="snapshotter"/>
    </axon:event-sourcing-repository>
    <bean id="myCache" class="net.sf.ehcache.jcache.JCache">
        <constructor-arg>
            <bean class="org.springframework.cache.ehcache.EhCacheFactoryBean">
                <property name="cacheName" value="myCache"/>
                <property name="cacheManager" ref="myCacheManager"/>          
                <!-- whatever properties required for EhCache -->
            </bean>
        </constructor-arg>
    </bean>
    
    <bean id="myCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="cacheManagerName" value="myCacheManager"/>
        <property name="configLocation" value="classpath:/myCache.xml"/>
    </bean>    
    
    <bean id="snapshotter" class="org.axonframework.eventsourcing.SpringAggregateSnapshotter">
        <property name="eventStore" ref="eventStore"/>
        <property name="executor" ref="taskExecutor"/>
    </bean>

    <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
        <property name="corePoolSize" value="2"/>
        <property name="maxPoolSize" value="5"/>
        <property name="waitForTasksToCompleteOnShutdown" value="true"/>
    </bean> 

Questions:
1. Since each aggregate (PurchaseOrder) will have at most 5 events, what would be best values to put on the different configuration elements?
2. Should I *only* have a snapshotter, and not a cache?
3. About caching...currently writing the cache to a file, I feel you suggest it should be stored in-memory instead, how to do it?


Thanks in advance:)

bui...@gmail.com

unread,
Sep 4, 2013, 3:37:43 PM9/4/13
to axonfr...@googlegroups.com
Hi Viggo,

if you have aggregate that live for a longer period of time (persisting hundreds of events), a snapshotter is really recommended. The threshold that suits your application best is something you should find out using load tests. A couple of hundred events is generally fine. 

A cache is recommended when aggregates are subject to periods of high activity. Since your aggregate can be easily loaded from disk using the snapshot, you don't want the cache to store to disk. Just set overflowToDisk to false in your ehcache config. Check out the ehcache config for exactly how to configure your cache. 

If your aggregate has at most 5 events, you might not need either cache nor snapshotter. Loading the aggregate from 4 events will not give you a tremendous latency. If all 5 events happen in a very short amount of time, you could consider using a cache for improved performance or latency reduction.

Cheers,

Allard

Viggo Navarsete

unread,
Sep 4, 2013, 3:48:18 PM9/4/13
to axonfr...@googlegroups.com
Thanks Allard, I will play with your input later tonight:)

Deepak Gupta

unread,
Oct 6, 2017, 5:50:55 AM10/6/17
to Axon Framework Users
Hi 

Is there any way to use hazelcast for cache in CachingEventSourcingRepository?

Thanks
Deepak

Szymon Dembek

unread,
Oct 10, 2017, 5:31:25 AM10/10/17
to Axon Framework Users
Hi,

I'm running an Axon 3 based app on production with Hazelcast as an aggregate cache + I use Hazelcast distributed locks for locking the aggregate - this way I can run multiple instances of the same Axon app without dealing with distributed command bus at all.

Let me know if you need any help or code snippets regarding the use of Hazelcast.

Szymon

Deepak Gupta

unread,
Oct 13, 2017, 2:16:42 AM10/13/17
to Axon Framework Users
Hi Szymon,

From Axon Documentation, i came to know about jCache adapter. I am trying to use hazelcast as jcache cache provider. Still no luck yet. It would be great if you share the working code snippet or do the help. 

Thanks
Deepak Gupta
Reply all
Reply to author
Forward
0 new messages