Aerospike 8 introduces a new era of real-time transaction processingLearn more
Blog

Spring Data Aerospike 5.0.0: Important updates

February 6, 2025 | 6 min read
Untitled
Andrey Grosland
Software Engineer

As discussed in Part I, the latest release of Spring Data Aerospike, version 5.0.0, brings a number of new features and enhancements. This blog will dive into some of the major updates to the current functionality: update in application.properties, custom queries API, applying filter expression as secondary index fallback, and limiting the minimally supported Aerospike Server version to 6.1.0.0. In the meantime, if you're upgrading from Spring Data Aerospike 4.8.0 to 5.0.0, be sure to check out the migration guide at the end of this post for a step-by-step transition plan.

For further insights into the new capabilities, such as supporting transactions, byte array equality queries, cacheable sync option, and filter expression fallback be sure to read our accompanying blog, Spring Data Aerospike 5.0.0: New features.

Updated parameters in application properties

In a Spring project, externalized configuration parameters are often defined with specific prefixes to organize and manage settings efficiently. These prefixes help group related properties and ensure that the configuration is modular and easy to maintain. They are used when overriding default values through external property files, enhancing flexibility in configuration management.

Starting with Spring Data Aerospike 5.0.0, parameters in application.properties are updated to better reflect grouping and also to simplify and follow a more conventional approach. Their prefixes now are spring.aerospike* and spring.data.aerospike*.

For details see Configuration documentation.

Updated custom queries API

The previous Spring Data Aerospike versions utilized both regular and custom query methods. Regular query methods are added to interfaces that extend AerospikeRepository. Such methods serve various use cases and can be created using different criteria. However, they have their limits regarding readability and maintainability.

To provide more flexibility, a custom queries mechanism has been introduced in Spring Data Aerospike. It allows you to create complex queries in a readable manner.

Spring Data Aerospike 5.0.0 brings an update to the custom queries API. Let’s look at the examples.

Examples

Let’s consider the following complex query: find all Person entities whose names are equal to “John” or “Jack,” the primary key is “key1” or “key2,” and the record’s last update time is after midnight (12 a.m.) on January 10th, 2023. 

Test data will contain a Person named “John” that will satisfy the conditions of this complex query.

static final Person john = new Person(“key2”, "John");

We will build separate Qualifiers, which will be combined into a Query. The query will then be passed to a findUsingQuery() method.

Firstly we create a qualifier "name is equal to John".

Qualifier nameEqJohn = Qualifier.builder()
    	.setPath("name")
    	.setFilterOperation(FilterOperation.EQ)
    	.setValue("John")
   	.build();

Then we create another qualifier "name is equal to Jack".

Qualifier nameEqJack = Qualifier.builder()
    	.setPath("name")
    	.setFilterOperation(FilterOperation.EQ)
    	.setValue("Jack")
   	.build();

Now create a qualifier "primary key is equal to key1".

Qualifier keyEqKey1 = Qualifier.idEquals(“key1”);

Then a qualifier "primary key is equal to key2."

Qualifier keyEqKey2 = Qualifier.idEquals(“key2”);

Qualifier keyEqKey2 = Qualifier.idEquals(“key2”);

Now, it’s time to create a metadata qualifier: "last_update_time value is after 12 a.m. on January 10th, 2023."

Qualifier lastUpdateTimeAfter2023Jan10 = Qualifier.metadataBuilder()
	.setMetadataField(LAST_UPDATE_TIME)
   	.setFilterOperation(FilterOperation.GT)
	// Epoch timestamp in nanoseconds: 10 Jan 2023 00:00:00 GMT
	.setValue(1673308800000 * 1_000_000)
	.build();

We are combining name and primary key qualifiers using logical OR.

Qualifier name = Qualifier.or(firstNameEqJohn, firstNameEqJack);

Qualifier key = Qualifier.or(keyEqKey1, keyEqKey2);

Now we combine previously created qualifiers using logical AND to wrap them in a Query and pass to findUsingQuery method. The method returns a List of Person objects with one element that satisfies the query’s conditions.

List<Person> result = repository.findUsingQuery(
	new Query(Qualifier.and(name, key, lastUpdateTimeAfter2023Jan10))
);
Person john = new Person(“key1”, “John”);
assertThat(result).containsOnly(john);

Applying filter expression as secondary index filter fallback

In NoSQL databases such as Aerospike, a secondary index plays a crucial role in improving query performance by enabling faster lookups on non-primary key attributes. Unlike the primary index, which is typically based on the unique identifier (such as a document ID), a secondary index allows for efficient searches on other fields (bins in Aerospike terminology) within the data.

