Building a Spring Data Application with GigaSpaces

Reference Download

Spring Data Moore SR3

Spring Framework 5.2.2

Spring Data GigaSpaces

Overview

This topic explains how to build a Spring data application with GigaSpaces, using the Spring Data GigaSpaces library to store and retrieve POJOs.

In order to build a Spring data application with GigaSpaces, you have to do the following:

  • Install GigaSpaces, Maven, and the GigaSpaces Maven artifacts (or use the Maven repository)
  • Install and build the Spring Data GigaSpaces project
  • Populate and test the Space
  • Create a program and begin to read and write objects

The following software versions were used for this implementation:

  • GigaSpaces release 15.0
  • Spring version 5.2.2

Preparing the Environment

Installing GigaSpaces

The first step in preparing your environment is installing the GigaSpaces product, and then installing Maven and the GigaSpaces Maven artifacts.

To install GigaSpaces:

  1. Download the GigaSpaces product you want to use from the Download Center and install it as described in the Next Level section of the GigaSpaces documentation.

  2. Install Apache Maven as described in the Maven documentation.

    If you're not familiar with Maven, refer to the topic on Building Java Projects with Maven in the Spring documentation.

  3. Install the GigaSpaces Maven artifacts using the following GigaSpaces CLI command:

    maven install

Installing and Building the Spring Data GigaSpaces Project

After you set up the GigaSpaces data grid and Maven artifacts, you need to build a new Maven project using the spring-data-gigaspaces software package.

To install and build the Spring Data GigaSpaces project:

  1. Download the spring-data-gigaspaces project and build it with Maven, using the following command:

    mvn clean install
  2. Copy and paste the code snippet below into your build. This gets you started using spring-data-gigaspaces in your project with a dependency management system.

    <dependencies>
        <dependency>
             <groupId>org.springframework.data</groupId>
             <artifactId>spring-data-gigaspaces</artifactId>
             <version>15.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

Populating and Testing the Space

Defining a Simple Entity

GigaSpaces' in-memory data grid stores data in Spaces. Each Space can be configured as needed (replicated, partitioned, etc). For the Spring GigaSpaces

project, we use an embedded Space that is running as part of your program (there is no need to run a separate data grid).

The following example shows how to store Book objects.

import com.gigaspaces.annotation.pojo.SpaceClass;
import com.gigaspaces.annotation.pojo.SpaceId;
import java.io.Serializable;

@SpaceClass
public class Book implements Serializable {
   String id;
   String author;
   Integer copies;

   public Book() {
   }

   public Book(String id, String author, Integer copies) {
       this.id = id;
       this.author = author;
       this.copies = copies;
   }

   public String getAuthor() {
       return author;
   }

   public void setAuthor(String author) {
       this.author = author;
   }

   @SpaceId(autoGenerate = false)
   public String getId() {
       return id;
   }

   public void setId(String id) {
       this.id = id;
   }

   public Integer getCopies() {
       return copies;
   }

   public void setCopies(Integer copies) {
       this.copies = copies;
   }

   @Override
   public String toString() {
       return "Book{" + "id='" + id + '\'' + ", author='" + author + '\'' + ", copies=" + copies + '}';
   }
}

The example has the following attributes:

  • A Book class with three attributes; id, author, and copies. It also contains a constructor to populate the entities when creating a new instance, and the default constructor.
  • The Book class is annotated @SpaceClass. The annotation is not mandatory and you can write objects to the Space without it, but it is used to provide additional metadata.
  • The Book class also has a getter for id marked with @SpaceId. This property uniquely identifies the object within the Space, and is similar to a primary key in a database.
  • The number of book copies is defined. This is used when creating simple queries, as described below.
  • The toString() method prints out the book's id, author and copies.

Creating Simple Queries

The Spring Data GigaSpaces project focuses on storing data in the GigaSpaces data grid. It also inherits powerful functionality from the Spring Data Commons project, such as the ability to derive queries. This means that you don't have to learn the query language of the data grid, but can just write a handful of methods and the queries are generated for you.

To see how this works, lets create an interface that queries Book Space objects.

import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface BookRepository extends CrudRepository<Book, String> {
   List<Book> findByAuthor(String author);

   List<Book> findByCopiesLessThan(Integer copies);

   List<Book> findByAuthorOrCopiesGreaterThan(String author, Integer copies);
}

The BookRepository extends the CrudRepository interface and plugs in the type of values and keys with Book and String. Out of the box, this interface comes with many operations, including standard CRUD (Create, Read, Update, Delete) operations.

You can define other queries as needed by declaring their method signature. In this case, we add findByAuthor, which searches for entities of type Book and finds the those that matches with Author.

The following queries are also available:

  • findByCopiesLessThan to find books with a number of copies below a certain number
  • findByAuthorOrCopiesGreaterThan to find books with a certain author or number of copies above a certain number

