Open Gitter Chat

Microservices

Hazelcast® In-Memory Data Grid (IMDG) can be used as the backbone of a Microservices architecture. Hazelcast IMDG® is a simple, single JAR file with no external dependencies.

One of the core values of Hazelcast from its inception was simplicity and ease of use, and that still exists today. When you move an application or system into a distributed environment, having a simple and configurable backbone makes the task a lot easier.

Hazelcast is a library. Libraries are easier to use and understand enabling the development process to be more efficient. This simplicity and ease of use is a hallmark of Hazelcast and the reason it adapts well to the Microservices architecture.

Hazelcast IMDG is highly scalable (e.g. IMap and JCache). Hazelcast also supports other standard Java standard Collections such as Lists, Sets, Queues and some other constructs such as Topics and Ringbuffers, that can be easily leveraged for inter-process messaging. All of these attributes can offer functionality that is highly desirable within a Microservices platform.

Hazelcast IMDG can be deployed two ways:

  1. Embedded, where you add the JAR to your application and the Hazelcast Member instance is embedded in your application.
  2. Client-Server, where Hazelcast is run on its own. Here you can run Hazelcast from the command line, a Docker container or a cloud deployment such as AWS and Azure.

Code Examples

Vertx

Java

<!--mep-nl-->import io.vertx.core.*;<!--mep-nl-->import io.vertx.core.http.*;<!--mep-nl-->import io.vertx.core.shareddata.AsyncMap;<!--mep-nl-->import io.vertx.core.spi.cluster.ClusterManager;<!--mep-nl-->import io.vertx.spi.cluster.hazelcast.HazelcastClusterManager;<!--mep-nl--><!--mep-nl-->import java.util.Optional;<!--mep-nl-->import java.util.function.Consumer;<!--mep-nl--><!--mep-nl-->public class VertxExample {<!--mep-nl--><!--mep-nl-->   public static void main(String[] args) {<!--mep-nl--><!--mep-tab-->   ClusterManager clusterManager = new HazelcastClusterManager();<!--mep-nl--><!--mep-tab-->   VertxOptions options = new VertxOptions().setClusterManager(clusterManager);<!--mep-nl--><!--mep-nl--><!--mep-tab-->   Vertx.clusteredVertx(options, res -> {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   if (res.succeeded()) {<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   Vertx vertx = res.result();<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   vertx.deployVerticle(new Server());<!--mep-nl--><!--mep-tab--><!--mep-tab-->   }<!--mep-nl--><!--mep-tab-->   });<!--mep-nl-->   }<!--mep-nl--><!--mep-nl-->   public static class Server extends AbstractVerticle {<!--mep-nl--><!--mep-tab-->   @Override<!--mep-nl--><!--mep-tab-->   public void start() throws Exception {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   HttpServer httpServer = vertx.createHttpServer();<!--mep-nl--><!--mep-tab--><!--mep-tab-->   httpServer.requestHandler(req -> {<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   String key = req.getParam("key");<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   req.response().setChunked(true);<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   switch (req.method()) {<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   case GET:<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   map("my-map", map -> map.get(key, response(req)));<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   break;<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   case POST:<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   case PUT:<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   map("my-map", map -> map.put(key, req.getParam("value"), response(req)));<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   }<!--mep-nl--><!--mep-tab--><!--mep-tab-->   });<!--mep-nl--><!--mep-tab--><!--mep-tab-->   httpServer.listen(8080);<!--mep-nl--><!--mep-tab-->   }<!--mep-nl--><!--mep-nl--><!--mep-tab-->   private <T> Handler<AsyncResult<T>> response(HttpServerRequest req) {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   return res -> {<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   HttpServerResponse response = req.response();<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   if (res.succeeded()) response = response.setStatusCode(200).write(<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   Optional.ofNullable(res.result()).map(v -> v.toString()).orElse("null"));<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   else response = response.setStatusCode(500).write(res.cause().toString());<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   response.end();<!--mep-nl--><!--mep-tab--><!--mep-tab-->   };<!--mep-nl--><!--mep-tab-->   }<!--mep-nl--><!--mep-nl--><!--mep-tab-->   private void map(String mapName, Consumer<AsyncMap<String, String>> consumer) {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   vertx.sharedData().<String, String> getClusterWideMap(mapName, res -> {<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   if (res.succeeded()) consumer.accept(res.result());<!--mep-nl--><!--mep-tab--><!--mep-tab-->   });<!--mep-nl--><!--mep-tab-->   }<!--mep-nl-->   }<!--mep-nl-->}<!--mep-nl-->

