Data

Spring Data GemFire Tutorial

Welcome to the Spring Data GemFire tutorial. GemFire is a product from Pivotal. Pivotal Gemfire is an in-memory data grid powered by Apache Geode. Here is a quote from the Pivotal GemFire documentation:

Pivotal GemFire is a data management platform that provides real-time, consistent access to data-intensive applications throughout widely distributed cloud architectures.

GemFire pools memory, CPU, network resources, and optionally local disk across multiple processes to manage application objects and behavior. It uses dynamic replication and data partitioning techniques to implement high availability, improved performance, scalability, and fault tolerance. In addition to being a distributed data container, GemFire is an in-memory data management system that provides reliable asynchronous event notifications and guaranteed message delivery.

Spring Data GemFire makes it easier to build highly scalable, Spring-powered applications using Pivotal GemFire for distributed data management.

1. Suggested Reading

Here are some articles that will help you better understand this tutorial.

  1. Spring Data for Pivotal GemFire
  2. Pivotal GemFire Documentation
  3. Apache Geode

2. Tools

  1. Apache Maven
  2. Eclipse Oxygen
  3. Spring Boot
  4. Spring Data for Pivotal GemFire

3. Assumptions

This article assumes that you know your way around Eclipse. You are familiar with Maven. Familiarity with Spring Data is handy but not required. Basically, you have done some coding. This project has been created using Eclipse Oxygen so all instructions are based on this IDE.

4. Project Setup

To start, we create our project. This can be done by going to File -> New -> Maven Project and fill up what is required. Alternatively, we can import the Maven project by going to File -> Import… and picking the project.

5. Project Object Model

Our pom.xml should look like the one below:

pom.xml

<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">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.javacodegeeks.example</groupId>
  <artifactId>spring-data-gemfire</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
	  <version>2.0.3.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-gemfire</artifactId>
	  <version>2.0.8.RELEASE</version>
      </dependency>
    </dependencies>

    <repositories>
      <repository>
        <id>spring-libs-release</id>
        <name>Spring Releases</name>
        <url>https://repo.spring.io/libs-release</url>
        <snapshots>
          <enabled>false</enabled>
        </snapshots>
      </repository>
    </repositories>
</project>

As shown above, our project has 2 dependencies. We are using spring-boot-starter which means that we can use all the Spring modules included in it. For example, the Spring Core and Spring Boot modules will be available for us to use plus many more. We’ll use Spring Boot so that we won’t have to do dabble with XML configuration and we can create a stand-alone Spring application. The next dependency is spring-data-gemfire which contains all the libraries we need to create our Spring powered GemFire application. In Eclipse, we can see the dependency hierarchy by opening the pom.xml and clicking on the Dependency Hierarchy tab.

6. Define an Entity

Our example is about blogs. The first thing we need to do is create a Blog object and annotate it as Region. GemFire is an IMDG that maps data to Regions. This data will be mapped to the Blog Region.

Blog.java

package com.javacodegeeks.example;

import java.io.Serializable;

import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.gemfire.mapping.annotation.Region;

@Region(value = "Blog")
public class Blog implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	private final String url;
	
	private String title;
	
	@PersistenceConstructor
	public Blog(String url, String title) {
		this.url = url;
		this.title = title;
	}

	public String getUrl() {
		return url;
	}

	public String getTitle() {
		return title;
	}
	
	public void setTitle(String title) {
		this.title = title;
	}

	@Override
	public String toString() {
		return "Blog [url=" + url + ", title=" + title + "]";
	}
	
}

This class is fairly easy to understand. It has getters, setters, a constructor, a toString method, and some fields. The @PersistenceConstructor populates the entity when creating a new instance. This new entity will be created in the “Blog” Region. The url field is the key of the Blog instance because of the @Id annotation. It’s similar to the java.util.Map key-value concept.

Below, we will configure the Region as ClientRegionShortcut.LOCAL so that we don’t need to set up multiple nodes in a cluster.

7. Create a Repository Interface

We extend the CrudRepository interface to take advantage of Spring Data’s features. Spring Data has the ability to derive queries so we don’t have to learn the query language of GemFire. The methods we write are converted by Spring Data into GemFire queries.

BlogRepository.java

package com.javacodegeeks.example;

import org.springframework.data.gemfire.repository.query.annotation.Trace;
import org.springframework.data.repository.CrudRepository;

public interface BlogRepository extends CrudRepository<Blog, String> {
	@Trace
	Blog findByTitle(String title);
}

The generic parameters that CrudRepository works with are of type Blog and String. Because we extended CrudRepository, we inherit several methods for working with Blog persistence. We are able to create, read, update, and delete Blog entities.

We have also defined our own query method by simply declaring the method signature (findByTitle). The @Trace annotation enables GemFire OQL query debugging.

8. Create the Main Class

Our code below performs the four basic CRUD operations. Skim through the code below but peruse the explanation after it.

Main.java

package com.javacodegeeks.example;

