We’ve been seeing more and more implementations of IPageStore out in the wild for Apache Wicket. The interface basically decides how Wicket will store the Pagemap for your application. The default that ships with Wicket uses DiskPageStore which is an implementation that stores the serialized pages grouped in a single file per pagemap. After reading a wonderful blog post on Letsgetdugg a few days ago: Clustering Wicket for fun and profit!, I decided to take a look at writing an implementation using Hazelcast - an “open source clustering and highly scalable data distribution platform”. The implementation below borrows heavily from Victor. It basically creates a HazelcastInstance in the constructor and then overrides all the methods necessary from AbstractPageStore. Here’s some quick code to put in your app’s Application implementation that will use this new IPageStore:
1
2
3
4
5
@Override
protected ISessionStore newSessionStore() {
return new SecondLevelCacheSessionStore(this,
new HazelcastPageStore("default"));
}
And here’s the code for HazelcastPageStore:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public class HazelcastPageStore extends AbstractPageStore
implements SecondLevelCacheSessionStore.IClusteredPageStore {
private Logger logger = LoggerFactory.getLogger(HazelcastPageStore.class);
private String mapName;
private HazelcastInstance client;
public HazelcastPageStore(String mapName) { this(mapName, null); }
public HazelcastPageStore(String mapName, Config config) {
this.mapName = mapName;
client = Hazelcast.newHazelcastInstance(config);
}
public String getKey(final String sessId, final String pageMapName, final int pageId, final int pageVersion) {
return getKey(sessId, pageMapName, pageId, pageVersion, -1);
}
public String getKey(final String sessId, final String pageMapName, final int pageId, final int pageVersion, final int ajaxVersion) {
String key = sessId + ":" + pageMapName + ":" + pageId + ":" + pageVersion + ":" + ajaxVersion;
if (logger.isDebugEnabled()) {
logger.debug("GetKey: " + key);
}
return key;
}
public String storeKey(final String sessionId, final Page page) {
String key = sessionId + ":" + page.getPageMapName() + ":" + page.getId() + ":" + page.getCurrentVersionNumber() + ":" + (page.getAjaxVersionNumber() - 1);
if (logger.isDebugEnabled()) {
logger.debug("StoreKey: " + key);
}
return key;
}
public boolean containsPage(final String sessionId, final String pageMapName, final int pageId, final int pageVersion) {
return client.getMap(mapName).containsKey(getKey(sessionId, pageMapName, pageId, pageVersion));
}
public void destroy() {
client.shutdown();
}
public <t> Page getPage(final String sessionId, final String pagemap, final int id, final int versionNumber, final int ajaxVersionNumber) {
IMap<string, Page> map = client.getMap(mapName);
return map.get(getKey(sessionId, pagemap, id, versionNumber, ajaxVersionNumber));
}
public void pageAccessed(final String sessionId, final Page page) {
}
public void removePage(final String sessionId, final String pagemap, final int id) {
String key = getKey(sessionId, pagemap, id, 0);
key = key.substring(0, key.lastIndexOf(":"));
IMap<string, Page> map = Hazelcast.getMap(mapName);
for (String k : map.keySet()) {
if (k.startsWith(key)) {
map.remove(k);
}
}
}
public void storePage(final String sessionId, final Page page) {
IMap<string, Page> map = client.getMap(mapName);
map.put(storeKey(sessionId, page), page);
}
public void unbind(final String sessionId) {
IMap<string, Page> map = client.getMap(mapName);
for (String key : map.keySet()) {
if (key.startsWith(sessionId)) {
map.remove(key);
}
}
}
}
Several other IPageStore implementations available:
Let us know if you find any others out in the wild so we can add them here.
Read more