Kotlin

<!--mep-nl-->import io.vertx.core.*<!--mep-nl-->import io.vertx.core.http.*<!--mep-nl-->import io.vertx.core.shareddata.AsyncMap<!--mep-nl-->import io.vertx.spi.cluster.hazelcast.HazelcastClusterManager<!--mep-nl--><!--mep-nl-->fun main(args: Array<String>) {<!--mep-nl-->   val clusterManager = HazelcastClusterManager()<!--mep-nl-->   val vertxOptions = VertxOptions().apply { this.clusterManager = clusterManager }<!--mep-nl--><!--mep-nl-->   Vertx.clusteredVertx(vertxOptions) { res -><!--mep-nl--><!--mep-tab-->   res.result().deployVerticle(Server())<!--mep-nl-->   }<!--mep-nl-->}<!--mep-nl--><!--mep-nl-->class Server : AbstractVerticle() {<!--mep-nl-->   override fun start() {<!--mep-nl--><!--mep-tab-->   vertx.createHttpServer().requestHandler { req -><!--mep-nl--><!--mep-tab--><!--mep-tab-->   val key = req.getParam("key")<!--mep-nl--><!--mep-tab--><!--mep-tab-->   req.response().isChunked = true<!--mep-nl--><!--mep-tab--><!--mep-tab-->   when(req.method()) {<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   HttpMethod.GET -><!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   map("my-map") { it.get(key, response(req)) }<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   HttpMethod.POST, HttpMethod.PUT -><!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   map("my-map") { it.put(key, req.getParam("value"), response(req)) }<!--mep-nl--><!--mep-tab--><!--mep-tab-->   }<!--mep-nl--><!--mep-tab-->   }.listen(8080)<!--mep-nl-->   }<!--mep-nl--><!--mep-nl-->   fun <T> response(req: HttpServerRequest): Handler<AsyncResult<T>> = Handler {<!--mep-nl--><!--mep-tab-->   val (statusCode, body) = if (it.succeeded()) 200 to it.result() else 500 to it.cause()<!--mep-nl--><!--mep-tab-->   req.response().setStatusCode(statusCode).write(body.toString()).end()<!--mep-nl-->   }<!--mep-nl--><!--mep-nl-->   fun map(mapName: String, consumer: (AsyncMap<String, String>) -> Unit) =<!--mep-nl--><!--mep-tab--><!--mep-tab-->   vertx.sharedData().getClusterWideMap<String, String>(mapName) { if (it.succeeded()) consumer(it.result()) }<!--mep-nl--><!--mep-nl-->

JavaEE / Microprofile

<!--mep-nl-->import fish.payara.cdi.jsr107.impl.NamedCache;<!--mep-nl-->import fish.payara.micro.PayaraMicro;<!--mep-nl-->import org.jboss.shrinkwrap.api.ShrinkWrap;<!--mep-nl-->import org.jboss.shrinkwrap.api.exporter.ZipExporter;<!--mep-nl-->import org.jboss.shrinkwrap.api.spec.WebArchive;<!--mep-nl--><!--mep-nl-->import javax.cache.Cache;<!--mep-nl-->import javax.inject.*;<!--mep-nl-->import javax.ws.rs.*;<!--mep-nl-->import javax.ws.rs.core.Application;<!--mep-nl-->import java.io.InputStream;<!--mep-nl-->import java.util.*;<!--mep-nl--><!--mep-nl-->@Path("/")<!--mep-nl-->@Singleton<!--mep-nl-->@ApplicationPath("/")<!--mep-nl-->public class JavaEEHazelcast extends Application {<!--mep-nl--><!--mep-nl-->   public static void main(String[] args) throws Exception {<!--mep-nl--><!--mep-tab-->   InputStream inputStream = ShrinkWrap.create(WebArchive.class)<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   .addClass(JavaEEHazelcast.class)<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   .addAsResource("META-INF/beans.xml")<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   .as(ZipExporter.class)<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   .exportAsInputStream();<!--mep-nl--><!--mep-nl--><!--mep-tab-->   PayaraMicro.bootstrap().deploy("cache", inputStream);<!--mep-nl-->   }<!--mep-nl--><!--mep-nl-->   @Override<!--mep-nl-->   public Set<Class<?>> getClasses() {<!--mep-nl--><!--mep-tab-->   Set<Class<?>> classes = new HashSet<>();<!--mep-nl--><!--mep-tab-->   classes.add(JavaEEHazelcast.class);<!--mep-nl--><!--mep-tab-->   return classes;<!--mep-nl-->   }<!--mep-nl--><!--mep-nl-->   @Inject<!--mep-nl-->   @NamedCache(cacheName = "my-cache")<!--mep-nl-->   private Cache<String, String> cache;<!--mep-nl--><!--mep-nl-->   @GET<!--mep-nl-->   @Produces("text/plain")<!--mep-nl-->   public String get(@QueryParam("key") String key) {<!--mep-nl--><!--mep-tab-->   String value = cache.get(key);<!--mep-nl--><!--mep-tab-->   return value == null ? "null" : value;<!--mep-nl-->   }<!--mep-nl--><!--mep-nl-->   @POST<!--mep-nl-->   @Produces("text/plain")<!--mep-nl-->   public void post(@QueryParam("key") String key, @QueryParam("value") String value) {<!--mep-nl--><!--mep-tab-->   put(key, value);<!--mep-nl-->   }<!--mep-nl--><!--mep-nl-->   @PUT<!--mep-nl-->   @Produces("text/plain")<!--mep-nl-->   public void put(@QueryParam("key") String key, @QueryParam("value") String value) {<!--mep-nl--><!--mep-tab-->   cache.put(key, value);<!--mep-nl-->   }<!--mep-nl-->}<!--mep-nl-->

SpringBoot

Java

<!--mep-nl-->package com.hazelcast.bootiful;<!--mep-nl--><!--mep-nl-->import com.hazelcast.config.Config;<!--mep-nl-->import com.hazelcast.config.EntryListenerConfig;<!--mep-nl-->import com.hazelcast.config.XmlConfigBuilder;<!--mep-nl-->import com.hazelcast.core.EntryEvent;<!--mep-nl-->import com.hazelcast.core.HazelcastInstance;<!--mep-nl-->import com.hazelcast.core.IMap;<!--mep-nl-->import com.hazelcast.map.listener.EntryAddedListener;<!--mep-nl-->import com.hazelcast.map.listener.EntryRemovedListener;<!--mep-nl-->import com.hazelcast.map.listener.EntryUpdatedListener;<!--mep-nl-->import com.hazelcast.map.listener.MapListener;<!--mep-nl-->import lombok.extern.slf4j.Slf4j;<!--mep-nl-->import org.springframework.beans.factory.annotation.Autowired;<!--mep-nl-->import org.springframework.boot.SpringApplication;<!--mep-nl-->import org.springframework.boot.autoconfigure.SpringBootApplication;<!--mep-nl-->import org.springframework.cache.annotation.EnableCaching;<!--mep-nl-->import org.springframework.context.annotation.Bean;<!--mep-nl-->import org.springframework.stereotype.Component;<!--mep-nl-->import org.springframework.web.bind.annotation.PathVariable;<!--mep-nl-->import org.springframework.web.bind.annotation.RequestMapping;<!--mep-nl-->import org.springframework.web.bind.annotation.RequestParam;<!--mep-nl-->import org.springframework.web.bind.annotation.RestController;<!--mep-nl--><!--mep-nl-->import static org.springframework.web.bind.annotation.RequestMethod.*;<!--mep-nl--><!--mep-nl-->@SpringBootApplication<!--mep-nl-->@EnableCaching<!--mep-nl-->@Slf4j<!--mep-nl-->public class MicroserviceApplication {<!--mep-nl--><!--mep-nl-->   @Bean<!--mep-nl-->   public Config getConfig(MapListener listener) {<!--mep-nl--><!--mep-tab-->   final Config config = new XmlConfigBuilder().build();<!--mep-nl--><!--mep-tab-->   EntryListenerConfig listenerConfig = new EntryListenerConfig();<!--mep-nl--><!--mep-tab-->   listenerConfig<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   .setIncludeValue(true)<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   .setImplementation(listener);<!--mep-nl--><!--mep-tab-->   config.getMapConfig("my-cache").addEntryListenerConfig(listenerConfig);<!--mep-nl--><!--mep-tab-->   return config;<!--mep-nl-->   }<!--mep-nl--><!--mep-nl-->   @Bean<!--mep-nl-->   public IMap<String, String> getCacheMap(HazelcastInstance hazelcast) {<!--mep-nl--><!--mep-tab-->   return hazelcast.getMap("my-cache");<!--mep-nl-->   }<!--mep-nl--><!--mep-nl-->   /**<!--mep-nl--><!--mep-tab-->* | HTTP<!--mep-tab--> | CRUD<!--mep-tab-->  | Hazelcast   | httpie<!--mep-nl--><!--mep-tab-->* ----------------------------------------------<!--mep-nl--><!--mep-tab-->* | POST<!--mep-tab--> |  create   | set<!--mep-tab--><!--mep-tab--> | `http POST :8080/caching/1 value==test`<!--mep-nl--><!--mep-tab-->* | GET<!--mep-tab-->  | read<!--mep-tab-->  | get<!--mep-tab--><!--mep-tab--> | `http :8080/caching/1`<!--mep-nl--><!--mep-tab-->* | PUT<!--mep-tab-->  | update<!--mep-tab-->| put<!--mep-tab--><!--mep-tab--> | `http PUT :8080/caching/1 value==test2`<!--mep-nl--><!--mep-tab-->* | PATCH<!--mep-tab-->| update<!--mep-tab-->| replace<!--mep-tab--> | `http PATCH :8080/caching/1 oldValue==test2 newValue=="hey hey"`<!--mep-nl--><!--mep-tab-->* | DELETE   | delete<!--mep-tab-->| remove<!--mep-tab-->  | `http DELETE :8080/caching/1`<!--mep-nl--><!--mep-tab-->* ----------------------------------<!--mep-nl--><!--mep-tab-->*/<!--mep-nl-->   @RestController<!--mep-nl-->   @RequestMapping("caching")<!--mep-nl-->   public class MyController {<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @Autowired<!--mep-nl--><!--mep-tab-->   private IMap<String, String> cacheMap;<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @RequestMapping(method = POST,<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   path = "{key}",<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   params = {"value"})<!--mep-nl--><!--mep-tab-->   public void post(@PathVariable String key,<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->@RequestParam String value) {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   cacheMap.set(key, value);<!--mep-nl--><!--mep-tab-->   }<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @RequestMapping(<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   method = GET,<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   path = "/{key}")<!--mep-nl--><!--mep-tab-->   public String get(@PathVariable("key") String key) {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   return cacheMap.get(key);<!--mep-nl--><!--mep-tab-->   }<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @RequestMapping(<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   method = PUT,<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   path = "{key}",<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   params = {"value"})<!--mep-nl--><!--mep-tab-->   public String put(@PathVariable String key, @RequestParam String value) {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   return cacheMap.put(key, value);<!--mep-nl--><!--mep-tab-->   }<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @RequestMapping(<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   method = PATCH,<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   path = "/{key}",<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   params = {"oldValue", "newValue"})<!--mep-nl--><!--mep-tab-->   public boolean patch(@PathVariable("key") String key,<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->@RequestParam("oldValue") String value,<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab-->@RequestParam("newValue") String newValue) {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   return cacheMap.replace(key, value, newValue);<!--mep-nl--><!--mep-tab-->   }<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @RequestMapping(<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   method = DELETE,<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   path = "/{key}")<!--mep-nl--><!--mep-tab-->   public String delete(@PathVariable String key) {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   return cacheMap.remove(key);<!--mep-nl--><!--mep-tab-->   }<!--mep-nl--><!--mep-nl-->   }<!--mep-nl--><!--mep-nl-->   @Component<!--mep-nl-->   public class MyListener implements<!--mep-nl--><!--mep-tab--><!--mep-tab-->   EntryAddedListener<String, String>,<!--mep-nl--><!--mep-tab--><!--mep-tab-->   EntryUpdatedListener<String, String>,<!--mep-nl--><!--mep-tab--><!--mep-tab-->   EntryRemovedListener<String, String> {<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @Override<!--mep-nl--><!--mep-tab-->   public void entryAdded(EntryEvent<String, String> event) {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   log.info("Entry added [{} : {}]", event.getKey(), event.getValue());<!--mep-nl--><!--mep-tab-->   }<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @Override<!--mep-nl--><!--mep-tab-->   public void entryUpdated(EntryEvent<String, String> event) {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   log.info("Entry updated [{} : {}]. Old value {}", event.getKey(), event.getValue(), event.getOldValue());<!--mep-nl--><!--mep-tab-->   }<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @Override<!--mep-nl--><!--mep-tab-->   public void entryRemoved(EntryEvent<String, String> event) {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   log.info("Entry removed [{} : {}]", event.getKey(), event.getOldValue());<!--mep-nl--><!--mep-tab-->   }<!--mep-nl-->   }<!--mep-nl--><!--mep-nl-->   public static void main(String[] args) {<!--mep-nl--><!--mep-tab-->   SpringApplication.run(MicroserviceApplication.class, args);<!--mep-nl-->   }<!--mep-nl-->}<!--mep-nl-->

Groovy

<!--mep-nl-->package com.hazelcast.bootiful.groovy<!--mep-nl--><!--mep-nl-->import com.hazelcast.config.Config<!--mep-nl-->import com.hazelcast.config.EntryListenerConfig<!--mep-nl-->import com.hazelcast.config.XmlConfigBuilder<!--mep-nl-->import com.hazelcast.core.EntryEvent<!--mep-nl-->import com.hazelcast.core.HazelcastInstance<!--mep-nl-->import com.hazelcast.core.IMap<!--mep-nl-->import com.hazelcast.map.listener.EntryAddedListener<!--mep-nl-->import com.hazelcast.map.listener.EntryRemovedListener<!--mep-nl-->import com.hazelcast.map.listener.EntryUpdatedListener<!--mep-nl-->import com.hazelcast.map.listener.MapListener<!--mep-nl-->import groovy.transform.CompileStatic<!--mep-nl-->import groovy.util.logging.Slf4j<!--mep-nl-->import org.springframework.beans.factory.annotation.Autowired<!--mep-nl-->import org.springframework.boot.SpringApplication<!--mep-nl-->import org.springframework.boot.autoconfigure.SpringBootApplication<!--mep-nl-->import org.springframework.cache.annotation.EnableCaching<!--mep-nl-->import org.springframework.context.annotation.Bean<!--mep-nl-->import org.springframework.stereotype.Component<!--mep-nl-->import org.springframework.web.bind.annotation.PathVariable<!--mep-nl-->import org.springframework.web.bind.annotation.RequestMapping<!--mep-nl-->import org.springframework.web.bind.annotation.RequestParam<!--mep-nl-->import org.springframework.web.bind.annotation.RestController<!--mep-nl--><!--mep-nl-->import static org.springframework.web.bind.annotation.RequestMethod.*<!--mep-nl--><!--mep-nl-->@SpringBootApplication<!--mep-nl-->@EnableCaching<!--mep-nl-->@Slf4j<!--mep-nl-->@CompileStatic<!--mep-nl-->class MicroserviceApplication {<!--mep-nl--><!--mep-nl-->   @Bean<!--mep-nl-->   Config getConfig(MapListener listener) {<!--mep-nl--><!--mep-tab-->   EntryListenerConfig listenerConfig = new EntryListenerConfig()<!--mep-nl--><!--mep-tab-->   listenerConfig.setIncludeValue(true).setImplementation(listener)<!--mep-nl--><!--mep-tab-->   def config = new XmlConfigBuilder()<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   .build()<!--mep-nl--><!--mep-tab-->   config.getMapConfig("my-cache").addEntryListenerConfig listenerConfig<!--mep-nl--><!--mep-tab-->   config<!--mep-nl-->   }<!--mep-nl--><!--mep-nl-->   @Bean<!--mep-nl-->   IMap<String, String> getCacheMap(HazelcastInstance hazelcast) { hazelcast.getMap "my-cache" }<!--mep-nl--><!--mep-nl-->   /**<!--mep-nl--><!--mep-tab-->* | HTTP<!--mep-tab--> | CRUD<!--mep-tab-->  | Hazelcast   | httpie<!--mep-nl--><!--mep-tab-->* ----------------------------------------------<!--mep-nl--><!--mep-tab-->* | POST<!--mep-tab--> | create<!--mep-tab-->| set<!--mep-tab--><!--mep-tab--> | `http POST :8080/caching/1 value==test`<!--mep-nl--><!--mep-tab-->* | GET<!--mep-tab-->  | read<!--mep-tab-->  | get<!--mep-tab--><!--mep-tab--> | `http :8080/caching/1`<!--mep-nl--><!--mep-tab-->* | PUT<!--mep-tab-->  | update<!--mep-tab-->| put<!--mep-tab--><!--mep-tab--> | `http PUT :8080/caching/1 value==test2`<!--mep-nl--><!--mep-tab-->* | PATCH<!--mep-tab-->| update<!--mep-tab-->| replace<!--mep-tab--> | `http PATCH :8080/caching/1 oldValue==test2 newValue=="hey hey"`<!--mep-nl--><!--mep-tab-->* | DELETE   | delete<!--mep-tab-->| remove<!--mep-tab-->  | `http DELETE :8080/caching/1`<!--mep-nl--><!--mep-tab-->* ----------------------------------<!--mep-nl--><!--mep-tab-->*/<!--mep-nl-->   @RestController<!--mep-nl-->   @RequestMapping("caching")<!--mep-nl-->   class MyController {<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @Autowired<!--mep-nl--><!--mep-tab-->   private IMap<String, String> cacheMap<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @RequestMapping(method = POST, path = "{key}", params = ["value"])<!--mep-nl--><!--mep-tab-->   def post(@PathVariable String key, @RequestParam String value) { cacheMap.set key, value }<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @RequestMapping(<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   method = GET,<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab-->   path = "/{key}")<!--mep-nl--><!--mep-tab-->   def get(@PathVariable("key") String key) { cacheMap[key] }<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @RequestMapping(method = PUT, path = "{key}", params = ["value"])<!--mep-nl--><!--mep-tab-->   def put(@PathVariable String key, @RequestParam String value) { cacheMap[key] = value }<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @RequestMapping(method = PATCH, path = "/{key}", params = ["oldValue", "newValue"])<!--mep-nl--><!--mep-tab-->   def patch(@PathVariable("key") String key,<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--> @RequestParam("oldValue") String value,<!--mep-nl--><!--mep-tab--><!--mep-tab--><!--mep-tab--><!--mep-tab--> @RequestParam("newValue") String newValue) {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   cacheMap.replace key, value, newValue<!--mep-nl--><!--mep-tab-->   }<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @RequestMapping(method = DELETE, path = "/{key}")<!--mep-nl--><!--mep-tab-->   def delete(@PathVariable String key) { cacheMap.remove key }<!--mep-nl--><!--mep-nl-->   }<!--mep-nl--><!--mep-nl-->   @Component<!--mep-nl-->   class MyListener implements<!--mep-nl--><!--mep-tab--><!--mep-tab-->   EntryAddedListener<String, String>,<!--mep-nl--><!--mep-tab--><!--mep-tab-->   EntryUpdatedListener<String, String>,<!--mep-nl--><!--mep-tab--><!--mep-tab-->   EntryRemovedListener<String, String> {<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @Override<!--mep-nl--><!--mep-tab-->   void entryAdded(EntryEvent<String, String> event) {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   log.info "Entry added [{} : {}]", event.getKey(), event.getValue()<!--mep-nl--><!--mep-tab-->   }<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @Override<!--mep-nl--><!--mep-tab-->   void entryUpdated(EntryEvent<String, String> event) {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   log.info "Entry updated [{} : {}]. Old value {}", event.getKey(), event.getValue(), event.getOldValue()<!--mep-nl--><!--mep-tab-->   }<!--mep-nl--><!--mep-nl--><!--mep-tab-->   @Override<!--mep-nl--><!--mep-tab-->   void entryRemoved(EntryEvent<String, String> event) {<!--mep-nl--><!--mep-tab--><!--mep-tab-->   log.info "Entry removed [{} : {}]", event.getKey(), event.getOldValue()<!--mep-nl--><!--mep-tab-->   }<!--mep-nl-->   }<!--mep-nl--><!--mep-nl-->   static void main(String... args) {<!--mep-nl--><!--mep-tab-->   SpringApplication.run MicroserviceApplication.class, args<!--mep-nl-->   }<!--mep-nl-->}<!--mep-nl-->

Hazelcast IMDG