«Top»

On the following page, we show our example application
can be implemented using Hazelcast in client-server mode.

Overview

Hazelcast’s Native Clients
provide a way to do all Hazelcast operations without being a member of the cluster.
That way, Hazelcast’s existing peer-to-peer mode
can be run on dedicated server hardware, while application servers deploy native clients to
interact with the servers.

hz

As the underlying implementation is the same, Hazelcast’s client-server deployment
has the same properties as the peer-to-peer deployment.

Initialization

The following initialization code creates a Hazelcast Native Client
and configures it programmatically. The server addresses are
hard-coded as localhost:5701 and localhost:5702:

@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
    ClientConfig clientConfig = new ClientConfig();
    clientConfig.getGroupConfig().setName("dev").setPassword("dev-pass");
    clientConfig.addAddress("localhost:5701", "localhost:5702");
    HazelcastInstance client = HazelcastClient.newHazelcastClient(clientConfig);
    ConcurrentMap<String, UserEventList> map = client.getMap("events");
    ServletContext context = servletContextEvent.getServletContext();
    context.setAttribute("map", map);
}

The REST interface loads the Cache the same way as
in the peer-to-peer example:

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

@PostConstruct
@SuppressWarnings("unchecked")
public void init() {
    map = (ConcurrentMap) context.getAttribute(CACHE);
}

Shutdown

@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
    Hazelcast.shutdownAll();
}

Write

@POST
@Path("{user}")
@Consumes(MediaType.APPLICATION_JSON)
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 );
}

Read

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

Dependencies

<dependency>
    <groupId>com.hazelcast</groupId>
    <artifactId>hazelcast</artifactId>
    <version>2.5</version>
</dependency>

<dependency>
    <groupId>com.hazelcast</groupId>
    <artifactId>hazelcast-client</artifactId>
    <version>2.5</version>
</dependency>

How to Run

Server

A script server.sh is included in Hazelcast’s hazelcast-2.5.zip
distribution. However, if the script is run as it is, it will not be
possible to store UserEventList objects on the server, as that class
is defined in the
common JAR of our example application.

Our example code is hosted on GitHub.
The file common/target/common-0.1.jar is created when the example project
built with maven.

Hazelcast’s server.sh needs to be edited, and common/target/common-0.1.jar
must be added to the classpath. After that, Hazelcast’s server instances can be
started with

sh ./server.sh

Client

The clients are run as follows:

Instance 1:

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

Instance 2:

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

The Web interfaces are then available via
http://localhost:8080
and
http://localhost:9090.

Advanced Topics

Apart from the Native Clients shown above, Hazelcast also supports
Lite Members.
Both, native clients and lite members do not store data.
However, lite members are part of the distributed hash table,
i.e. they have a socket connection to every member in the cluster and know which
node is responsable for which key range.

When the number of clients is small, lite members may perform better,
as they can access data much faster. If the number of clients is high
or if the clients are connected through the WAN,
native clients perform better as they do not require so much networking
overhead.

Next

The final page of part 4 of our series shows how our example application
can be implemented using Infinispan in client-server mode: