The local Hazelcast example
shown in part 2
implemented a local cache for a single Tomcat instance.

This section shows how the application can be extended to provide a
peer-to-peer-based shared cache among multiple Tomcat instances.

As it turns out, the Hazelcast application can be run in peer-to-peer
mode without any configuration or code changes

Hazelcast uses UDP multicast automatically to detect peers, and maintains
a Distributed Hash Table. The peer-to-peer
architecture allows for atomic operations, which means that the atomic
ConcurrentMap operations in the distributed scenario works as well as in the
local scenario

As new members join the network, the cluster will re-distribute the keys
such that eventually every member in the cluster will own almost same number
of partitions, and almost same number of entries. Also eventually every member
will know the owner of each partition
(and each key)


Initialization is the same as in the local cache example:

public void contextInitialized(ServletContextEvent servletContextEvent) {
    Config cfg = new Config();
    HazelcastInstance instance = Hazelcast.newHazelcastInstance(cfg);
    ConcurrentMap<String, UserEventList> map = instance.getMap("events");
    ServletContext context = servletContextEvent.getServletContext();
    context.setAttribute(CACHE, map);

Also, the configuration in hazelcast.xml remains the same:

<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config-2.1.xsd"
    <map name="events">
        <max-size policy="cluster_wide_map_size">1000</max-size>

As the Hazelcast cache implements ConcurrentMap, the REST interface
initialization does not need to be changed:

// ...
private ServletContext context;
private ConcurrentMap<String, UserEventList> map;

public void init() {
    map = (ConcurrentMap) context.getAttribute(CACHE);


public void contextDestroyed(ServletContextEvent servletContextEvent) {


Hazelcast’s distributed ConcurrentMap provides atomic and consistent updates
in a peer-to-peer environment:

public void appendEvent(@PathParam("user") String user, String msg) {
    boolean success;
    map.putIfAbsent(user, UserEventList.emptyList());
    do {
        UserEventList oldMsgList = map.get(user);
        UserEventList newMsgList = UserEventList.append(oldMsgList, msg);
        success = map.replace(user, oldMsgList, newMsgList);
    while ( ! success );


public List<String> searchByUser(@PathParam("user") String user) {
    UserEventList result = map.get(user);
    if ( result == null ) {
        return new ArrayList<>();
    return result.getMessages();



How To Run

Our example code is hosted on GitHub.
The project can be run with maven:

Instance 1:

mvn tomcat7:run-war -pl part03.hazelcast -am verify -Dmaven.tomcat.port=8080

Instance 2:

mvn tomcat7:run-war -pl part03.hazelcast -am verify -Dmaven.tomcat.port=9090

The Web interface is then accessible via

Advanced Usages

In Hazelcast’s Distributed Hash Table, for each key there is a responsible peer.
Hazelcast uses this infrastructure to implement functionality that goes beyond
simple caching:

  • Hazelcast provides a publish/subscribe messaging infrastructure.
  • Hazelcast provides a distributed computing infrastructure, where each
    peer processes the values it’s responsible for.

See the Hazelcast documentation
for more info.


The final page of part 3 of our series will introduce peer-to-peer clustering with Infinispan: