Where i work, each with we’re assigned to a different tasks. My tasks this week are: test Beehive Webservices (i’ll post about it later) and test Oracle Coherence and Terracota.
I decided to start with Coherence because it really called my attention — it’s a in-memory jcache compliant clustered cache.
I started reading some docs about it and discovered that it can act as an 2nd-level-cache to Hibernate, so why not give a try with grails?
Everything is quite easy:
First, you have to download coherence zip to your machine and extract it. You will have a dir structure like this:
coherence
|– bin
|– doc
|– examples
`– lib
To start an Coherence console, just type bin/coherence.sh (with your JAVA_HOME set). It’ll show a lot of output, but the main thing is:
Services
(
TcpRing{TcpSocketAccepter{State=STATE_OPEN, ServerSocket=192.168.0.2:8088}, Connections=[]}
ClusterService{Name=Cluster, State=(SERVICE_STARTED, STATE_JOINED), Id=0, Version=3.3, OldestMemberId=1}
)
Here it shows the cluster nodes — Coherence will always search for nodes on your machine through network broadcasting. So, if you start another console (on another machine, or on the same, you decide) you’ll see:
Services
(
TcpRing{TcpSocketAccepter{State=STATE_OPEN, ServerSocket=192.168.0.2:8089}, Connections=[]}
ClusterService{Name=Cluster, State=(SERVICE_STARTED, STATE_JOINED), Id=0, Version=3.3, OldestMemberId=1}
)
Map (?):
2008-08-25 21:18:10.026 Oracle Coherence GE 3.3.1/389 (thread=TcpRingListener, member=2): TcpRing: connecting to member 1 using TcpSocket{State=STATE_OPEN, Socket=Socket[addr=/192.168.0.2,port=50602,localport=8089]}
Here Coherence shows that it recognized the other node you started. (BTW on the other console you’ll see a message like this too)
If you type who on any console, coherence will tell you how many machines are on the cluster and who are them:
MasterMemberSet
(
ThisMember=Member(Id=2, Timestamp=2008-08-25 21:18:08.241, Address=192.168.0.2:8089, MachineId=26626, Location=process:30900@rome)
OldestMember=Member(Id=1, Timestamp=2008-08-25 21:16:35.527, Address=192.168.0.2:8088, MachineId=26626, Location=process:30378@rome)
ActualMemberSet=MemberSet(Size=2, BitSetCount=2
Member(Id=1, Timestamp=2008-08-25 21:16:35.527, Address=192.168.0.2:8088, MachineId=26626, Location=process:30378@rome)
Member(Id=2, Timestamp=2008-08-25 21:18:08.241, Address=192.168.0.2:8089, MachineId=26626, Location=process:30900@rome)
)
Now let’s start with the funny part (playing w/ Grails!)
First, you have to put coherence jars on your app — coherence.jar, tangosol.jar and coherence-hibernate.jar — this last one being the one with the 2nd level cache classes.
Then, put on your Datasource.groovy:
hibernate {
cache.use_second_level_cache=true
cache.use_query_cache=true
cache.provider_class='com.tangosol.coherence.hibernate.CoherenceCacheProvider'
show_sql = true
}
The bold part is the main thing — is the hibernate’s 2nd level cache implementation. I recommend you to put the show_sql to true, just to see when a query hits the database.
Then create a file called hibernate-cache-config.xml (ok, the actual name doesn’t really matter…) and put the following content on it: http://pastebin.com/f7c883504
This file contains the configuration on how the cache should be created, replicated and etc.
Now, put
static mapping = {
cache true
}
on the domain classes you want to cache. (this is important — and i didn’t know that, but thanks to Les Hazlewood’s explanation on this thread i know why i need it)
Now, let’s test it!
Fire-up a grails console instance with the following command:
grails -Dtangosol.coherence.cacheconfig=./hibernate-cache-config.xml -Dtangosol.coherence.hibernate.cacheconfig=./hibernate-cache-config.xml console
With this command you set two system variables (coherence uses them) that point to the file we created later.
After typing enter (duh!) you will see a lot of messages about coherence (just like the ones you saw when starting the console) (note: i recommend you not to have any other instance of coherence running when doing these tests). When the coherence finally started, save some instances of your domain class(ess) — i.e.:
import com.tangosol.net.CacheFactory
(1..25).each { new Author(firstName:"${it}", lastName:"${it}", birthday:new Date()-1).save() }
Then run this code on the same console (assuming your domain class is called Author):
import com.tangosol.net.CacheFactory
cache = CacheFactory.getCache(Author.class.name)
Author.get(1)
Author.list()
println "Cache size: ${cache.size()}"
println " ---- Cache Content ---- "
cache.each {k,v ->
println "Key: ${k} -- Value:${v}"
}
return null
On my machine, i see this output:
Hibernate: select author0_.id as id1_0_, author0_.version as version1_0_, author0_.birthday as birthday1_0_, author0_.first_name as first4_1_0_, author0_.last_name as last5_1_0_ from author author0_ where author0_.id=?
Hibernate: select this_.id as id1_0_, this_.version as version1_0_, this_.birthday as birthday1_0_, this_.first_name as first4_1_0_, this_.last_name as last5_1_0_ from author this_
Cache size: 25
---- Cache Content ----
Key: Author#1 -- Value:Item{version=0,freshTimestamp=1219712346919
Key: Author#2 -- Value:Item{version=0,freshTimestamp=1219712346928
Key: Author#3 -- Value:Item{version=0,freshTimestamp=1219712346929
Key: Author#4 -- Value:Item{version=0,freshTimestamp=1219712346930
Key: Author#5 -- Value:Item{version=0,freshTimestamp=1219712346931
Key: Author#6 -- Value:Item{version=0,freshTimestamp=1219712346933
Key: Author#7 -- Value:Item{version=0,freshTimestamp=1219712346934
Key: Author#8 -- Value:Item{version=0,freshTimestamp=1219712346935
Key: Author#9 -- Value:Item{version=0,freshTimestamp=1219712346936
Key: Author#10 -- Value:Item{version=0,freshTimestamp=1219712346938
Key: Author#11 -- Value:Item{version=0,freshTimestamp=1219712346939
Key: Author#12 -- Value:Item{version=0,freshTimestamp=1219712346944
Key: Author#13 -- Value:Item{version=0,freshTimestamp=1219712346945
Key: Author#14 -- Value:Item{version=0,freshTimestamp=1219712346947
Key: Author#15 -- Value:Item{version=0,freshTimestamp=1219712346948
Key: Author#16 -- Value:Item{version=0,freshTimestamp=1219712346949
Key: Author#17 -- Value:Item{version=0,freshTimestamp=1219712346951
Key: Author#18 -- Value:Item{version=0,freshTimestamp=1219712346952
Key: Author#19 -- Value:Item{version=0,freshTimestamp=1219712346955
Key: Author#20 -- Value:Item{version=0,freshTimestamp=1219712346956
Key: Author#21 -- Value:Item{version=0,freshTimestamp=1219712346957
Key: Author#22 -- Value:Item{version=0,freshTimestamp=1219712346960
Key: Author#23 -- Value:Item{version=0,freshTimestamp=1219712346961
Key: Author#24 -- Value:Item{version=0,freshTimestamp=1219712346962
Key: Author#25 -- Value:Item{version=0,freshTimestamp=1219712346963
What this means is that we have all 25 objects on cache! Uhuu!
On the next post….
– Add this to a real web-app
– Create a web interface to show what objects we have on cache and clean it
See you next time.