Let us first see an example of a query using a matching secondary index.

Examples

An instance of Person named dave is created with predefined values.

static final Person dave = new Person(“id2”, "Dave");

A secondary index is created with the correct index type “STRING” referring to the “firstName” bin.

repository.createIndex(Person.class, "person_firstName_index", "firstName", IndexType.STRING);

The query runs bringing the correct results.

List<Person> result = template.findByFirstName(“Dave”);
assertThat(result).containsOnly(dave);

There can be situations, however, when a specific bin is referenced by an incompatible secondary index. For instance, a numeric index pointing to a String bin, and so on.

In the previous versions of Spring Data Aerospike, having such a discrepancy led to getting an AerospikeException with an “Index not found” message. Starting with the Spring Data Aerospike release 5.0.0, there is a fallback mechanism in place that retries to run a query once more using just a filter expression (i.e. a scan operation) if a secondary index-related issue has occurred. In that case, there will be a warning log message printed: “Got secondary index related exception (resultCode: …), retrying with filter expression only (scan operation)”.

Note: Fallback to “filter expression only” results in slower query performance.

Let us see an example of a query using an incompatible secondary index.

If a secondary index is created with index type “NUMERIC” referring to the String “firstName” bin, the query runs using filter expression only.

repository.createIndex(Person.class, "person_firstName_index", "firstName", IndexType.NUMERIC); // The matching type must be STRING


List<Person> result = template.findByFirstName(“Dave”);
assertThat(result).containsOnly(dave);

Limiting the minimal Aerospike server version

Spring Data Aerospike uses the Aerospike Java client, which obviously needs an installed Aerospike Server to connect to.

As with any software, Aerospike releases introduce new features and performance enhancements. To ensure compatibility with the latest features and improvements, leverage performance optimizations, and streamline maintenance, the oldest Aerospike Server version supported by Spring Data Aerospike is now 6.1.0.0.

Users are encouraged to upgrade to 6.1.* or a higher version of Aerospike Server to ensure compatibility and access to the latest improvements.

Migration guide

This guide outlines the steps for migrating from Spring Data Aerospike version 4.8.0 to 5.0.0.

1. Update dependencies

  • Modify your pom.xml file:

Update the Spring Data Aerospike dependency version to the latest release:

<dependency>
   <groupId>com.aerospike</groupId>
   <artifactId>spring-data-aerospike</artifactId>
   <version>5.0.0</version>
</dependency>
  • It is recommended to update Spring dependencies to 3.4.2.

2. Configuration changes

  • application.properties:

4.8.0

5.0.0

Migration steps

spring-data-aerospike.connection.hosts

spring.aerospike.hosts

Rename properties

spring-data-aerospike.connection.namespace

spring.data.aerospike.namespace

" "

spring-data-aerospike.data.scans-enabled

spring.data.aerospike.scans-enabled

" "

spring.data-aerospike.data.send-key

spring.data.aerospike.send-key

" "

spring-data-aerospike.data.create-indexes-on-startup

spring.data.aerospike.create-indexes-on-startup

" "

spring-data-aerospike.data.index-cache-refresh-seconds

spring.data.aerospike.index-cache-refresh-seconds

" "

spring-data-aerospike.data.server-version-refresh-seconds

spring.data.aerospike.server-version-refresh-seconds

" "

spring-data-aerospike.data.query-max-records

spring.data.aerospike.query-max-records

" "

spring-data-aerospike.data.batch-write-size

spring.data.aerospike.batch-write-size

" "

spring-data-aerospike.data.keep-original-key-types

spring.data.aerospike.keep-original-key-type

" "

  • customConverters method (if it is in use):

4.8.0

5.0.0

Migration steps

@Override protected List<?> customConverters()

@Override protected List<Object> customConverters()

Update method signature

3. Removed exception

IndexAlreadyExistsException is removed, it is no longer needed due to the fact that the minimal supported Aerospike Server version is 6.1.

Learn more about Spring Data Aerospike 5.0.0

To learn more about the Spring Data Aerospike project, explore our GitHub page, which provides comprehensive information. For additional insights, check out the release notes for Spring Data Aerospike 5.0.0.

Aerospike Server Enterprise and Standard Edition

Aerospike Server Enterprise and Standard Edition are available as a package for various Linux distributions. Each package contains an installer for Aerospike Server and Aerospike Tools. After downloading a package, refer to the Installation Guide for package installation details.