At this point, we can put everything together and build the actual Spring Data application.

Building the Application

Creating your Program

After you have prepared your environment and populated the Space with some test data, you can create the Program class with all the components, and then run your application. For example, see the code example below, which has the following characteristics:

  • The @EnableGigaspacesRepositories annotation is added to the configuration.
  • The Space is required to store all data, which is done using the Spring Data GigaSpaces SpaceClient bean.
  • The types are <String, Book>, matching the key type (String) with the value type (Book).
  • The public static void main uses Spring Boot's SpringApplication.run() to launch the application and invoke the CommandLineRunner that builds the relationships.
  • The application autowires an instance of BookRepository that you just defined. Spring Data GigaSpaces dynamically creates a concrete class that implements that interface, and plugs 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.
  • To run the application, add --spring.main.allow-bean-definition-overriding=true --spring.main.web-application-type=nonein your Program arguments.
import org.openspaces.core.GigaSpace;
import org.openspaces.core.GigaSpaceConfigurer;
import org.openspaces.core.space.UrlSpaceConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.data.gigaspaces.repository.config.EnableGigaspacesRepositories;
import org.springframework.data.gigaspaces.repository.support.GigaspacesRepositoryFactory;

import java.io.IOException;

@Configuration
@EnableGigaspacesRepositories
public class Application implements CommandLineRunner {
   @Autowired
   BookRepository bookRepository;

   @Bean
   GigaSpace spaceClient() {
       UrlSpaceConfigurer urlConfigurer = new UrlSpaceConfigurer("/./testSpace");
       return new GigaSpaceConfigurer(urlConfigurer).gigaSpace();
   }

   @Bean
   BookRepository bookRepository() {
       RepositoryFactorySupport factory = new GigaspacesRepositoryFactory(spaceClient(), null);
       return factory.getRepository(BookRepository.class);
   }

   @Override
   public void run(String... strings) throws Exception {
       Book thinkingInJava = new Book("1234", "Eccel", 10000);
       Book effectiveJava = new Book("2345", "Bloch", 20000);
       Book springInAction = new Book("3456", "Walls", 50000);
       System.out.println("Before writing objects to space...");
       for (Book book : new Book[]{thinkingInJava, effectiveJava, springInAction}) {
           System.out.println("\t" + book);
       }
       bookRepository.save(thinkingInJava);
       bookRepository.save(effectiveJava);
       bookRepository.save(springInAction);
       System.out.println("Lookup books by author...");
       for (String name : new String[]{thinkingInJava.author, effectiveJava.author, effectiveJava.author}) {
           System.out.println("\t" + bookRepository.findByAuthor(name));
       }
       System.out.println("Lookup for less popular books...");
       for (Book book : bookRepository.findByCopiesLessThan(15000)) {
           System.out.println("\t" + book);
       }
       System.out.println("Lookup for popular books or books of specific author...");
       for (Book book : bookRepository.findByAuthorOrCopiesGreaterThan("Bloch", 30000)) {
           System.out.println("\t" + book);
       }
       System.exit(0);
   }

   public static void main(String[] args) throws IOException {
       SpringApplication.run(Application.class, args);
   }
}

In the above example, the Space is created locally using built-in components and an evaluation license. For a production solution, use the production version of GigaSpaces, where you can create distributed Spaces across multiple nodes.

Writing and Reading Objects

You can create some Book instances, such as SpringInAction, ThinkingInJava, and EffectiveJava. Initially, they only exist in memory. After creating them, we store them in the Space. After the Book instances are created, you can run queries on them, for example:

  • Look up books by author
  • Find less popular books
  • Find popular books or books written by a specific author

You should see something like this:

13:25:42.393 [main] INFO  com.gigaspaces.space.testSpace - Space started [duration=11.668s, url=/./testSpace?schema=default&groups=xap-15.0.0&state=started, policy=all-in-cache, persistency-mode=memory]
13:25:43.435 [main] INFO  hello.QuickStartTest - Started QuickStartTest in 15.79 seconds (JVM running for 20.418)
Before writing objects to space...
	Book{id='1234', author='Eccel', copies=10000}
	Book{id='2345', author='Bloch', copies=20000}
	Book{id='3456', author='Walls', copies=50000}
Lookup books by author...
	[Book{id='1234', author='Eccel', copies=10000}]
	[Book{id='2345', author='Bloch', copies=20000}]
	[Book{id='2345', author='Bloch', copies=20000}]
Lookup for less popular books...
	Book{id='1234', author='Eccel', copies=10000}
Lookup for popular books or books of specific author...
	Book{id='2345', author='Bloch', copies=20000}
	Book{id='3456', author='Walls', copies=50000}