- The Weather Application
- Initializing the CacheManager
- Putting stuff in the cache
- Making entries expire
- Configuring the cache
- Clustering the application
- Listen to changes in the cluster
- Listen to changes in the cache
- Grouping entries together
- Temperature averages with streams
- Declarative configuration
The Weather App
In this step we will unleash the power of Infinispan's clustering, showing how it can be used to share data among multiple nodes. These nodes can either be on the same physical host, or running in containers or on dedicated VMs or on separate machines. Obviously, for the purposes of this tutorial, running all nodes on the same host is easiest since it doesn't require messing around with networks and firewalls. To achieve this, just launch the application from separate terminal instances. For best results use a terminal which supports vertical splitting (such as Tilix on Linux, iTerm2 on OSX or ConEmu on Windows).
In order to turn a CacheManager into a clustered one, we need to supply a special "global" configuration to it with an enabled transport:
We went the easy route by using the convenience defaultClusteredBuilder() method, but we can achieve the same result by constructing a plain GlobalConfigurationBuidler and tweaking the necessary parameters. Making the CacheManager clustered is not enough: we also want a clustered cache. For this example we will use a distributed synchronous cache with two owners (the default), by changing the default cache configuration:
= preserve do :escaped GlobalConfigurationBuilder global = GlobalConfigurationBuilder.defaultClusteredBuilder(); global.transport().clusterName("WeatherApp"); cacheManager = new DefaultCacheManager(global.build());
The entries will be distributed among the cluster members according to the hash of their keys. Since we asked for two owners, each entry will have a primary owner and a backup owner.
= preserve do :escaped config.clustering().cacheMode(CacheMode.DIST_SYNC);
Since the entries we will be inserting will need to be transferred between the nodes over the network, we need to make sure both keys and values can be serialized with the default Infinispan marshaller - ProtoStream. As the Cache utilise a String for the key, we don't have to do anything for the key as Strings are supported natively by ProtoStream. For the value, LocationWeather, it's necessary to annotate the class with @ProtoField annotations, and generate a SerializationContextInitializer implementation, which is then registered with the GlobalConfigurationBuidler.
It is now time to fire up your multiple terminals and try this for yourself:
= preserve do :escaped serialization().addContextInitializers(new SerializationContextInitializerImpl());
Make sure you start the second instance soon after the first one has started, because we have not told either instance to "wait" for the other. While the end result will be similar to the previous run (obviously multiplied by two) you will see some extra logging related to the node discovery. We want to control this behaviour, so we'll be looking at listeners in the next step.
= preserve do :escaped $ git checkout -f step-5 $ mvn clean package exec:exec # from terminal 1 $ mvn exec:exec # from terminal 2