Apache Ignite and Spring on your Kubernetes Cluster Part 1: Spring Boot application
On a previous series of blogs we spun up an Ignite cluster on a Kubernetes cluster.
In this tutorial we shall use the Ignite cluster created previously on with a Spring Boot Application.
Let’s create our project using Spring Boot. The Spring Boot application will connect to the Ignite cluster.
Let’s add our dependencies.
<?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.gkatzioura</groupId> <artifactId>job-api-ignite</artifactId> <version>0.0.1-SNAPSHOT</version> <name>job-api-ignite</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.apache.ignite</groupId> <artifactId>ignite-kubernetes</artifactId> <version>2.7.6</version> </dependency> <dependency> <groupId>org.apache.ignite</groupId> <artifactId>ignite-spring</artifactId> <version>2.7.6</version> <exclusions> <exclusion> <groupId>org.apache.ignite</groupId> <artifactId>ignite-indexing</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
As in previous tutorials we shall use GitHub’s Job api.
The first step would be to add the Job Model that deserializes.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 | package com.gkatzioura.jobapi.model; import java.io.Serializable; import lombok.Data; @Data public class Job implements Serializable { private String id; private String type; private String url; private String createdAt; private String company; private String companyUrl; private String location; private String title; private String description; } |
The we need a repository for the Jobs. Beware the class needs to be serializable. Ignite caches data off-heap.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | package com.gkatzioura.jobapi.repository; import java.util.ArrayList; import java.util.List; import com.gkatzioura.jobapi.model.Job; import lombok.Data; import org.apache.ignite.Ignite; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Repository; import org.springframework.web.client.RestTemplate; @Repository public class GitHubJobRepository { private static final String JOB_API_CONSTANST = "https://jobs.github.com/positions.json?page={page}" ; public static final String GITHUBJOB_CACHE = "githubjob" ; private final RestTemplate restTemplate; private final Ignite ignite; GitHubJobRepository(Ignite ignite) { this .restTemplate = new RestTemplate(); this .ignite = ignite; } @Cacheable (value = GITHUBJOB_CACHE) public List<Job> getJob( int page) { return restTemplate.getForObject(JOB_API_CONSTANST,JobList. class ,page); } public List<Job> fetchFromIgnite( int page) { for (String cache: ignite.cacheNames()) { if (cache.equals(GITHUBJOB_CACHE)) { return (List<Job>) ignite.getOrCreateCache(cache).get( 1 ); } } return new ArrayList<>(); } @Data private static class JobList extends ArrayList<Job> { } } |
The main reason the JobList class exists is for convenience for unmarshalling.
As you can see the repository has the annotation @Cacheable. This mean that our requests will be cached. The fetchFromIgnite method is a test method for the sake of this example. We shall use it to access the data cached by ignite directly.
We shall also add the controller.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | package com.gkatzioura.jobapi.controller; import java.util.List; import com.gkatzioura.jobapi.model.Job; import com.gkatzioura.jobapi.repository.GitHubJobRepository; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping ( "/jobs" ) public class JobsController { private final GitHubJobRepository gitHubJobRepository; JobsController(GitHubJobRepository gitHubJobRepository) { this .gitHubJobRepository = gitHubJobRepository; } @GetMapping ( "/github/{page}" ) public List<Job> gitHub( @PathVariable ( "page" ) int page) { return this .gitHubJobRepository.getJob(page); } @GetMapping ( "/github/ignite/{page}" ) public List<Job> gitHubIgnite( @PathVariable ( "page" ) int page) { return this .gitHubJobRepository.fetchFromIgnite(page); } } |
Two methods on the controller, the one to fetch the data as usual and caches them behind the scenes and the other on that we shall use for testing.
It’s time for us to configure the Ignite client that uses the nodes on our Kubernetes cluster.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | package com.gkatzioura.jobapi.config; import lombok.extern.slf4j.Slf4j; import org.apache.ignite.Ignite; import org.apache.ignite.Ignition; import org.apache.ignite.cache.spring.SpringCacheManager; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; import org.apache.ignite.spi.discovery.tcp.ipfinder.kubernetes.TcpDiscoveryKubernetesIpFinder; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @EnableCaching @Slf4j public class SpringCacheConfiguration { @Bean public Ignite igniteInstance() { log.info( "Creating ignite instance" ); TcpDiscoveryKubernetesIpFinder tcpDiscoveryKubernetesIpFinder = new TcpDiscoveryKubernetesIpFinder(); tcpDiscoveryKubernetesIpFinder.setNamespace( "default" ); tcpDiscoveryKubernetesIpFinder.setServiceName( "job-cache" ); TcpDiscoverySpi tcpDiscoverySpi = new TcpDiscoverySpi(); tcpDiscoverySpi.setIpFinder(tcpDiscoveryKubernetesIpFinder); IgniteConfiguration igniteConfiguration = new IgniteConfiguration(); igniteConfiguration.setDiscoverySpi(tcpDiscoverySpi); igniteConfiguration.setClientMode( false ); return Ignition.start(igniteConfiguration); } @Bean public SpringCacheManager cacheManager(Ignite ignite) { SpringCacheManager springCacheManager = new SpringCacheManager(); springCacheManager.setIgniteInstanceName(ignite.name()); return springCacheManager; } } |
We created our cache. It shall use the Kubernetes TCP discovery mode.
The next step is to add our Main class.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | package com.gkatzioura.jobapi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCaching; @SpringBootApplication @EnableCaching public class IgniteKubeClusterApplication { public static void main(String[] args) { SpringApplication.run(IgniteKubeClusterApplication. class , args); } } |
The next blog will be focused on shipping the solution to kubernetes.
Published on Java Code Geeks with permission by Emmanouil Gkatziouras, partner at our JCG program. See the original article here: Apache Ignite and Spring on your Kubernetes Cluster Part 1: Spring Boot application Opinions expressed by Java Code Geeks contributors are their own. |