This guide walks you through the process of building an application with Pivotal GemFire’s data fabric.
What you’ll build
You will use the powerful Spring Data for Pivotal GemFire library to store and retrieve POJOs.
What you’ll need
Define a simple entity
Pivotal GemFire is a In-Memory Data Grid (IMDG) that maps data to Regions. It is possible to configure
distributed Regions that partition and replicate data across multiple nodes in a cluster. However, in this guide,
you will be using a LOCAL
Region so you don’t have to set up anything extra, such as an entire cluster of servers.
Pivotal GemFire is a Key/Value store and a Region implements the java.util.concurrent.ConcurrentMap
interface. Though
you can treat a Region like a java.util.Map
, it is quite a bit more sophisticated than just a simple Java Map
given data is distributed, replicated and generally managed inside the Region.
In this example, you store Person
objects in Pivotal GemFire (a Region) using only a few annotations.
src/main/java/hello/Person.java
link:complete/src/main/java/hello/Person.java[]
Here you have a Person
class with two fields, name
and age
. You also have a single, persistent constructor to
populate the entities when creating a new instance. The class uses Project Lombok
to simplify the implementation.
Notice that this class is annotated with @Region("People")
. When Pivotal GemFire stores an instance of this class,
a new entry is created inside the "People" Region. This class also marks the name
field with @Id
. This signifies
the identifier used to identify and track the Person
data inside Pivotal GemFire. Essentially, the @Id
annotated
field (e.g. name
) is the key and the Person
instance is the value in the key/value entry. There is no automated
key generation in Pivotal GemFire so you must set the id (i.e. name
) prior to persisting the entity to Pivotal GemFire.
The next important piece is the person’s age. Later in this guide, you will use it to fashion some queries.
The overridden toString()
method will print out the person’s name and age.
Create simple queries
Spring Data for Pivotal GemFire focuses on storing and accessing data in Pivotal GemFire using Spring. It also inherits powerful functionality from the Spring Data Commons project, such as the ability to derive queries. Essentially, you don’t have to learn the query language of Pivotal GemFire (OQL); you can simply write a handful of methods and the queries are written for you by the framework.
To see how this works, create an interface that queries Person
objects stored in Pivotal GemFire.
src/main/java/hello/PersonRepository.java
link:complete/src/main/java/hello/PersonRepository.java[]
PersonRepository
extends the CrudRepository
interface from Spring Data Commons and specifies types for
the generic type parameters for both the value and the id (key) that the Repository works with, i.e. Person
and String
, respectively. Out-of-the-box, this interface comes with many operations, including basic CRUD
(CREATE, READ UPDATE, DELETE) and simple query (e.g. findById(..)
) data access operations.
You can define other queries as needed by simply declaring their method signature. In this case, you add findByName
,
which essentially searches for objects of type Person
and finds one that matches on name
.
You also have:
-
findByAgeGreaterThan
to find people above a certain age -
findByAgeLessThan
to find people below a certain age -
findByAgeGreaterThanAndAgeLessThan
to find people in a certain age range
Let’s wire this up and see what it looks like!
Create an application class
Here you create an Application class with all the components.
src/main/java/hello/Application.java
link:complete/src/main/java/hello/Application.java[]
In the configuration, you need to add the @EnableGemfireRepositories
annotation.
-
By default,
@EnableGemfireRepositories
will scan the current package for any interfaces that extend one of Spring Data’s Repository interfaces. Use it’sbasePackageClasses = MyRepository.class
to safely tell Spring Data for Pivotal GemFire to scan a different root package by type for application-specific Repository extensions.
A Pivotal GemFire cache containing 1 or more Regions is required to store all the data. For that, you use 1
of Spring Data for Pivotal GemFire’s convenient configuration-based annotations: @ClientCacheApplication
,
@PeerCacheApplication or `@CacheServerApplication
.
Pivotal GemFire supports different cache topologies like client/server, peer-to-peer (p2p) and even WAN arrangements. In p2p, a peer cache instance is embedded in the application and your application would have the ability to participate in a cluster as peer cache member. However, your application is subject to all the constraints of being a peer member in the cluster, so this is not as commonly used as, say, the client/server topology.
In our case, we will be using @ClientCacheApplication
to create a "client" cache instance, which has the ability to
connect to and communicate with a cluster of servers. However, to keep things simple, the client will just store
data locally using a LOCAL
, client Region, without the need to setup or run any servers.
Note
|
Spring recommends the production, enterprise edition that is Pivotal GemFire, where you can create distributed caches and Regions across multiple nodes in cluster. Alternatively, you can also use the open source version, Apache Geode, and get support from the Apache Geode community. |
Now, remember how you tagged Person
to be stored in a Region called "People" using the SDG mapping annotation,
@Region("People")
? You define that Region here using the ClientRegionFactoryBean<String, Person>
bean definition.
You need to inject an instance of the cache you just defined while also naming it "People".
Note
|
A Pivotal GemFire cache instance (whether a peer or client) is just a container for Regions, which store your data. You can think of the cache as a schema in an RDBMS and Regions as the tables. However, a cache also performs other administrative functions to control and manage all your Regions. |
Note
|
The types are <String, Person> , matching the key type (String ) with the value type (Person ).
|
The public static void main
method uses Spring Boot’s SpringApplication.run()
to launch the application
and invoke the ApplicationRunner
(another bean definition) that performs the data access operations on Pivotal GemFire
using the application’s Spring Data Repository.
The application autowires an instance of PersonRepository
that you just defined. Spring Data for Pivotal GemFire
will dynamically create a concrete class that implements this interface and plug in the needed query code to meet
the interface’s obligations. This Repository instance is the used by the run()
method to demonstrate
the functionality.
Store and fetch data
In this guide, you are creating three local Person
objects, Alice, Baby Bob, and Teen Carol. Initially,
they only exist in memory. After creating them, you have to save them to Pivotal GemFire.
Now you run several queries. The first looks up everyone by name. Then you execute a handful of queries to find adults, babies, and teens, all using the age attribute. With the logging turned up, you can see the queries Spring Data for Pivotal GemFire writes on your behalf.
Tip
|
change the @ClientCacheApplication annotation logLevel attribute to "config" to see the Pivotal GemFire
OQL queries that are generated by SDG. Because the query methods (e.g. findByName ) are annotated with SDG’s @Trace
annotation, this turns on Pivotal GemFire’s OQL query tracing (query-level logging), which shows you the generated OQL,
execution time, whether any Pivotal GemFire Indexes were used by the query to gather the results, and the number of rows
returned by the query.
|
You should see something like this (with other stuff like queries as well):
Before linking up with GemFire... Alice is 40 years old. Baby Bob is 1 years old. Teen Carol is 13 years old. Lookup each person by name... Alice is 40 years old. Baby Bob is 1 years old. Teen Carol is 13 years old. Adults (over 18): Alice is 40 years old. Babies (less than 5): Baby Bob is 1 years old. Teens (between 12 and 20): Teen Carol is 13 years old.
Summary
Congratulations! You set up an Pivotal GemFire cache client, stored simple entities, and developed quick queries.