title: Setup ehcache with jgroups replication on kubernetes
body: <p>I'm trying to setup a small springboot application using ehcache with jgroups replication in kubernetes, but somehow not able to discover the other members to form a cluster. The bootstrap request to find other nodes is not working, as the message is sent synchronously but not received by the other pod residing on another node.</p>
  
  <p>maven pom.xml</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
      &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
      &lt;parent&gt;
          &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
          &lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;
          &lt;version&gt;2.1.5.RELEASE&lt;/version&gt;
          &lt;relativePath/&gt; &lt;!-- lookup parent from repository --&gt;
      &lt;/parent&gt;
      &lt;groupId&gt;com.test.k8s&lt;/groupId&gt;
      &lt;artifactId&gt;ehcache-jgroups-demo&lt;/artifactId&gt;
      &lt;version&gt;0.0.1-SNAPSHOT&lt;/version&gt;
      &lt;name&gt;ehcache-jgroups-demo&lt;/name&gt;
      &lt;description&gt;Demo project for Spring Boot&lt;/description&gt;
  
      &lt;properties&gt;
          &lt;java.version&gt;11&lt;/java.version&gt;
      &lt;/properties&gt;
  
      &lt;dependencies&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-cache&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
          &lt;/dependency&gt;
  
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
              &lt;scope&gt;test&lt;/scope&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
              &lt;artifactId&gt;lombok&lt;/artifactId&gt;
              &lt;version&gt;1.18.0&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
              &lt;artifactId&gt;spring-boot-starter-actuator&lt;/artifactId&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;net.sf.ehcache&lt;/groupId&gt;
              &lt;artifactId&gt;ehcache&lt;/artifactId&gt;
              &lt;version&gt;${ehcache.version}&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;net.sf.ehcache&lt;/groupId&gt;
              &lt;artifactId&gt;ehcache-jgroupsreplication&lt;/artifactId&gt;
              &lt;version&gt;1.7&lt;/version&gt;
              &lt;exclusions&gt;
                  &lt;exclusion&gt;
                      &lt;groupId&gt;net.sf.ehcache&lt;/groupId&gt;
                      &lt;artifactId&gt;ehcache-core&lt;/artifactId&gt;
                  &lt;/exclusion&gt;
                  &lt;exclusion&gt;
                      &lt;groupId&gt;org.jgroups&lt;/groupId&gt;
                      &lt;artifactId&gt;jgroups&lt;/artifactId&gt;
                  &lt;/exclusion&gt;
              &lt;/exclusions&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.jgroups&lt;/groupId&gt;
              &lt;artifactId&gt;jgroups&lt;/artifactId&gt;
              &lt;version&gt;3.6.17.Final&lt;/version&gt;
          &lt;/dependency&gt;
          &lt;dependency&gt;
              &lt;groupId&gt;org.jgroups.kubernetes&lt;/groupId&gt;
              &lt;artifactId&gt;kubernetes&lt;/artifactId&gt;
              &lt;version&gt;0.9.2&lt;/version&gt;
              &lt;exclusions&gt;
                  &lt;exclusion&gt;
                      &lt;groupId&gt;io.undertow&lt;/groupId&gt;
                      &lt;artifactId&gt;undertow-core&lt;/artifactId&gt;
                  &lt;/exclusion&gt;
              &lt;/exclusions&gt;
          &lt;/dependency&gt;
      &lt;/dependencies&gt;
  
      &lt;build&gt;
          &lt;plugins&gt;
              &lt;plugin&gt;
                  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
                  &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
              &lt;/plugin&gt;
          &lt;/plugins&gt;
      &lt;/build&gt;
  
  &lt;/project&gt;
  </code></pre>
  
  <p>Springboot application</p>
  
  <pre><code>@SpringBootApplication
  public class EhcacheJgroupsDemoApplication {
  
      public static void main(String[] args) {
          SpringApplication.run(EhcacheJgroupsDemoApplication.class, args);
      }
  
  }
  
  @EnableCaching
  @Configuration
  class EHCacheConfig {
  
      @Bean
      public CacheManager cacheManager(){
          return new EhCacheCacheManager(ehCacheManagerFactory().getObject());
      }
  
      @Bean
      public EhCacheManagerFactoryBean ehCacheManagerFactory(){
          EhCacheManagerFactoryBean ehCacheBean = new EhCacheManagerFactoryBean();
          ehCacheBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
          ehCacheBean.setShared(true);
          return ehCacheBean;
      }
  
  }
  
  @Component
  @Slf4j
  class CacheManagerCheck implements CommandLineRunner {
  
  
      private final CacheManager cacheManager;
  
      public CacheManagerCheck(CacheManager cacheManager) {
          this.cacheManager = cacheManager;
      }
  
      @Override
      public void run(String... strings) {
          log.info("\n\n" + "=========================================================\n"
                  + "Using cache manager: " + this.cacheManager.getClass().getName() + "\n"
                  + "=========================================================\n\n");
      }
  
  }
  
  @RestController
  class CountryController {
  
      @Autowired
      CountryRepository countryRepository;
  
      @GetMapping(value = "/country/{code}")
      public ResponseEntity&lt;Country&gt; getCountryByCode(@PathVariable("code") String code) {
          Country country = countryRepository.findByCode(code);
          return ResponseEntity.ok(country);
      }
  
      @DeleteMapping(value = "/country/{code}")
      public ResponseEntity deleteCountryByCode(@PathVariable("code") String code) {
          countryRepository.deleteCode(code);
          return ResponseEntity.ok().build();
      }
  }
  
  @Slf4j
  @Component
  class CountryRepository {
  
      @Cacheable(value="countries", key="#code")
      public Country findByCode(String code) {
          log.info("---&gt; Loading country with code={}", code);
          return new Country(code);
      }
  
      @CacheEvict(value="countries",key = "#code")
      public int deleteCode(String code){
          log.info("---&gt; Deleting country with code={}", code);
          return 0;
      }
  }
  
  @Data
  class Country implements Serializable {
  
      private final String code;
  }
  </code></pre>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;ehcache
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
          updateCheck="false"&gt;
  
      &lt;cacheManagerPeerProviderFactory
              class="x.x.x.x.JGroupsCacheManagerPeerProviderFactory"
              properties="file=jgroups/tcp.xml" /&gt;
  
      &lt;defaultCache maxElementsInMemory="50" eternal="false"
                    overflowToDisk="false" memoryStoreEvictionPolicy="LFU"&gt;
          &lt;cacheEventListenerFactory
                  class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
                  properties="replicateAsynchronously=false, replicatePuts=true,
              replicateUpdates=true, replicateUpdatesViaCopy=false,
              replicateRemovals=true"/&gt;
  
          &lt;bootstrapCacheLoaderFactory
                  class="net.sf.ehcache.distribution.jgroups.JGroupsBootstrapCacheLoaderFactory"
                  properties="bootstrapAsynchronously=false"/&gt;
      &lt;/defaultCache&gt;
  
      &lt;cache name="countries" eternal="false" maxElementsInMemory="100"
             overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"
             timeToLiveSeconds="60" memoryStoreEvictionPolicy="LRU"&gt;
          &lt;cacheEventListenerFactory
                  class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory"
                  properties="replicateAsynchronously=false, replicatePuts=true,
              replicateUpdates=true, replicateUpdatesViaCopy=false,
              replicateRemovals=true"/&gt;
  
          &lt;bootstrapCacheLoaderFactory
                  class="net.sf.ehcache.distribution.jgroups.JGroupsBootstrapCacheLoaderFactory"
                  properties="bootstrapAsynchronously=false"/&gt;
      &lt;/cache&gt;
  
  &lt;/ehcache&gt;
  </code></pre>
  
  <p>tcp.xml</p>
  
  <pre><code>&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="urn:org:jgroups"
          xsi:schemaLocation="urn:org:jgroups http://www.jgroups.org/schema/jgroups.xsd"&gt;
      &lt;TCP
              bind_addr="${jgroups.tcp.address:match-interface:en.*}"
              bind_port="7800"
              recv_buf_size="5M"
              send_buf_size="1M"
              max_bundle_size="64K"
              enable_diagnostics="true"
              thread_naming_pattern="cl"
  
              thread_pool.min_threads="0"
              thread_pool.max_threads="500"
              thread_pool.keep_alive_time="30000" /&gt;
  
      &lt;org.jgroups.protocols.kubernetes.KUBE_PING
              namespace="${KUBE_NAMESPACE:ehcache-demo}"/&gt;
  
      &lt;MERGE3 max_interval="30000"
              min_interval="10000"/&gt;
  
      &lt;VERIFY_SUSPECT timeout="1500"/&gt;
  
      &lt;BARRIER /&gt;
      &lt;pbcast.NAKACK2 xmit_interval="500"
                      xmit_table_num_rows="100"
                      xmit_table_msgs_per_row="2000"
                      xmit_table_max_compaction_time="30000"
                      use_mcast_xmit="false"
                      discard_delivered_msgs="true" /&gt;
      &lt;UNICAST3
              xmit_table_num_rows="100"
              xmit_table_msgs_per_row="1000"
              xmit_table_max_compaction_time="30000"/&gt;
      &lt;pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
                     max_bytes="8m"/&gt;
      &lt;pbcast.GMS print_local_addr="true" join_timeout="3000"
                  view_bundling="true"/&gt;
      &lt;MFC max_credits="2M"
           min_threshold="0.4"/&gt;
      &lt;FRAG2 frag_size="60K"  /&gt;
      &lt;pbcast.STATE_TRANSFER  /&gt;
      &lt;CENTRAL_LOCK /&gt;
      &lt;COUNTER/&gt;
  &lt;/config&gt;
  </code></pre>