import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
import org.springframework.data.gemfire.config.annotation.EnableEntityDefinedRegions;
import org.springframework.data.gemfire.repository.config.EnableGemfireRepositories;
import org.apache.geode.cache.client.ClientRegionShortcut;

@SpringBootApplication
@ClientCacheApplication(name="CrudGemFireExample", logLevel = "fatal") // the pivotal gemfire cache
@EnableEntityDefinedRegions(basePackageClasses = Blog.class, clientRegionShortcut = ClientRegionShortcut.LOCAL) // enable the creation of Pivotal GemFire/Apache Geode Regions based on the application persistent entities
@EnableGemfireRepositories
public class Main {
	
	public static void main(String args[]) {
		SpringApplication.run(Main.class, args);
	}

	@Bean
	ApplicationRunner run(BlogRepository blogRepo) {
		
		System.out.println("Spring Data GemFire example");
		
		Blog example = new Blog("http://example.com", "Example");
		Blog jcg = new Blog("http://javacodegeeks.com", "JCG");
		Blog dzone = new Blog("https://dzone.com", "Dzone");
		
		// create
		blogRepo.save(example);
		blogRepo.save(jcg);
		blogRepo.save(dzone);
		
		// read
		blogRepo.findAll().forEach(blog -> System.out.println(blog));
		
		// find by title
		System.out.println("Finding JCG...");
		Blog temp = blogRepo.findByTitle("JCG");
		System.out.println(temp);

		// update
		temp.setTitle("new JCG");
		blogRepo.save(temp);
		System.out.println("JCG updated...");
		blogRepo.findAll().forEach(blog -> System.out.println(blog));
		
		// delete
		System.out.println("Deleting Example");
		temp = blogRepo.findByTitle("Example");
		blogRepo.delete(temp);
		blogRepo.findAll().forEach(blog -> System.out.println(blog));
		
		return null;
	}
}

The @ClientCacheApplication is one of GemFire’s convenient configuration-based annotation. This tells us that this is a GemFire cache client and its name in the cluster is CrudGemFireExample. It will only output fatal log messages.
The @EnableEntityDefinedRegions enables the creation of Pivotal GemFire/Apache Geode Regions based on the application persistent entities. We have defined the Region as ClientRegionShortcut.LOCAL so that we won’t need to run any servers and the client will just store the data locally. The basePackageClasses specifies the packages to scan for @Region annotated persistent entities. The package of each class specified will be scanned.
The @EnableGemfireRepositories annotation enables GemFire repositories. This means that Spring will scan the current package for any interfaces that extend one of Spring Data’s Repository interfaces.
The public static void main method uses Spring Boot’s SpringApplication.run() to run the application and invoke the ApplicationRunner that performs our CRUD operations on GemFire. The BlogRepository has been autowired by Spring.

9. Spring Data GemFire Output

After running the code above (Run As -> Java Application), we should have an output that looks like the one below.

Console Output

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.3.RELEASE)

[info 2018/07/29 11:27:56.284 BST  tid=0x1] No active profile set, falling back to default profiles: default

[info 2018/07/29 11:27:56.482 BST  tid=0x1] Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@43f02ef2: startup date [Sun Jul 29 11:27:56 BST 2018]; root of context hierarchy

Spring Data GemFire example
Blog [url=https://dzone.com, title=Dzone]
Blog [url=http://javacodegeeks.com, title=JCG]
Blog [url=http://example.com, title=Example]
Finding JCG...
Blog [url=http://javacodegeeks.com, title=JCG]
JCG updated...
Blog [url=https://dzone.com, title=Dzone]
Blog [url=http://javacodegeeks.com, title=new JCG]
Blog [url=http://example.com, title=Example]
Deleting Example
Blog [url=https://dzone.com, title=Dzone]
Blog [url=http://javacodegeeks.com, title=new JCG]

The output shows the CRUD operations being performed. We created 3 blog objects. We read the blog objects from the in-memory GemFire cache. Then we searched the cache for a title. After that, we updated the “JCG” title, changing it from “JCG” to “new JCG”. Then we deleted the “Example” blog object. Easy peasy lemon squeezy.

10. Spring Data GemFire Summary

In summary, we include the spring-data-gemfire dependency to make available all the Spring modules we need to make GemFire operations. We define an entity, in this case a Blog class. Next, we created a repository interface by extending Spring’s CrudRepository. Finally, we wire everything up in the main application class.

11. Download the Source Code

This is an example about Spring Data GemFire.

Download
You can download the source code of this example here: spring-data-gemfire.zip.

Joel Patrick Llosa

I graduated from Silliman University in Dumaguete City with a degree in Bachelor of Science in Business Computer Application. I have contributed to many Java related projects at Neural Technologies Ltd., University of Southampton (iSolutions), Predictive Technologies, LLC., Confluence Service, North Concepts, Inc., NEC Telecom Software Philippines, Inc., and NEC Technologies Philippines, Inc. You can also find me in Upwork freelancing as a Java Developer.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button