├── .circleci └── config.yml ├── .gitignore ├── config └── hazelcast.xml ├── employee-kubernetes-service ├── k8s │ └── deployment.yaml ├── pom.xml ├── skaffold.yaml └── src │ └── main │ └── java │ └── pl │ └── piomin │ └── services │ └── employee │ ├── EmployeeApplication.java │ ├── api │ └── EmployeeController.java │ ├── data │ └── EmployeeRepository.java │ └── model │ └── Employee.java ├── employee-service ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── pl │ │ │ └── piomin │ │ │ └── services │ │ │ └── datagrid │ │ │ └── employee │ │ │ ├── EmployeeApplication.java │ │ │ ├── api │ │ │ └── EmployeeController.java │ │ │ ├── data │ │ │ ├── EmployeeRepository.java │ │ │ └── EmployeeSerializer.java │ │ │ ├── model │ │ │ └── Employee.java │ │ │ └── service │ │ │ └── EmployeeService.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── pl │ └── piomin │ └── services │ └── datagrid │ └── employee │ ├── EmployeeApplicationTest.java │ ├── MysqlContainerDevMode.java │ └── data │ └── AddEmployeeRepositoryTest.java ├── person-service ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── java │ │ └── pl │ │ │ └── piomin │ │ │ └── services │ │ │ └── datagrid │ │ │ └── person │ │ │ ├── PersonApplication.java │ │ │ ├── api │ │ │ └── PersonController.java │ │ │ ├── data │ │ │ └── PersonRepository.java │ │ │ └── model │ │ │ └── Person.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── pl │ └── piomin │ └── services │ └── datagrid │ └── person │ ├── MysqlAndHazelcastContainersDevMode.java │ ├── PersonDevModeApplication.java │ └── data │ └── AddPersonRepositoryTest.java ├── pom.xml ├── readme.md └── renovate.json /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: '2.1' 2 | 3 | jobs: 4 | analyze: 5 | docker: 6 | - image: 'cimg/openjdk:21.0.6' 7 | steps: 8 | - checkout 9 | - run: 10 | name: Analyze on SonarCloud 11 | command: mvn verify sonar:sonar -DskipTests 12 | test: 13 | executor: machine_executor_amd64 14 | steps: 15 | - checkout 16 | - run: 17 | name: Install OpenJDK 21 18 | command: | 19 | java -version 20 | sudo apt-get update && sudo apt-get install openjdk-21-jdk 21 | sudo update-alternatives --set java /usr/lib/jvm/java-21-openjdk-amd64/bin/java 22 | sudo update-alternatives --set javac /usr/lib/jvm/java-21-openjdk-amd64/bin/javac 23 | java -version 24 | export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 25 | - run: 26 | name: Maven Tests 27 | command: mvn test 28 | 29 | orbs: 30 | maven: circleci/maven@2.0.0 31 | 32 | executors: 33 | machine_executor_amd64: 34 | machine: 35 | image: ubuntu-2204:2023.10.1 36 | environment: 37 | architecture: "amd64" 38 | platform: "linux/amd64" 39 | 40 | workflows: 41 | maven_test: 42 | jobs: 43 | - test 44 | - analyze: 45 | context: SonarCloud -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.project 2 | /.settings/ 3 | -------------------------------------------------------------------------------- /config/hazelcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | dev 5 | dev-pass 6 | 7 | http://192.168.99.100:38080/mancenter 8 | 9 | 5701 10 | true 11 | 12 | 0 13 | 14 | 15 | 16 | 224.2.2.3 17 | 54327 18 | 2 19 | 32 20 | 21 | 22 | 23 | 127.0.0.1 24 | 127.0.0.1 25 | 26 | 27 | 28 | my-access-key 29 | my-secret-key 30 | us-west-1 31 | ec2.amazonaws.com 32 | hazelcast-sg 33 | type 34 | hz-nodes 35 | 36 | 37 | 38 | 39 | 10.10.1.* 40 | 41 | 42 | 43 | 44 | PBEWithMD5AndDES 45 | thesalt 46 | thepass 47 | 19 48 | 49 | 50 | 51 | BINARY 52 | true 53 | false 54 | INDEX-ONLY 55 | 1 56 | 0 57 | 0 58 | 0 59 | NONE 60 | 2147483647 61 | 25 62 | 100 63 | com.hazelcast.map.merge.PutIfAbsentMapMergePolicy 64 | false 65 | 66 | false 67 | 68 | 69 | 0 70 | 1 71 | 72 | 73 | 74 | true 75 | 2147483647 76 | 1 77 | 0 78 | -1 79 | 80 | 81 | 1 82 | 0 83 | true 84 | true 85 | SET 86 | 87 | 88 | true 89 | 2147483647 90 | 1 91 | 0 92 | 93 | 94 | true 95 | 2147483647 96 | 1 97 | 0 98 | 99 | 100 | 0 101 | 1 102 | 0 103 | 104 | 105 | 10000 106 | 0 107 | 1 108 | 0 109 | BINARY 110 | 111 | 112 | 113 | true 114 | 16 115 | 0 116 | 117 | 118 | 119 | 0 120 | false 121 | BIG_ENDIAN 122 | false 123 | true 124 | false 125 | true 126 | 127 | 128 | true 129 | 10 130 | BLOCK 131 | 132 | 133 | 134 | 135 | 16 136 | 4194304 137 | 12.5 138 | 139 | 140 | 141 | /opt/hazelcast/hot-restart 142 | 1 143 | 120 144 | 900 145 | FULL_RECOVERY_ONLY 146 | 147 | -------------------------------------------------------------------------------- /employee-kubernetes-service/k8s/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: employee-service 5 | labels: 6 | app: employee-service 7 | spec: 8 | replicas: 3 9 | selector: 10 | matchLabels: 11 | app: employee-service 12 | template: 13 | metadata: 14 | labels: 15 | app: employee-service 16 | spec: 17 | containers: 18 | - name: employee-service 19 | image: piomin/employee-service 20 | ports: 21 | - name: http 22 | containerPort: 8080 23 | - name: multicast 24 | containerPort: 5701 25 | --- 26 | apiVersion: v1 27 | kind: Service 28 | metadata: 29 | name: employee-service 30 | labels: 31 | app: employee-service 32 | spec: 33 | ports: 34 | - port: 8080 35 | protocol: TCP 36 | selector: 37 | app: employee-service 38 | type: NodePort 39 | --- 40 | apiVersion: v1 41 | kind: Service 42 | metadata: 43 | name: hazelcast-service 44 | spec: 45 | selector: 46 | app: employee-service 47 | ports: 48 | - name: hazelcast 49 | port: 5701 50 | type: LoadBalancer -------------------------------------------------------------------------------- /employee-kubernetes-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | pl.piomin.services 8 | sample-hazelcast-spring-datagrid 9 | 1.0-SNAPSHOT 10 | 11 | 4.0.0 12 | 13 | employee-kubernetes-service 14 | 15 | 16 | ${project.artifactId} 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | com.hazelcast 26 | spring-data-hazelcast 27 | 2.4.0 28 | 29 | 30 | com.hazelcast 31 | hazelcast-spring 32 | 33 | 34 | com.hazelcast 35 | hazelcast-kubernetes 36 | 2.2.3 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-maven-plugin 45 | 46 | 47 | com.google.cloud.tools 48 | jib-maven-plugin 49 | 3.4.5 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /employee-kubernetes-service/skaffold.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: skaffold/v2alpha1 2 | kind: Config 3 | build: 4 | artifacts: 5 | - image: piomin/employee-service 6 | jib: {} 7 | tagPolicy: 8 | gitCommit: {} -------------------------------------------------------------------------------- /employee-kubernetes-service/src/main/java/pl/piomin/services/employee/EmployeeApplication.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.employee; 2 | 3 | import com.hazelcast.config.Config; 4 | 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.data.hazelcast.repository.config.EnableHazelcastRepositories; 9 | 10 | @SpringBootApplication 11 | @EnableHazelcastRepositories 12 | public class EmployeeApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(EmployeeApplication.class, args); 16 | } 17 | 18 | @Bean 19 | Config config() { 20 | Config config = new Config(); 21 | config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(false); 22 | config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false); 23 | config.getNetworkConfig().getJoin().getKubernetesConfig().setEnabled(true) 24 | .setProperty("namespace", "default") 25 | .setProperty("service-name", "hazelcast-service"); 26 | return config; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /employee-kubernetes-service/src/main/java/pl/piomin/services/employee/api/EmployeeController.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.employee.api; 2 | 3 | import java.util.List; 4 | 5 | import pl.piomin.services.employee.data.EmployeeRepository; 6 | import pl.piomin.services.employee.model.Employee; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import org.springframework.web.bind.annotation.DeleteMapping; 11 | import org.springframework.web.bind.annotation.GetMapping; 12 | import org.springframework.web.bind.annotation.PathVariable; 13 | import org.springframework.web.bind.annotation.PostMapping; 14 | import org.springframework.web.bind.annotation.RequestBody; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | @RestController 19 | @RequestMapping("/employees") 20 | public class EmployeeController { 21 | 22 | private static final Logger logger = LoggerFactory.getLogger(EmployeeController.class); 23 | 24 | private EmployeeRepository repository; 25 | 26 | EmployeeController(EmployeeRepository repository) { 27 | this.repository = repository; 28 | } 29 | 30 | @GetMapping("/person/{id}") 31 | public Employee findByPersonId(@PathVariable("id") Integer personId) { 32 | logger.info("findByPersonId({})", personId); 33 | return repository.findByPersonId(personId); 34 | } 35 | 36 | @GetMapping("/company/{company}") 37 | public List findByCompany(@PathVariable("company") String company) { 38 | logger.info(String.format("findByCompany({})", company)); 39 | return repository.findByCompany(company); 40 | } 41 | 42 | @GetMapping("/company/{company}/position/{position}") 43 | public List findByCompanyAndPosition(@PathVariable("company") String company, @PathVariable("position") String position) { 44 | logger.info(String.format("findByCompany({}, {})", company, position)); 45 | return repository.findByCompanyAndPosition(company, position); 46 | } 47 | 48 | @GetMapping("/{id}") 49 | public Employee findById(@PathVariable("id") Long id) { 50 | logger.info("findById({})", id); 51 | return repository.findById(id).get(); 52 | } 53 | 54 | @GetMapping("/salary/{salary}") 55 | public List findBySalaryGreaterThan(@PathVariable("salary") int salary) { 56 | logger.info(String.format("findBySalaryGreaterThan({})", salary)); 57 | return repository.findBySalaryGreaterThan(salary); 58 | } 59 | 60 | @PostMapping 61 | public Employee add(@RequestBody Employee emp) { 62 | logger.info("add({})", emp); 63 | return repository.save(emp); 64 | } 65 | 66 | @DeleteMapping("/{id}") 67 | public void delete(@PathVariable("id") Long id) { 68 | logger.info("delete({})", id); 69 | repository.deleteById(id); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /employee-kubernetes-service/src/main/java/pl/piomin/services/employee/data/EmployeeRepository.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.employee.data; 2 | 3 | 4 | import java.util.List; 5 | 6 | import pl.piomin.services.employee.model.Employee; 7 | 8 | import org.springframework.data.hazelcast.repository.HazelcastRepository; 9 | 10 | public interface EmployeeRepository extends HazelcastRepository { 11 | 12 | Employee findByPersonId(Integer personId); 13 | 14 | List findByCompany(String company); 15 | 16 | List findByCompanyAndPosition(String company, String position); 17 | 18 | List findBySalaryGreaterThan(int salary); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /employee-kubernetes-service/src/main/java/pl/piomin/services/employee/model/Employee.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.employee.model; 2 | 3 | import org.springframework.data.annotation.Id; 4 | 5 | import java.io.Serializable; 6 | import java.util.Objects; 7 | 8 | public class Employee implements Serializable { 9 | 10 | @Id 11 | private Long id; 12 | private Integer personId; 13 | private String company; 14 | private String position; 15 | private int salary; 16 | 17 | public Long getId() { 18 | return id; 19 | } 20 | 21 | public void setId(Long id) { 22 | this.id = id; 23 | } 24 | 25 | public Integer getPersonId() { 26 | return personId; 27 | } 28 | 29 | public void setPersonId(Integer personId) { 30 | this.personId = personId; 31 | } 32 | 33 | public String getCompany() { 34 | return company; 35 | } 36 | 37 | public void setCompany(String company) { 38 | this.company = company; 39 | } 40 | 41 | public String getPosition() { 42 | return position; 43 | } 44 | 45 | public void setPosition(String position) { 46 | this.position = position; 47 | } 48 | 49 | public int getSalary() { 50 | return salary; 51 | } 52 | 53 | public void setSalary(int salary) { 54 | this.salary = salary; 55 | } 56 | 57 | @Override 58 | public String toString() { 59 | return "Employee{" + 60 | "id=" + id + 61 | ", personId=" + personId + 62 | ", company='" + company + '\'' + 63 | ", position='" + position + '\'' + 64 | ", salary=" + salary + 65 | '}'; 66 | } 67 | 68 | @Override 69 | public boolean equals(Object o) { 70 | if (this == o) return true; 71 | if (o == null || getClass() != o.getClass()) return false; 72 | 73 | Employee employee = (Employee) o; 74 | 75 | return Objects.equals(id, employee.id); 76 | } 77 | 78 | @Override 79 | public int hashCode() { 80 | return id != null ? id.hashCode() : 0; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /employee-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | /.classpath 4 | /.project 5 | -------------------------------------------------------------------------------- /employee-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | pl.piomin.services 6 | sample-hazelcast-spring-datagrid 7 | 1.0-SNAPSHOT 8 | 9 | employee-service 10 | 11 | 12 | ${project.artifactId} 13 | 14 | 15 | 16 | 17 | org.springframework.boot 18 | spring-boot-starter-data-jpa 19 | 20 | 21 | com.hazelcast 22 | hazelcast 23 | 24 | 25 | com.hazelcast 26 | hazelcast-spring 27 | 28 | 29 | org.testcontainers 30 | mysql 31 | 1.21.1 32 | test 33 | 34 | 35 | org.testcontainers 36 | junit-jupiter 37 | 1.21.1 38 | test 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-testcontainers 43 | test 44 | 45 | 46 | -------------------------------------------------------------------------------- /employee-service/src/main/java/pl/piomin/services/datagrid/employee/EmployeeApplication.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.employee; 2 | 3 | import com.hazelcast.config.Config; 4 | import com.hazelcast.config.ManagementCenterConfig; 5 | import com.hazelcast.config.SerializerConfig; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.context.annotation.Bean; 9 | import pl.piomin.services.datagrid.employee.data.EmployeeSerializer; 10 | import pl.piomin.services.datagrid.employee.model.Employee; 11 | 12 | @SpringBootApplication 13 | public class EmployeeApplication { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(EmployeeApplication.class, args); 17 | } 18 | 19 | @Bean 20 | Config config() { 21 | Config c = new Config(); 22 | c.setInstanceName("cache-1"); 23 | c.setClusterName("dev"); 24 | ManagementCenterConfig mcc = new ManagementCenterConfig() 25 | .setConsoleEnabled(true); 26 | c.setManagementCenterConfig(mcc); 27 | SerializerConfig sc = new SerializerConfig() 28 | .setTypeClass(Employee.class) 29 | .setClass(EmployeeSerializer.class); 30 | c.getSerializationConfig().addSerializerConfig(sc); 31 | return c; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /employee-service/src/main/java/pl/piomin/services/datagrid/employee/api/EmployeeController.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.employee.api; 2 | 3 | import java.util.List; 4 | import java.util.logging.Logger; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import pl.piomin.services.datagrid.employee.model.Employee; 14 | import pl.piomin.services.datagrid.employee.service.EmployeeService; 15 | 16 | @RestController 17 | public class EmployeeController { 18 | 19 | private Logger logger = Logger.getLogger(EmployeeController.class.getName()); 20 | 21 | @Autowired 22 | EmployeeService service; 23 | 24 | @GetMapping("/employees/person/{id}") 25 | public Employee findByPersonId(@PathVariable("id") Integer personId) { 26 | logger.info(String.format("findByPersonId(%d)", personId)); 27 | return service.findByPersonId(personId); 28 | } 29 | 30 | @GetMapping("/employees/company/{company}") 31 | public List findByCompany(@PathVariable("company") String company) { 32 | logger.info(String.format("findByCompany(%s)", company)); 33 | return service.findByCompany(company); 34 | } 35 | 36 | @GetMapping("/employees/{id}") 37 | public Employee findById(@PathVariable("id") Integer id) { 38 | logger.info(String.format("findById(%d)", id)); 39 | return service.findById(id); 40 | } 41 | 42 | @PostMapping("/employees") 43 | public Employee add(@RequestBody Employee emp) { 44 | logger.info(String.format("add(%s)", emp)); 45 | return service.add(emp); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /employee-service/src/main/java/pl/piomin/services/datagrid/employee/data/EmployeeRepository.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.employee.data; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.repository.CrudRepository; 6 | 7 | import pl.piomin.services.datagrid.employee.model.Employee; 8 | 9 | public interface EmployeeRepository extends CrudRepository { 10 | 11 | public Employee findByPersonId(Integer personId); 12 | 13 | public List findByCompany(String company); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /employee-service/src/main/java/pl/piomin/services/datagrid/employee/data/EmployeeSerializer.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.employee.data; 2 | 3 | import com.hazelcast.nio.ObjectDataInput; 4 | import com.hazelcast.nio.ObjectDataOutput; 5 | import com.hazelcast.nio.serialization.StreamSerializer; 6 | import pl.piomin.services.datagrid.employee.model.Employee; 7 | 8 | import java.io.IOException; 9 | 10 | public class EmployeeSerializer implements StreamSerializer { 11 | 12 | @Override 13 | public int getTypeId() { 14 | return 1; 15 | } 16 | 17 | @Override 18 | public void write(ObjectDataOutput out, Employee employee) throws IOException { 19 | out.writeInt(employee.getId()); 20 | out.writeInt(employee.getPersonId()); 21 | out.writeUTF(employee.getCompany()); 22 | } 23 | 24 | @Override 25 | public Employee read(ObjectDataInput in) throws IOException { 26 | Employee e = new Employee(); 27 | e.setId(in.readInt()); 28 | e.setPersonId(in.readInt()); 29 | e.setCompany(in.readUTF()); 30 | return e; 31 | } 32 | 33 | @Override 34 | public void destroy() { 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /employee-service/src/main/java/pl/piomin/services/datagrid/employee/model/Employee.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.employee.model; 2 | 3 | import jakarta.persistence.Entity; 4 | import jakarta.persistence.GeneratedValue; 5 | import jakarta.persistence.Id; 6 | 7 | import java.io.Serializable; 8 | 9 | @Entity 10 | public class Employee implements Serializable { 11 | 12 | private static final long serialVersionUID = 3214253910554454648L; 13 | 14 | @Id 15 | @GeneratedValue 16 | private Integer id; 17 | private Integer personId; 18 | private String company; 19 | 20 | public Integer getId() { 21 | return id; 22 | } 23 | 24 | public void setId(Integer id) { 25 | this.id = id; 26 | } 27 | 28 | public Integer getPersonId() { 29 | return personId; 30 | } 31 | 32 | public void setPersonId(Integer personId) { 33 | this.personId = personId; 34 | } 35 | 36 | public String getCompany() { 37 | return company; 38 | } 39 | 40 | public void setCompany(String company) { 41 | this.company = company; 42 | } 43 | 44 | @Override 45 | public int hashCode() { 46 | final int prime = 31; 47 | int result = 1; 48 | result = prime * result + ((company == null) ? 0 : company.hashCode()); 49 | result = prime * result + ((id == null) ? 0 : id.hashCode()); 50 | result = prime * result + ((personId == null) ? 0 : personId.hashCode()); 51 | return result; 52 | } 53 | 54 | @Override 55 | public boolean equals(Object obj) { 56 | if (this == obj) 57 | return true; 58 | if (obj == null) 59 | return false; 60 | if (getClass() != obj.getClass()) 61 | return false; 62 | Employee other = (Employee) obj; 63 | if (company == null) { 64 | if (other.company != null) 65 | return false; 66 | } else if (!company.equals(other.company)) 67 | return false; 68 | if (id == null) { 69 | if (other.id != null) 70 | return false; 71 | } else if (!id.equals(other.id)) 72 | return false; 73 | if (personId == null) { 74 | if (other.personId != null) 75 | return false; 76 | } else if (!personId.equals(other.personId)) 77 | return false; 78 | return true; 79 | } 80 | 81 | @Override 82 | public String toString() { 83 | return "Employee [id=" + id + ", personId=" + personId + ", company=" + company + "]"; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /employee-service/src/main/java/pl/piomin/services/datagrid/employee/service/EmployeeService.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.employee.service; 2 | 3 | import com.hazelcast.config.IndexType; 4 | import com.hazelcast.core.HazelcastInstance; 5 | import com.hazelcast.map.IMap; 6 | import com.hazelcast.query.Predicate; 7 | import com.hazelcast.query.PredicateBuilder; 8 | import com.hazelcast.query.impl.PredicateBuilderImpl; 9 | import jakarta.annotation.PostConstruct; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | import pl.piomin.services.datagrid.employee.data.EmployeeRepository; 13 | import pl.piomin.services.datagrid.employee.model.Employee; 14 | 15 | import java.util.ArrayList; 16 | import java.util.Collection; 17 | import java.util.List; 18 | import java.util.Optional; 19 | import java.util.logging.Logger; 20 | 21 | @Service 22 | public class EmployeeService { 23 | 24 | private Logger logger = Logger.getLogger(EmployeeService.class.getName()); 25 | 26 | @Autowired 27 | EmployeeRepository repository; 28 | @Autowired 29 | HazelcastInstance instance; 30 | 31 | IMap map; 32 | 33 | @PostConstruct 34 | public void init() { 35 | map = instance.getMap("employee"); 36 | map.addIndex(IndexType.HASH, "company"); 37 | logger.info("Employees cache: " + map.size()); 38 | } 39 | 40 | @SuppressWarnings("rawtypes") 41 | public Employee findByPersonId(Integer personId) { 42 | PredicateBuilder.EntryObject eo = new PredicateBuilderImpl().getEntryObject(); 43 | Predicate predicate = eo.get("personId").equal(personId); 44 | logger.info("Employee cache find"); 45 | Collection ps = map.values(predicate); 46 | logger.info("Employee cached: " + ps); 47 | Optional e = ps.stream().findFirst(); 48 | if (e.isPresent()) 49 | return e.get(); 50 | logger.info("Employee cache find"); 51 | Employee emp = repository.findByPersonId(personId); 52 | logger.info("Employee: " + emp); 53 | map.put(emp.getId(), emp); 54 | return emp; 55 | } 56 | 57 | @SuppressWarnings("rawtypes") 58 | public List findByCompany(String company) { 59 | PredicateBuilder.EntryObject eo = new PredicateBuilderImpl().getEntryObject(); 60 | Predicate predicate = eo.get("company").equal(company); 61 | logger.info("Employees cache find"); 62 | Collection ps = map.values(predicate); 63 | logger.info("Employees cache size: " + ps.size()); 64 | if (ps.size() > 0) { 65 | return new ArrayList<>(ps); 66 | } 67 | logger.info("Employees find"); 68 | List e = repository.findByCompany(company); 69 | logger.info("Employees size: " + e.size()); 70 | e.parallelStream().forEach(it -> { 71 | map.putIfAbsent(it.getId(), it); 72 | }); 73 | return e; 74 | } 75 | 76 | public Employee findById(Integer id) { 77 | Employee e = map.get(id); 78 | if (e != null) 79 | return e; 80 | e = repository.findById(id).orElseThrow(); 81 | map.put(id, e); 82 | return e; 83 | } 84 | 85 | public Employee add(Employee e) { 86 | e = repository.save(e); 87 | map.put(e.getId(), e); 88 | return e; 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /employee-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: ${PORT:2222} 3 | 4 | spring: 5 | application: 6 | name: employee-service 7 | datasource: 8 | url: jdbc:mysql://localhost:33306/datagrid?useSSL=false 9 | username: datagrid 10 | password: datagrid 11 | jpa: 12 | hibernate: 13 | ddl-auto: create 14 | # properties: 15 | # hibernate: 16 | # show_sql: true 17 | # cache: 18 | # use_query_cache: true 19 | # use_second_level_cache: true 20 | # hazelcast: 21 | # use_native_client: true 22 | # native_client_address: 192.168.99.100:5701 23 | # native_client_group: dev 24 | # native_client_password: dev-pass 25 | # region: 26 | # factory_class: com.hazelcast.hibernate.HazelcastCacheRegionFactory 27 | 28 | #logging: 29 | # level: 30 | # com.hazelcast: DEBUG 31 | # org.hibernate: DEBUG -------------------------------------------------------------------------------- /employee-service/src/test/java/pl/piomin/services/datagrid/employee/EmployeeApplicationTest.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.employee; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | 5 | public class EmployeeApplicationTest { 6 | 7 | public static void main(String[] args) { 8 | SpringApplication.from(EmployeeApplication::main) 9 | .with(MysqlContainerDevMode.class) 10 | .run(args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /employee-service/src/test/java/pl/piomin/services/datagrid/employee/MysqlContainerDevMode.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.employee; 2 | 3 | import org.springframework.boot.test.context.TestConfiguration; 4 | import org.springframework.boot.testcontainers.service.connection.ServiceConnection; 5 | import org.springframework.context.annotation.Bean; 6 | import org.testcontainers.containers.MySQLContainer; 7 | 8 | @TestConfiguration 9 | public class MysqlContainerDevMode { 10 | 11 | @Bean 12 | @ServiceConnection 13 | public MySQLContainer mysql() { 14 | return new MySQLContainer<>("mysql:8.0") 15 | .withUsername("datagrid") 16 | .withPassword("datagrid"); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /employee-service/src/test/java/pl/piomin/services/datagrid/employee/data/AddEmployeeRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.employee.data; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.boot.testcontainers.service.connection.ServiceConnection; 7 | import org.springframework.test.context.DynamicPropertyRegistry; 8 | import org.springframework.test.context.DynamicPropertySource; 9 | import org.testcontainers.containers.MySQLContainer; 10 | import org.testcontainers.junit.jupiter.Container; 11 | import org.testcontainers.junit.jupiter.Testcontainers; 12 | import pl.piomin.services.datagrid.employee.model.Employee; 13 | 14 | import java.text.DecimalFormat; 15 | import java.util.Random; 16 | import java.util.logging.Logger; 17 | 18 | 19 | @SpringBootTest 20 | @Testcontainers 21 | public class AddEmployeeRepositoryTest { 22 | 23 | protected Logger logger = Logger.getLogger(AddEmployeeRepositoryTest.class.getName()); 24 | 25 | @Autowired 26 | EmployeeRepository repository; 27 | 28 | @Container 29 | @ServiceConnection 30 | private static final MySQLContainer MYSQL = new MySQLContainer<>("mysql:8.0") 31 | .withUsername("datagrid") 32 | .withPassword("datagrid"); 33 | 34 | @Test 35 | void add() { 36 | for (int i = 0; i < 1000; i++) { 37 | int ix = new Random().nextInt(100); 38 | Employee e = new Employee(); 39 | e.setPersonId(i); 40 | e.setCompany("TEST" + new DecimalFormat("000").format(ix)); 41 | e = repository.save(e); 42 | logger.info("Add: " + e); 43 | } 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /person-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.settings/ 3 | /.classpath 4 | /.project 5 | -------------------------------------------------------------------------------- /person-service/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | pl.piomin.services 6 | sample-hazelcast-spring-datagrid 7 | 1.0-SNAPSHOT 8 | 9 | person-service 10 | 11 | 12 | ${project.artifactId} 13 | 14 | 15 | 16 | 17 | org.springframework.boot 18 | spring-boot-starter-data-jpa 19 | 20 | 21 | com.hazelcast 22 | hazelcast 23 | 24 | 25 | com.hazelcast 26 | hazelcast-spring 27 | 28 | 29 | org.testcontainers 30 | mysql 31 | 1.21.1 32 | test 33 | 34 | 35 | org.testcontainers 36 | junit-jupiter 37 | 1.21.1 38 | test 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-testcontainers 43 | test 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /person-service/src/main/java/pl/piomin/services/datagrid/person/PersonApplication.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.person; 2 | 3 | import com.hazelcast.client.config.ClientConfig; 4 | import com.hazelcast.client.config.ClientConnectionStrategyConfig; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.boot.SpringApplication; 9 | import org.springframework.boot.autoconfigure.SpringBootApplication; 10 | import org.springframework.cache.annotation.EnableCaching; 11 | import org.springframework.context.annotation.Bean; 12 | 13 | @SpringBootApplication 14 | @EnableCaching 15 | public class PersonApplication { 16 | 17 | private static final Logger LOG = LoggerFactory.getLogger(PersonApplication.class); 18 | 19 | public static void main(String[] args) { 20 | SpringApplication.run(PersonApplication.class, args); 21 | } 22 | 23 | @Value("${spring.hazelcast.url:localhost:5701}") 24 | private String hazelcastUrl; 25 | 26 | @Bean 27 | ClientConfig clientConfig() { 28 | LOG.info("Connecting Hazelcast: url={}", hazelcastUrl); 29 | ClientConfig config = new ClientConfig(); 30 | config.getNetworkConfig().addAddress(hazelcastUrl); 31 | config.setInstanceName("cache-1"); 32 | 33 | ClientConnectionStrategyConfig strategy = new ClientConnectionStrategyConfig(); 34 | strategy.setAsyncStart(true); 35 | config.setConnectionStrategyConfig(strategy); 36 | return config; 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /person-service/src/main/java/pl/piomin/services/datagrid/person/api/PersonController.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.person.api; 2 | 3 | import java.util.List; 4 | 5 | import com.hazelcast.client.HazelcastClientOfflineException; 6 | import jakarta.annotation.PostConstruct; 7 | 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.cache.CacheManager; 12 | import org.springframework.web.bind.annotation.GetMapping; 13 | import org.springframework.web.bind.annotation.PathVariable; 14 | import org.springframework.web.bind.annotation.RestController; 15 | 16 | import pl.piomin.services.datagrid.person.data.PersonRepository; 17 | import pl.piomin.services.datagrid.person.model.Person; 18 | 19 | @RestController 20 | public class PersonController { 21 | 22 | protected Logger logger = LoggerFactory.getLogger(PersonController.class.getName()); 23 | 24 | @Autowired 25 | PersonRepository repository; 26 | @Autowired 27 | CacheManager manager; 28 | 29 | @PostConstruct 30 | public void init() { 31 | try { 32 | logger.info("Cache manager: " + manager); 33 | logger.info("Cache manager names: " + manager.getCacheNames()); 34 | } catch (HazelcastClientOfflineException e) { 35 | logger.error("No Hazelcast connection", e); 36 | } 37 | } 38 | 39 | @GetMapping("/persons/pesel/{pesel}") 40 | public List findByPesel(@PathVariable("pesel") String pesel) { 41 | return repository.findByPesel(pesel); 42 | } 43 | 44 | @GetMapping("/persons/{id}") 45 | public Person findById(@PathVariable("id") Integer id) { 46 | return repository.findById(id).orElseThrow(); 47 | } 48 | 49 | @GetMapping("/persons") 50 | public List findAll() { 51 | return (List) repository.findAll(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /person-service/src/main/java/pl/piomin/services/datagrid/person/data/PersonRepository.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.person.data; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.cache.annotation.Cacheable; 6 | import org.springframework.data.repository.CrudRepository; 7 | 8 | import pl.piomin.services.datagrid.person.model.Person; 9 | 10 | public interface PersonRepository extends CrudRepository { 11 | 12 | @Cacheable("findByPesel") 13 | public List findByPesel(String pesel); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /person-service/src/main/java/pl/piomin/services/datagrid/person/model/Person.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.person.model; 2 | 3 | import jakarta.persistence.Entity; 4 | import jakarta.persistence.GeneratedValue; 5 | import jakarta.persistence.Id; 6 | import org.hibernate.annotations.Cache; 7 | import org.hibernate.annotations.CacheConcurrencyStrategy; 8 | 9 | import java.io.Serializable; 10 | 11 | @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 12 | @Entity 13 | public class Person implements Serializable { 14 | 15 | private static final long serialVersionUID = 3214253910554454648L; 16 | 17 | @Id 18 | @GeneratedValue 19 | private Integer id; 20 | private String firstName; 21 | private String lastName; 22 | private String pesel; 23 | private int age; 24 | 25 | public Integer getId() { 26 | return id; 27 | } 28 | 29 | public void setId(Integer id) { 30 | this.id = id; 31 | } 32 | 33 | public String getFirstName() { 34 | return firstName; 35 | } 36 | 37 | public void setFirstName(String firstName) { 38 | this.firstName = firstName; 39 | } 40 | 41 | public String getLastName() { 42 | return lastName; 43 | } 44 | 45 | public void setLastName(String lastName) { 46 | this.lastName = lastName; 47 | } 48 | 49 | public String getPesel() { 50 | return pesel; 51 | } 52 | 53 | public void setPesel(String pesel) { 54 | this.pesel = pesel; 55 | } 56 | 57 | public int getAge() { 58 | return age; 59 | } 60 | 61 | public void setAge(int age) { 62 | this.age = age; 63 | } 64 | 65 | @Override 66 | public String toString() { 67 | return "Person [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", pesel=" + pesel + "]"; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /person-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: ${PORT:2222} 3 | 4 | spring: 5 | application: 6 | name: person-service 7 | datasource: 8 | url: jdbc:mysql://localhost:33306/datagrid?useSSL=false 9 | username: datagrid 10 | password: datagrid 11 | hikari: 12 | connection-timeout: 2000 13 | initialization-fail-timeout: 0 14 | jpa: 15 | database-platform: org.hibernate.dialect.MySQL8Dialect 16 | # properties: 17 | # hibernate: 18 | # dialect: org.hibernate.dialect.MySQL8Dialect 19 | hibernate: 20 | # dialect: org.hibernate.dialect.MySQL8Dialect 21 | ddl-auto: create 22 | 23 | management: 24 | endpoint: 25 | caches: 26 | enabled: false 27 | #management.endpoints.web.exposure.include: 'health' 28 | #management.endpoint.health: 29 | # show-details: always 30 | # probes: 31 | # enabled: true 32 | 33 | # properties: 34 | # hibernate: 35 | # show_sql: true 36 | # cache: 37 | # use_query_cache: true 38 | # use_second_level_cache: true 39 | # hazelcast: 40 | # instance_name: cache-1 41 | # use_native_client: true 42 | # native_client_address: 192.168.99.100 43 | # native_client_group: dev 44 | # native_client_password: dev-pass 45 | # region: 46 | # factory_class: com.hazelcast.hibernate.HazelcastCacheRegionFactory 47 | 48 | testcontainers: 49 | beans: 50 | startup: parallel 51 | #logging: 52 | # level: 53 | # com.hazelcast: DEBUG 54 | # org.hibernate: DEBUG -------------------------------------------------------------------------------- /person-service/src/test/java/pl/piomin/services/datagrid/person/MysqlAndHazelcastContainersDevMode.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.person; 2 | 3 | import org.springframework.boot.test.context.TestConfiguration; 4 | import org.springframework.boot.testcontainers.service.connection.ServiceConnection; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.test.context.DynamicPropertyRegistry; 7 | import org.testcontainers.containers.GenericContainer; 8 | import org.testcontainers.containers.MySQLContainer; 9 | import org.testcontainers.utility.DockerImageName; 10 | 11 | @TestConfiguration(proxyBeanMethods = false) 12 | public class MysqlAndHazelcastContainersDevMode { 13 | 14 | @Bean 15 | @ServiceConnection 16 | public MySQLContainer mysql() { 17 | return new MySQLContainer<>("mysql:8.0") 18 | .withUsername("datagrid") 19 | .withPassword("datagrid"); 20 | } 21 | 22 | @Bean 23 | public GenericContainer hazelcast(DynamicPropertyRegistry registry) { 24 | GenericContainer hazelcast = new GenericContainer<>(DockerImageName.parse("hazelcast/hazelcast:5.1")) 25 | .withExposedPorts(5701); 26 | registry.add("spring.hazelcast.url", () -> hazelcast.getHost() + ":" + hazelcast.getFirstMappedPort()); 27 | return hazelcast; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /person-service/src/test/java/pl/piomin/services/datagrid/person/PersonDevModeApplication.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.person; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | 5 | public class PersonDevModeApplication { 6 | 7 | public static void main(String[] args) { 8 | SpringApplication.from(PersonApplication::main) 9 | .with(MysqlAndHazelcastContainersDevMode.class) 10 | .run(args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /person-service/src/test/java/pl/piomin/services/datagrid/person/data/AddPersonRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package pl.piomin.services.datagrid.person.data; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.boot.testcontainers.service.connection.ServiceConnection; 7 | import org.springframework.test.context.DynamicPropertyRegistry; 8 | import org.springframework.test.context.DynamicPropertySource; 9 | import org.testcontainers.containers.GenericContainer; 10 | import org.testcontainers.containers.MySQLContainer; 11 | import org.testcontainers.junit.jupiter.Container; 12 | import org.testcontainers.junit.jupiter.Testcontainers; 13 | import org.testcontainers.utility.DockerImageName; 14 | import pl.piomin.services.datagrid.person.model.Person; 15 | 16 | import java.text.DecimalFormat; 17 | import java.util.List; 18 | import java.util.Random; 19 | import java.util.logging.Logger; 20 | 21 | @SpringBootTest 22 | @Testcontainers 23 | public class AddPersonRepositoryTest { 24 | 25 | protected Logger logger = Logger.getLogger(AddPersonRepositoryTest.class.getName()); 26 | 27 | @Autowired 28 | PersonRepository repository; 29 | 30 | @Container 31 | @ServiceConnection 32 | static final MySQLContainer mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0")) 33 | .withUsername("datagrid") 34 | .withPassword("datagrid"); 35 | 36 | @Container 37 | // @ServiceConnection 38 | static final GenericContainer hazelcast = new GenericContainer<>(DockerImageName.parse("hazelcast/hazelcast:5.1")) 39 | .withExposedPorts(5701); 40 | 41 | @DynamicPropertySource 42 | static void hazelcastProperties(DynamicPropertyRegistry registry) { 43 | String url = hazelcast.getHost() + ":" + hazelcast.getFirstMappedPort(); 44 | registry.add("spring.hazelcast.url", () -> url); 45 | } 46 | 47 | @Test 48 | public void add() { 49 | for (int i = 0; i < 1000; i++) { 50 | int ix = new Random().nextInt(100000); 51 | Person p = new Person(); 52 | p.setFirstName("Jan" + ix); 53 | p.setLastName("Testowy" + ix); 54 | p.setPesel(new DecimalFormat("0000000").format(ix) + new DecimalFormat("000").format(i%100)); 55 | p.setAge(ix%100); 56 | p = repository.save(p); 57 | logger.info("Add: " + p); 58 | } 59 | 60 | } 61 | 62 | @Test 63 | void find() { 64 | logger.info("find()"); 65 | List ps = repository.findByPesel("0034919066"); 66 | logger.info("find(): " + ps); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | pl.piomin.services 5 | sample-hazelcast-spring-datagrid 6 | 1.0-SNAPSHOT 7 | pom 8 | 9 | 10 | org.springframework.boot 11 | spring-boot-starter-parent 12 | 3.5.0 13 | 14 | 15 | 16 | 17 | UTF-8 18 | UTF-8 19 | 21 20 | piomin_sample-hazelcast-spring-datagrid 21 | piomin 22 | https://sonarcloud.io 23 | 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-web 29 | 30 | 31 | 32 | 33 | 34 | 35 | com.mysql 36 | mysql-connector-j 37 | runtime 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-test 42 | test 43 | 44 | 45 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-maven-plugin 51 | 52 | 53 | org.jacoco 54 | jacoco-maven-plugin 55 | 0.8.13 56 | 57 | 58 | 59 | prepare-agent 60 | 61 | 62 | 63 | report 64 | test 65 | 66 | report 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | person-service 77 | employee-service 78 | employee-kubernetes-service 79 | 80 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Hazelcast With Spring Boot Demo Project [![Twitter](https://img.shields.io/twitter/follow/piotr_minkowski.svg?style=social&logo=twitter&label=Follow%20Me)](https://twitter.com/piotr_minkowski) 2 | 3 | In this project I'm demonstrating you the most interesting features of [Hazelcast](https://hazelcast.com/) and its integration with Spring Boot and Spring Data to build cache or distributed in-memory data grid. 4 | 5 | ## Getting Started 6 | Currently you may find here some examples of application that integrates Hazelcast with Spring Boot and Spring Data. Some of them are divided into the branches and described in a separated articles on my blog. Here's a full list of available examples: 7 | 1. Using Hazelcast as 2nd level JPA Cache for **Hibernate** and **MySQL** database. The example is available in the branch [master](https://github.com/piomin/sample-hazelcast-spring-datagrid/tree/master). A detailed guide may be find in the following article: [JPA caching with Hazelcast, Hibernate and Spring Boot](https://piotrminkowski.com/2017/05/08/jpa-caching-with-hazelcast-hibernate-and-spring-boot/). 8 | 2. Using Hazelcast with [Striim](https://www.striim.com/) for enabling hot cache between **MySQL** database and in-memory data grid. The example is available in the branch [striim](https://github.com/piomin/sample-hazelcast-spring-datagrid/tree/striim). A detailed guide may be find in the following article: [Hazelcast Hot Cache with Striim](https://piotrminkowski.com/2017/08/09/hazelcast-hot-cache-with-striim/). 9 | 3. Using Hazelcast cluster on **Kubernetes** with Spring Boot. The example is available in the branch [master](https://github.com/piomin/sample-hazelcast-spring-datagrid/tree/master). A detailed guide may be find in the following article: [Hazelcast With Spring Boot on Kubernetes](https://piotrminkowski.com/2020/01/31/hazelcast-with-spring-boot-on-kubernetes/). 10 | 4. Using Hazelcast cluster with Spring Boot that programically stores data in the two sources: **MySQL** and Hazelcast. The example is available in the branch [master](https://github.com/piomin/sample-hazelcast-spring-datagrid/tree/master). A detailed guide may be find in the following article: [In-memory Data Grid with Hazelcast](https://piotrminkowski.com/2017/05/10/in-memory-data-grid-with-hazelcast/). 11 | 12 | ### Usage 13 | 14 | In the most cases you need to have Maven and JDK8+. In the third example with Kubernetes you will have to run **Minikube** on your machine. The best way to run the sample applications is with IDEs like IntelliJ IDEA or Eclipse. 15 | 16 | ## Architecture 17 | 18 | Our sample microservices-based system consists of the following modules: 19 | - **employee-service** - a module which is a simple Spring Boot application for storing `Employee` objects in Hazelcast and MySQL (optionally) 20 | - **person-service** - a module which is a simple Spring Boot application for storing `Person` objects in Hazelcast and MySQL (optionally) 21 | - **employee-service-kubernetes** - a module dedicated only for 3rd example based on Kubernetes. 22 | 23 | The following picture illustrates the architecture for running Hazelcast on Kubernetes (**Minikube**) (**Example 3**). 24 | 25 |
26 | 27 | The following picture illustrates the architecture for running Hazelcast with **Striim** as a hot cache for MySQL database (**Example 2**). 28 | 29 |
30 | 31 | The following picture illustrates the architecture for running Hazelcast with Spring Boot as in-memory data grid that programically stores data in two sources (**Example 4**). 32 | 33 |
34 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base",":dependencyDashboard" 5 | ], 6 | "packageRules": [ 7 | { 8 | "matchUpdateTypes": ["minor", "patch", "pin", "digest"], 9 | "automerge": true 10 | } 11 | ], 12 | "prCreation": "not-pending" 13 | } --------------------------------------------------------------------------------