# Technical Documentation: spring-projects/spring-data-examples

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/spring-projects/spring-data-examples)

### Overview (`multi-store/README.md`)

# Spring Data - Multi-store example

This sample shows a project working with multiple Spring Data modules and how the repository auto-detection has become stricter with the Evans release train.

If you run `ApplicationConfigurationTest` you should see the following output:

```
… DEBUG … - Multiple Spring Data modules found, entering strict repository configuration mode!
… 
… DEBUG … - Spring Data JPA - Could not safely identify store assignment for repository candidate interface example.springdata.multistore.shop.OrderRepository.
… DEBUG … - Spring Data JPA - Registering repository: customerRepository - Interface: example.springdata.multistore.customer.CustomerRepository - Factory: org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean
… DEBUG … - Multiple Spring Data modules found, entering strict repository configuration mode!
…
… DEBUG … - Spring Data MongoDB - Could not safely identify store assignment for repository candidate interface example.springdata.multistore.customer.CustomerRepository.
… DEBUG … - Spring Data MongoDB - Registering repository: orderRepository - Interface: example.springdata.multistore.shop.OrderRepository - Factory: org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean
```

As you can see, Spring Data detects the fact that the application runs on multiple Spring Data modules. This triggers the strict configuration mode in which only repository interfaces will be detected that can be uniquely assigned to the module currently scanned. By default this assignment is detected by inspecting the managed domain type for store specific annotations (e.g. `@Entity` for JPA or `@Document` for MongoDB).

---

### Overview (`cassandra/kotlin/README.md`)

# Spring Data Cassandra - Kotlin examples

This project contains samples of Kotlin-specific features of Spring Data (Cassandra).

## Value defaulting on entity construction

Kotlin allows defaulting for constructor- and method arguments. 
Defaulting allows usage of substitute values if a field in the document is absent or simply `null`. 
Spring Data inspects objects whether they are Kotlin types and uses the appropriate constructor.

```kotlin
@Table
data class Person(@PrimaryKeyColumn(type = PrimaryKeyType.PARTITIONED) val firstname: String? = "", val lastname: String = "White")

operations.cqlOperations.execute(QueryBuilder.insertInto("person").value("firstname", "Walter"))

val person = operations.query<Person>()
				.matching(query(where("firstname").isEqualTo("Walter")))
				.firstValue()!!

assertThat(person.lastname).isEqualTo("White")
```

## Kotlin Extensions

Spring Data exposes methods accepting a target type to either query for or to project results values on. 
Kotlin represents classes with its own type, `KClass` which can be an obstacle when attempting to obtain a Java `Class` type.

Spring Data ships with extensions that add overloads for methods accepting a type parameter by either leveraging generics or accepting `KClass` directly.

```kotlin
operations.getTableName<Person>()
 
operations.getTableName(Person::class)
```

## Nullability

Declaring repository interfaces using Kotlin allows expressing nullability constraints on arguments and return types. Spring Data evaluates nullability of arguments and return types and reacts to these. Passing `null` to a non-nullable argument raises an `IllegalArgumentException`, as you're already used to from Kotlin. Spring Data helps you also to prevent `null` in query results. If you wish to return a nullable result, use Kotlin's nullability marker `?`. To prevent `null` results, declare the return type of a query method as non-nullable. In the case a query yields no result, a non-nullable query method throws `EmptyResultDataAccessException`.  

```kotlin
interface PersonRepository : CrudRepository<Person, String> {

	/**
	 * Query method declaring a nullable return type that allows to return null values.
	 */
	fun findOneOrNoneByFirstname(firstname: String): Person?

	/**
	 * Query method declaring a nullable argument.
	 */
	fun findNullableByFirstname(firstname: String?): Person?

	/**
	 * Query method requiring a result. Throws [org.springframework.dao.EmptyResultDataAccessException] if no result is found.
	 */
	fun findOneByFirstname(firstname: String): Person
}
```

---

### Overview (`cassandra/reactive/README.md`)

# Spring Data Cassandra 2.0 - Reactive examples

This project contains samples of reactive data access features with Spring Data (Cassandra).

## Reactive Template API usage with `ReactiveCassandraTemplate`

The main reactive Template API class is `ReactiveCassandraTemplate`, ideally used through its interface `ReactiveCassandraOperations`. It defines a basic set of reactive data access operations using [Project Reactor](http://projectreactor.io) `Mono` and `Flux` reactive types.

```java
template.insert(Flux.just(new Person("Walter", "White", 50),
				new Person("Skyler", "White", 45),
				new Person("Saul", "Goodman", 42),
				new Person("Jesse", "Pinkman", 27)));

Flux<Person> flux = template.select(select()
                                         .from("person")
                                         .where(eq("lastname", "White")), Person.class);
```

The test cases in `ReactiveCassandraTemplateIntegrationTest` show basic Template API usage.
Reactive data access reads and converts individual elements while processing the stream.


## Reactive Repository support

Spring Data Cassandra provides reactive repository support with Project Reactor and RxJava 1 reactive types. The reactive API supports reactive type conversion between reactive types.

```java
public interface ReactivePersonRepository extends ReactiveCrudRepository<Person, String> {

	Flux<Person> findByLastname(String lastname);

	@Query("SELECT * FROM person WHERE firstname = ?0 and lastname  = ?1")
	Mono<Person> findByFirstnameAndLastname(String firstname, String lastname);

	// Accept parameter inside a reactive type for deferred execution
	Flux<Person> findByLastname(Mono<String> lastname);

	Mono<Person> findByFirstnameAndLastname(Mono<String> firstname, String lastname);
}
```

```java
public interface RxJava1PersonRepository extends RxJava1CrudRepository<Person, String> {

	Observable<Person> findByLastname(String lastname);

	@Query("SELECT * FROM person WHERE firstname = ?0 and lastname  = ?1")
	Single<Person> findByFirstnameAndLastname(String firstname, String lastname);

	// Accept parameter inside a reactive type for deferred execution
	Observable<Person> findByLastname(Single<String> lastname);

	Single<Person> findByFirstnameAndLastname(Single<String> firstname, String lastname);
}
```

---

### Overview (`cassandra/vector-search/README.md`)

# Spring Data for Apache Cassandra - Vector Search Example

This project
contains [Vector Search](https://docs.spring.io/spring-data/cassandra/reference/5.0/cassandra/repositories/vector-search.html)
with Spring Data for Apache Cassandra.

## Vector Support

The Spring Data `Vector` type can be used in repository query methods.
Domain type properties of managed domain types are required to use a numeric array representation for embeddings.

```java

@Table
public class Comment {

    @Id
    private String id;

    private String country;
    private String description;

    @SaiIndexed
    @VectorType(dimensions = 5)
    private Vector embedding;

    // ...
}


public interface CommentRepository extends Repository<Comment, String> {

    SearchResults<Comment> searchTop10ByEmbeddingNear(Vector embedding, ScoringFunction function);
}
```

This example contains a test class to illustrate vector search with a Repository in `CassandraVectorSearchTest`.

---

### Overview (`couchbase/example/README.md`)

# Spring Data Couchbase - Examples

This project contains samples of data access features with Spring Data (Couchbase).

## Prerequisites

The examples require a running [Couchbase Server](https://www.couchbase.com/downloads) with the travel sample bucket imported. We assume you're running Couchbase 6.5 and we have updated the `application.properties` class accordingly to adapt RBAC authentication.

For more information, see the [official documentation](https://docs.spring.io/spring-data/couchbase/docs/current/reference/html/#reference).

---

### Overview (`couchbase/reactive/README.md`)

# Spring Data Couchbase 4.0 - Reactive examples

This project contains samples of reactive data access features with Spring Data (Couchbase).


## Reactive Repository support

Spring Data Couchbase provides reactive repository support with Project Reactor:

```java
public interface ReactiveAirlineRepository extends ReactiveCrudRepository<Airline, String> {

    Mono<Airline> findByIata(String code);

    Flux<Airline> findAllBy();
}
```

For more information, see the [official documentation](https://docs.spring.io/spring-data/couchbase/docs/current/reference/html/#reference).

---

### Overview (`couchbase/transactions/README.md`)

# Getting Started

### Running the Sample

* `$> docker run -d --name db -p 8091-8097:8091-8097 -p 11210:11210 -p 11207:11207 -p 18091-18095:18091-18095 -p 18096:18096 -p 18097:18097 couchbase`
* Create new _cluster_ via `http://localhost:8091/`
* Create new [bucket](http://localhost:8091/ui/index.html#/buckets) named _travel-sample_.
* 

### Reference Documentation
For further reference, please consider the following sections:

* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.5.2/maven-plugin/reference/html/)
* [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.5.2/maven-plugin/reference/html/#build-image)
* [Spring Data Couchbase](https://docs.spring.io/spring-boot/docs/2.5.2/reference/htmlsingle/#boot-features-couchbase)

---

### Overview (`elasticsearch/example/README.md`)

# Spring Data Elasticsearch - Examples

Requirements:

 * [Maven](http://maven.apache.org/download.cgi) - required.
 * [Elasticsearch](http://www.elasticsearch.org/overview/elkdownloads) - optional.


To use local elasticsearch cluster:

* install elasticsearch 
* Adapt 'application.properties' to point to your elasticsearch cluster

---

### Overview (`elasticsearch/reactive/README.md`)

# Spring Data Elasticsearch - Reactive Examples

The `ReactiveElasticsearchClient` is a client based on `WebClient`. 
It uses the request/response objects provided by the Elasticsearch core project. 
Calls are directly operated on the reactive stack, not wrapping async (thread pool bound) responses into reactive types.

```java
@SpringBootApplication
class ApplicationConfiguration {}
```

The `ReactiveElasticsearchClient` can be used with the `ReactiveElasticsearchOperations` and `ReactiveElasticsearchRepository`.

```java
@Autowired ReactiveElasticsearchOperations operations;

// ...

CriteriaQuery query = new CriteriaQuery("keywords").contains("java");

Flux<Conference> result = operations.find(query, Conference.class);
```

```java
interface ConferenceRepository extends ReactiveCrudRepository<Conference, String> {
 
    Flux<Conference> findAllByKeywordsContains(String keyword);
}

// ...

@Autowired ConferenceRepository repository;

// ...

Flux<Conference> result = repository.findAllByKeywordsContains("java");
```


**Requirements:**

 * [Maven](http://maven.apache.org/download.cgi)
 * [Elasticsearch](https://www.elastic.co/de/downloads/elasticsearch)

**Running Elasticsearch** 

```bash
$ cd elasticsearch
$ ./bin/elasticsearch
```

---

### Overview (`jpa/jpa21/README.md`)

# Spring Data JPA - JPA 2.1 example

This project contains samples of JPA 2.1 specific features of Spring Data JPA.

## Support for declarative Fetch Graphs customization

You can customize the loading of entity associations via EntityGraphs. JPA 2.1 provides the `NamedEntityGraph` annotation
that allows you to define fetching behavior in a flexible way.

In Spring Data JPA we support to specify which fetch-graph to use for a repository query method via the `EntityGraph` annotation.

You can refer to a fetch graph by name like in the following example.
```java
@EntityGraph("product-with-tags")
Product findOneById(Long id);
```

We also offer an alternative and more concise way to declaratively specify a fetch graph for a repository query method in an 
ad-hoc manner:
```java
@EntityGraph(attributePaths = "tags")
Product getOneById(Long id);
```
By explicitly specifying which associations to fetch via the `attributePaths` attribute you don't need to specify a 
`NamedEntityGraph` annotation on your entity :)

## Support for stored procedure execution

You can execute stored procedures either predefined using the JPA 2.1 mapping annotations or dynamically let the stored procedure definition be derived from the repository method name.

Stored procedure declaration in the database (schema.sql):

```sql
DROP procedure IF EXISTS plus1inout
/;
CREATE procedure plus1inout (IN arg int, OUT res int)
BEGIN ATOMIC
    set res = arg + 1;
END
/;
```

JPA 2.1 stored procedure declaration:

```java
@Entity
@NamedStoredProcedureQuery(name = "User.plus1", procedureName = "plus1inout", parameters = {
  @StoredProcedureParameter(mode = ParameterMode.IN, name = "arg", type = Integer.class),
  @StoredProcedureParameter(mode = ParameterMode.OUT, name = "res", type = Integer.class) })
public class User {

    @Id @GeneratedValue//
    private Long id;
}

```

Spring Data JPA repository declaration to execute procedures:

```java
public interface UserRepository extends CrudRepository<User, Long> {

  // Explicitly mapped to named stored procedure {@code User.plus1} in the {@link EntityManager}.
  // By default, we would've tried to find a procedure declaration named User.plus1BackedByOtherNamedStoredProcedure
  @Procedure(name = "User.plus1")
  Integer plus1BackedByOtherNamedStoredProcedure(@Param("arg") Integer arg);

  // Directly map the method to the stored procedure in the database (to avoid the annotation madness on your domain classes).
  @Procedure
  Integer plus1inout(Integer arg);
}
```

Calling `UserRepository.plus1BackedByOtherNamedStoredProcedure(…)` will execute the stored procedure `plus1inout` using the meta-data declared on the `User` domain class.

`UserRepository.plus1inout(…)` will derive stored procedure metadata from the repository and default to positional parameter binding and expect a single output parameter of the backing stored procedure.

## Support for custom SqlResultSetMapping with ConstructorResult

Sometimes, e.g. for analytics, it is handy to be able to return a different entity result type from a Repository query method than the base Repository entity type or an interface based projection.

In those cases one can leverage JPAs `SqlResultSetMapping` feature to map the columns of the result of a query to different fields.

JPA 2.1 introduced the new `SqlResultSetMapping` type `ConstructorResult` which allows to map columns of a result set row to a constructor invocation
which can be nicely used in combination with Value Objects.

This example shows how to define a custom `SqlResultSetMapping` for the result of an analytical native query that reports the usage summary for a set of Subscriptions.

`SqlResultSetMapping` definition on the `Subscription` entity class:
```java
@Entity
@NoArgsConstructor
@SqlResultSetMapping(
  name = "subscriptionSummary",
  classes = @ConstructorResult(
    targetClass = SubscriptionSummary.class,
    columns = {
      @ColumnResult(name = "productName", type = String.class),
      @ColumnResult(name = "subscriptions", type = long.class)
}))
@NamedNativeQuery(
  name = "Subscription.findAllSubscriptionSummaries",
  query = "select product_name as productName, count(user_id) as subscriptions from subscription group by product_name order by productName",
  resultSetMapping = "subscriptionSummary"
)
@Data
public class Subscription {
  …
}
```

`SubscriptionSummary` is modelled as a value object:
```java
@Value
public class SubscriptionSummary {

  String product;
  Long usageCount;
}
```

The `SubscriptionRepository` declares the custom query method `findAllSubscriptionSummaries` which is backed by the named native query declared on the `Subscription` entity.
```java
interface SubscriptionRepository extends CrudRepository<Subscription,Long> {

  @Query(nativeQuery = true)
  List<SubscriptionSummary> findAllSubscriptionSummaries();
}
```

---

### Overview (`jpa/multiple-datasources/README.md`)

# Spring Data JPA - Multiple datasources example

This project contains an example of how to set up Spring Data to work with two independent databases. Note, that this example is not about JTA transactions spanning multiple databases but rather just interacting with separate databases through a cleanly separated domain model and Spring Data repositories.

## Interesting points to look at

To connect to two databases we need to manually configure a `DataSource`, `EntityManagerFactory` and `JpaTransactionManager`. This is done in `CustomerConfig` and `OrderConfig`. `DataInitializer` then simulates a Spring component interacting with those databases in separate methods. `Application.init()` orchestrates calls to those methods.

---

### Overview (`jpa/query-by-example/README.md`)

# Spring Data JPA - Query-by-Example (QBE) example

This project contains samples of Query-by-Example of Spring Data JPA.

## Support for Query-by-Example

Query by Example (QBE) is a user-friendly querying technique with a simple interface. It
allows dynamic query creation and does not require to write queries containing field
names. In fact, Query by Example does not require to write queries using JPA-QL at all.

An `Example` takes a data object (usually the entity object or a subtype of it) and a
specification how to match properties. You can use Query by Example with JPA Repositories.

```java
public interface PersonRepository extends CrudRepository<Person, String>, QueryByExampleExecutor<Person> {
}
```

```java
Example<Person> example = Example.of(new Person("Jon", "Snow"));
repo.findAll(example);


ExampleMatcher matcher = ExampleMatcher.matching().
    .withMatcher("firstname", endsWith())
    .withMatcher("lastname", startsWith().ignoreCase());

Example<Person> example = Example.of(new Person("Jon", "Snow"), matcher); 
repo.count(example);
```

This example contains a test class to illustrate Query-by-Example with a Repository
in `UserRepositoryIntegrationTests`.

---

### Overview (`jpa/vector-search/README.md`)

# Spring Data JPA - Vector Search Example

This project contains [Vector Search](https://docs.spring.io/spring-data/jpa/reference/4.0/repositories/vector-search.html) with Spring Data JPA and the `hibernate-vector` module.

## Vector Support

The Spring Data `Vector` type can be used in repository query methods.
Domain type properties of managed domain types are required to use a numeric array representation for embeddings.

```java

@Entity
@Table(name = "jpa_comment")
public class Comment {

    @Id
    @GeneratedValue private Long id;

    private String country;
    private String description;

    @JdbcTypeCode(SqlTypes.VECTOR)
    @Array(length = 5)
    private float[] embedding;

    // ...
}


public interface CommentRepository extends Repository<Comment, String> {

    SearchResults<Comment> searchTop10ByCountryAndEmbeddingNear(String country, Vector vector, Score distance);
}
```

This example contains a test class to illustrate vector search with a Repository in `JpaVectorSearchTest`.

---

### Overview (`ldap/example/README.md`)

# Spring Data LDAP - Example

This project contains samples of Spring Data (LDAP).


```java
public interface PersonRepository extends CrudRepository<Person, Name> {

  List<Person> findByUid(String uid);

  List<Person> findByLastnameStartsWith(String prefix);
}
```

The test cases in `PersonRepositoryIntegrationTests` show basic interaction to search, create and modify objects stored in an LDAP repository.

---

### Overview (`mongodb/aggregation/README.md`)

# Spring Data MongoDB - Aggregations

This project contains samples for using MongoDB [Aggregations](https://docs.mongodb.com/manual/aggregation/) 
showing both the programmatic and declarative approach for integrating an Aggregation Pipeline into a repository.

## Programmatic

The programmatic approach uses a [custom repository](https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#repositories.custom-implementations) implementation along with the [Aggregation Framework](https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo.aggregation).

```java
class OrderRepositoryImpl implements OrderRepositoryCustom {

	private MongoOperations operations;
	
	// ...

	@Override
	public Invoice getInvoiceFor(Order order) {

		AggregationResults<Invoice> results = operations.aggregate(newAggregation(Order.class, 
			match(where("id").is(order.getId())), 
			unwind("items"), 
			project("id", "customerId", "items") 
				.andExpression("'$items.price' * '$items.quantity'").as("lineTotal"), 
			group("id") 
				.sum("lineTotal").as("netAmount") 
				.addToSet("items").as("items"), 
			project("id", "items", "netAmount") 
				.and("orderId").previousOperation() 
				.andExpression("netAmount * [0]", taxRate).as("taxAmount") 
				.andExpression("netAmount * (1 + [0])", taxRate).as("totalAmount") 
		), Invoice.class);

		return results.getUniqueMappedResult();
	}
}
```

## Declarative

The [declarative approach](https://docs.spring.io/spring-data/mongodb/docs/2.2.0.RC2/reference/html/#mongodb.repositories.queries.aggregation) allows to define an Aggregation Pipeline via the `@Aggregation` annotation.

```java
public interface OrderRepository extends CrudRepository<Order, String>, OrderRepositoryCustom {

	@Aggregation("{ $group : { _id : $customerId, total : { $sum : 1 } } }")
	List<OrdersPerCustomer> totalOrdersPerCustomer(Sort sort);

	@Aggregation(pipeline = { "{ $match : { customerId : ?0 } }", "{ $count : total }" })
	Long totalOrdersForCustomer(String customerId);
}
```

---

### Overview (`mongodb/change-streams/README.md`)

# Spring Data MongoDB - Change Streams Example

This project contains usage samples for consuming MongoDB 3.6 [Change Streams](https://docs.mongodb.com/manual/changeStreams/) using the imperative as well as the reactive MongoDB Java drivers.

### Imperative Style

Change stream events can be consumed using a `MessageListener` registered within a `MessageListenerContainer`. The container takes care of running the task in a separate `Thread` pushing events to the `MessageListener`.

```java
@Configuration
class Config {

	@Bean
	MessageListenerContainer messageListenerContainer(MongoTemplate template) {
		return new DefaultMessageListenerContainer(template);
	}
}
```

Once the `MessageListenerContainer` is in place `MessageListeners` can be registered.

```java
MessageListener<ChangeStreamDocument<Document>, Person> messageListener = (message) -> {
	System.out.println("Hello " + message.getBody().getFirstname());
};

ChangeStreamRequest<Person> request = ChangeStreamRequest.builder()
	.collection("person")
	.filter(newAggregation(match(where("operationType").is("insert"))))
	.publishTo(messageListener)
	.build();

Subscription subscription = messageListenerContainer.register(request, Person.class);

// ...
```

### Reactive Style

Change stream events be directly consumed via a `Flux` connected to the change stream.

```java
Flux changeStream = reactiveTemplate
	.changeStream(newAggregation(match(where("operationType").is("insert"))),
				Person.class, ChangeStreamOptions.empty(), "person");
				
changeStream.doOnNext(event -> System.out.println("Hello " + event.getBody().getFirstname()))
	.subscribe();
```

---

### Overview (`mongodb/example/README.md`)

# Spring Data MongoDB - Example

This project contains examples for:

* Derived query method and geospatial queries using a `Repository` interface.
* Usage of property-specific converters.
* `EntityCallback` API usage for before convert/save interaction.
* Result projections for DTOs and interface types.
* Bulk write to multiple collections.
* Query metadata.
* Unwrapping entities into the parent document.

---

### Overview (`mongodb/fluent-api/README.md`)

# Spring Data MongoDB 2.0 - FluentMongoOperations Example

This project contains usage samples of `FluentMongoOperations`.

## Fluent API

`FluentMongoOperations` provides a stripped down, more focused API alternative for classic `MongoOperations`.
The main entry points are typical tasks for finding and manipulating ``Document``s on a domain type base, while operations like creating indexes are left out.

For convenience classic `MongoOperations` extend `FluentMongoOperations`, however for most cases it might be sufficient to just work with the reduced interface.
To get started just inject `FluentMongoOperations`.

The entry point methods of `FluentMongoOperations` provide you with an immutable fluent API allowing only valid next steps while constructing the operation to execute. This allows to set up operations once and keep those in memory for multiple executions.

### Query

Looking at the following `query(SWCharacter.class)`.

`SWCharacter` is used for mapping the query properties to the actual document field names. As the `SWCharacter` defines `@Field("firstname") name;` the `where` clause of the query is mapped to the MongoDB representation as `{ firstname : "luke" }`.

Using `as(Jedi.class)` switches return type mapping from `SWCharacter` to `Jedi` which allows to map resulting documents to a different type than the one used for query mapping.

So far no actual query execution has been invoked. Calling on of the terminating methods like `one()`, `first()`, `all()`,... triggers the query.

```java
mongoOps.query(SWCharacter.class)
  .inCollection("star-wars")
  .as(Jedi.class)
  .matching(query(where("name").is("luke")))
  .one();

```

Different stages in the command assembly process allow to seamlessly switch to different API paths. Using `near` instead of `matching` switches to the path for geo queries requiring the presence of a `NearQuery` while altering the command result type from `List` to `GeoResults` and limiting terminating operations to just `all()`.

```java

NearQuery alderaanWithin3Parsecs = NearQuery.near(-73.9667, 40.78)
  .maxDistance(new Distance(3, MILES))
  .spherical(true);

GeoResults<Jedi> results = mongoOps.query(SWCharacter.class)
  .as(Jedi.class)
  .near(alderaanWithin3Parsecs)
  .all();
```


### Update

Looking at the following `update(Jedi.class)`.

`Jedi` already defines the `collection` via the `@Document` annotation, so there is no need to explicitly specify a collection name via `inCollection(String)`. The `Jedi` domain type is also used for query and update mapping.

So far no actual query execution has been invoked. Calling on of the terminating methods like `all()`, `upsert()`, `findAndModify()`, etc. triggers the update.
```java


mongoOps.update(Jedi.class)
  .matching(query(where("lastname").is("windu")))
  .apply(update("name", "mence"))
  .upsert();
```

---

### Overview (`mongodb/geo-json/README.md`)

# Spring Data MongoDB - GeoJSON examples

This project contains samples of [GeoJSON](http://geojson.org) specific features of Spring Data (MongoDB).

## Support for GeoJSON types in domain classes

Using [GeoJSON](http://geojson.org) types in domain classes is straight forward. The `org.springframework.data.mongodb.core.geo` package contains types like `GeoJsonPoint` or `GeoJsonPolygon` which are extensions to the existing `org.springframework.data.geo` types.
Find more information in the [MongoDB manual on GeoJSON support](http://docs.mongodb.org/manual/core/2dsphere/#geospatial-indexes-store-geojson) to learn about requirements and restrictions.

```java
public class Store {

	String id;

	/**
	 * location is stored in GeoJSON format.
	 * {
	 *   "type" : "Point",
	 *   "coordinates" : [ x, y ]
	 * }
	 */
	GeoJsonPoint location;
}
```

## Support for GeoJSON types in repository methods

Using GeoJson types as repository query parameters forces usage of the `$geometry` operator when creating the query.

```java
public interface StoreRepository extends CrudRepository<Store, String> {

	List<Store> findByLocationWithin(Polygon polygon);
}
```

```java
/* {
 *   "location": {
 *     "$geoWithin": {
 *       "$geometry": {
 *         "type": "Polygon",
 *         "coordinates": [
 *           [
 *             [-73.992514,40.758934],
 *             [-73.961138,40.760348],
 *             [-73.991658,40.730006],
 *             [-73.992514,40.758934]
 *           ]
 *         ]
 *       }
 *     }
 *   }
 * }
 */
repo.findByLocationWithin(
  new GeoJsonPolygon(
    new Point(-73.992514, 40.758934),
    new Point(-73.961138, 40.760348),
    new Point(-73.991658, 40.730006),
    new Point(-73.992514, 40.758934)));

/* {
 *   "location" : {
 *     "$geoWithin" : {
 *        "$polygon" : [ [ -73.992514, 40.758934 ] , [ -73.961138, 40.760348 ] , [ -73.991658, 40.730006 ] ]
 *     }
 *   }
 * }
 */
repo.findByLocationWithin(
  new Polygon(
    new Point(-73.992514, 40.758934),
    new Point(-73.961138, 40.760348),
    new Point(-73.991658, 40.730006));
```

---

### Overview (`mongodb/gridfs/README.md`)

# Spring Data MongoDB - GridFS example

This project contains an example of [GridFS](https://docs.mongodb.com/v3.4/core/gridfs/) specific features of Spring Data (MongoDB).

## Support for storing a file

Using [GridFsOperations](http://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/gridfs/GridFsOperations.html) to store a file.

```java
InputStream is = ...
gridFsOperations.store(is, "myFile1.txt");
```

## Support for query a file by name

Using [GridFsOperations](http://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/gridfs/GridFsOperations.html) to query a GridFSDBFile by its filename.

```java
GridFSDBFile gridFsFile = gridFsOperations.findOne(query(whereFilename().is("myFile1.txt")));
```

## Support for storing a file with metadata

Using [GridFsOperations](http://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/gridfs/GridFsOperations.html) to store a file with additional metadata..

```java
InputStream is = ...
Customer customerMetaData = new Customer("Hardy", "Lang");
gridFsOperations.store(is, "myCustomerFile.txt", customerMetaData);

```

## Support for query a file by metadata

Using [GridFsOperations](http://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/gridfs/GridFsOperations.html) to query a GridFSDBFile by metadata.

```java
GridFSDBFile gridFsFile = gridFsOperations.findOne(query(whereMetaData("firstName").is("Hardy")));
```

---

### Overview (`mongodb/kotlin/README.md`)

# Spring Data MongoDB - Kotlin examples

This project contains samples of Kotlin-specific features of Spring Data (MongoDB).

## Value defaulting on entity construction

Kotlin allows defaulting for constructor- and method arguments. 
Defaulting allows usage of substitute values if a field in the document is absent or simply `null`. 
Spring Data inspects objects whether they are Kotlin types and uses the appropriate constructor.

```kotlin
data class Person (@Id val id: String?, val firstname: String? = "Walter", val lastname: String)

operations.insert<Document>().inCollection("person").one(Document("lastname", "White"))

val walter = operations.findOne<Document>(query(where("lastname").isEqualTo("White")), "person")

assertThat(walter.firstname).isEqualTo("Walter")
```

## Kotlin Extensions

Spring Data exposes methods accepting a target type to either query for or to project results values on. 
Kotlin represents classes with its own type, `KClass` which can be an obstacle when attempting to obtain a Java `Class` type.

Spring Data ships with extensions that add overloads for methods accepting a type parameter by either leveraging generics or accepting `KClass` directly.

```kotlin
operations.getCollectionName<Person>()
 
operations.getCollectionName(Person::class)
```

## Nullability

Declaring repository interfaces using Kotlin allows expressing nullability constraints on arguments and return types. Spring Data evaluates nullability of arguments and return types and reacts to these. Passing `null` to a non-nullable argument raises an `IllegalArgumentException`, as you're already used to from Kotlin. Spring Data helps you also to prevent `null` in query results. If you wish to return a nullable result, use Kotlin's nullability marker `?`. To prevent `null` results, declare the return type of a query method as non-nullable. In the case a query yields no result, a non-nullable query method throws `EmptyResultDataAccessException`.  

```kotlin
interface PersonRepository : CrudRepository<Person, String> {

	/**
	 * Query method declaring a nullable return type that allows to return null values.
	 */
	fun findOneOrNoneByFirstname(firstname: String): Person?

	/**
	 * Query method declaring a nullable argument.
	 */
	fun findNullableByFirstname(firstname: String?): Person?

	/**
	 * Query method requiring a result. Throws [org.springframework.dao.EmptyResultDataAccessException] if no result is found.
	 */
	fun findOneByFirstname(firstname: String): Person
}
```

## Type-Safe Kotlin Mongo Query DSL

Using the `Criteria` extensions allows to write type-safe queries via an idiomatic API.

```kotlin
operations.find<Person>(Query(Person::firstname isEqualTo "Tyrion"))
```

## Coroutines and Flow support

```kotlin
runBlocking {
	operations.find<Person>(Query(where("firstname").isEqualTo("Tyrion"))).awaitSingle()
}
```

```kotlin
runBlocking {
	operations.findAll<Person>().asFlow().toList()
}
```

---

### Overview (`mongodb/linking/README.md`)

# Spring Data MongoDB - Linking Example

This project contains examples for linking Documents using:

* `@DBRef`
* `@DocumentReference`

## DBRef

Use MongoDB native `dbref` for storing associations.

```java
class Manager {
	
    @DBRef
    private List<Employee> employees;

    // ...
}
```

## DocumentReference

Link documents via their id.

```java
class Manager {
	
    @DocumentReference
    private List<Employee> employees;

    // ...
}
```

Link documents via a (non _id_) property.

```java
class Manager {
	
    @DocumentReference(lookup = "{ 'name' : ?#{#target} }")
    private List<Employee> employees;

    // ...
}
```

Link documents JPA style.

```java
class Manager {

    @ReadOnlyProperty
    @DocumentReference(lookup="{'managerId':?#{#self._id} }")
    private List<Employee> employees;

    // ...
}
```
----

For more information please refer to the [Reference Documentation](https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mapping-usage-references).

---

### Overview (`mongodb/query-by-example/README.md`)

# Spring Data MongoDB - Query-by-Example (QBE) example

This project contains samples of Query-by-Example of Spring Data MongoDB.

## Support for Query-by-Example

Query by Example (QBE) is a user-friendly querying technique with a simple interface. It
allows dynamic query creation and does not require to write queries containing field
names. In fact, Query by Example does not require to write queries using BSON at all.

An `Example` takes a data object (usually the entity object or a subtype of it) and a
specification how to match properties. You can use Query by Example with `MongoOperations`
and Repositories.

```java
interface PersonRepository extends CrudRepository<Person, String>, QueryByExampleExecutor<Person> {
}
```

```java
Example<Person> example = Example.of(new Person("Jon", "Snow"));
repo.findAll(example);


ExampleMatcher matcher = ExampleMatcher.matching().
    .withMatcher("firstname", endsWith())
    .withMatcher("lastname", startsWith().ignoreCase());

Example<Person> example = Example.of(new Person("Jon", "Snow"), matcher); 
repo.count(example);
```

This example contains two test classes to illustrate Query-by-Example with `MongoOperations` in `MongoOperationsIntegrationTests` and the usage with a Repository in `UserRepositoryIntegrationTests`.

---

### Overview (`mongodb/querydsl/README.md`)

# Spring Data MongoDB - Querydsl example

This project contains samples of [Querydsl](https://github.com/querydsl/querydsl) usage in Spring Data MongoDB.

Querydsl is a framework which enables the construction of fluent, type-safe queries for multiple backends including MongoDB.
Spring Data integrates with Querydsl via `QuerydslPredicateExecutor` and its reactive counterpart `ReactiveQuerydslPredicateExecutor`. 

**NOTE**: You may have to run `mvn compile` to generate the required `Q` classes first.

## Imperative

```java
interface CustomerQuerydslRepository 
        extends CrudRepository<Customer, String>, QuerydslPredicateExecutor<Customer> { }

@Autowired CustomerQuerydslRepository repository;

// ...

List<Customer> result = repository.findAll(QCustomer.customer.lastname.eq("Matthews"));
```

## Reactive

```java
interface ReactiveCustomerQuerydslRepository
		extends ReactiveCrudRepository<Customer, String>, ReactiveQuerydslPredicateExecutor<Customer> { }
		
@Autowired ReactiveCustomerQuerydslRepository repository;

// ...

Flux<Customer> result = repository.findAll(QCustomer.customer.lastname.eq("Matthews"));
```

---

### Overview (`mongodb/reactive/README.md`)

# Spring Data MongoDB 2.0 - Reactive examples

This project contains samples of reactive data access features with Spring Data (MongoDB).

## Prerequisites

MongoDB requires the Reactive Streams driver to provide reactive data access.
The Reactive Streams driver maintains its own connections. Using Spring Data MongoDB Reactive support
together with blocking Spring Data MongoDB data access will open multiple connections to your MongoDB servers.

## Reactive Template API usage with `ReactiveMongoTemplate`

The main reactive Template API class is `ReactiveMongoTemplate`, ideally used through its interface `ReactiveMongoOperations`. It defines a basic set of reactive data access operations using [Project Reactor](http://projectreactor.io) `Mono` and `Flux` reactive types.

```java
template.insertAll(Arrays.asList(new Person("Walter", "White", 50),
				new Person("Skyler", "White", 45),
				new Person("Saul", "Goodman", 42),
				new Person("Jesse", "Pinkman", 27)));

Flux<Person> flux = template.find(Query.query(Criteria.where("lastname").is("White")), Person.class);
```

The test cases in `ReactiveMongoTemplateIntegrationTest` show basic Template API usage.
Reactive data access reads and converts individual elements while processing the stream.


## Reactive Repository support

Spring Data MongoDB provides reactive repository support with Project Reactor and RxJava 2 reactive types. The reactive API supports reactive type conversion between reactive types.

```java
public interface ReactivePersonRepository extends ReactiveCrudRepository<Person, String> {

	Flux<Person> findByLastname(String lastname);

	@Query("{ 'firstname': ?0, 'lastname': ?1}")
	Mono<Person> findByFirstnameAndLastname(String firstname, String lastname);

	// Accept parameter inside a reactive type for deferred execution
	Flux<Person> findByLastname(Mono<String> lastname);

	Mono<Person> findByFirstnameAndLastname(Mono<String> firstname, String lastname);

	@Tailable // Use a tailable cursor
	Flux<Person> findWithTailableCursorBy();
}
```

```java
public interface RxJava2PersonRepository extends RxJava2CrudRepository<Person, String> {

	Flowable<Person> findByLastname(String lastname);

	@Query("{ 'firstname': ?0, 'lastname': ?1}")
	Maybe<Person> findByFirstnameAndLastname(String firstname, String lastname);

	// Accept parameter inside a reactive type for deferred execution
	Flowable<Person> findByLastname(Single<String> lastname);

	Maybe<Person> findByFirstnameAndLastname(Single<String> firstname, String lastname);

	@Tailable // Use a tailable cursor
	Flowable<Person> findWithTailableCursorBy();
}
```

---

### Overview (`mongodb/repository-metrics/README.md`)

# Spring Data MongoDB 3.1 - Repository Metrics

Configure a `RepositoryMethodInvocationListener` to capture invocation metrics on `Repository` interfaces.

```java

@Configuration(proxyBeanMethods = false)
class RepositoryMetricsConfiguration {

	@Bean
	public RepoMetricsPostProcessor repoMetricsPostProcessor() {
		return new RepoMetricsPostProcessor();
	}

	static class RepoMetricsPostProcessor implements BeanPostProcessor {

		@Override
		public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

			if (bean instanceof RepositoryFactoryBeanSupport<?, ?, ?> repositoryFactoryBean) {

				repositoryFactoryBean
						.addRepositoryFactoryCustomizer(repositoryFactory -> {
							repositoryFactory
									.addInvocationListener(System.out::println);  // register the invocation listener
						});
			}

			return bean;
		}
	}
}
```

---

### Overview (`mongodb/schema-validation/README.md`)

# Spring Data MongoDB 2.1 - Schema & Validation Example

MongoDB (as of version 3.2) supports validating documents against a given structure described by a query. 

```json
{
    "name" : {
        "$exists" : true,
        "$ne" : null,
        "$type" : 2
    },
    "age" : {
        "$exists" : true,
        "$ne" : null,
        "$type" : 16,
        "$gte" : 0,
        "$lte" : 125
    }
}
```

The structure can be built from `Criteria` objects in the same way as they are used for defining queries.

```java
Validator.criteria(where("name").exists(true).ne(null).type(2)
	.and("age").exists(true).ne(null).type(16).gte(0).lte(125));
```

MongoDB 3.6 supports collections that validate documents against a provided [JSON Schema](https://docs.mongodb.com/manual/core/schema-validation/#json-schema) that
complies with the JSON schema specification (draft 4).

```json
{
  "type": "object",
  "required": [ "name", "age" ],
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1
    },
    "age": {
      "type": "int",
      "minimum" : 0,
      "exclusiveMinimum" : false,
      "maximum" : 125,
      "exclusiveMaximum" : false
    }
  }
}
```
The `MongoJsonSchema` and its builder allow fluent schema definition via the Java API.

```java
MongoJsonSchema schema = MongoJsonSchema.builder() //
    .required("name", "age") //
    .properties( //
        string("name").minLength(1), //
        int32("age").gte(0).lte(125) //
    ).build();
```

The schema can be used for various functionality: Set up `Document` validation for a collection:

```java
template.createCollection(Jedi.class, CollectionOptions.empty().validator(Validator.schema(schema)));
```

and to query the store for documents matching a given blueprint:

```java
template.find(query(matchingDocumentStructure(schema)), Jedi.class);
```

---

### Overview (`mongodb/text-search/README.md`)

# Spring Data MongoDB - Text Search Examples

This project contains samples of text search specific features of Spring Data Mongodb.

## Support for Text Index

Define text index structures manually (like below) or use `@TextIndexed` to mark content to be indexed for full text search.

```java
TextIndexDefinition textIndex = new TextIndexDefinitionBuilder()
  .onField("title", 3F)
  .onField("content", 2F)
  .onField("categories")
  .build();

template.indexOps(BlogPost.class).ensureIndex(textIndex);
```

## Support for full text repository queries

Use derived finder methods to search for terms and phrases.

```java
interface BlogPostRepository extends CrudRepository<BlogPost, String> {

    // page through results for full text query
	Page<BlogPost> findBy(TextCriteria criteria, Pageable page);

    // find all matching documents and sort by relevance
	List<BlogPost> findAllByOrderByScoreDesc(TextCriteria criteria);
}
```

---

### Overview (`mongodb/transactions/README.md`)

# Spring Data MongoDB - Transaction Sample

This project contains samples for upcoming MongoDB 4.0 transactions.

## Running the Sample

The sample uses multiple embedded MongoDB processes in a [MongoDB replica set](https://docs.mongodb.com/manual/replication/).
It contains test for both the synchronous and the reactive transaction support in the `sync` / `reactive` packages.   

You may run the examples directly from your IDE or use maven on the command line.

**INFO:** The operations to download the required MongoDB binaries and spin up the cluster can take some time. Please 
be patient. 

## Sync Transactions

`MongoTransactionManager` is the gateway to the well known Spring transaction support. It lets applications use 
[the managed transaction features of Spring](http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html#transaction).
The `MongoTransactionManager` binds a `ClientSession` to the thread. `MongoTemplate` detects the session and operates
on these resources which are associated with the transaction accordingly. `MongoTemplate` can also participate in 
other, ongoing transactions.

```java
@Configuration
static class Config extends AbstractMongoConfiguration {

	@Bean
	MongoTransactionManager transactionManager(MongoDbFactory dbFactory) {
		return new MongoTransactionManager(dbFactory);
	}

	// ...
}

@Component
public class TransitionService {

    @Transactional
    public void run(Integer id) {
    
    	Process process = lookup(id);
    
    	if (!State.CREATED.equals(process.getState())) {
    		return;
    	}
    
    	start(process);
    	verify(process);
    	finish(process);
    }
}
```

## Programmatic Reactive transactions

`ReactiveMongoTemplate` offers dedicated methods (like `inTransaction()`) for operating within a transaction without having to worry about the
commit/abort actions depending on the operations outcome.

**NOTE:** Please note that you cannot preform meta operations, like collection creation within a transaction.

```java
@Service
public class ReactiveTransitionService {
	
    public Mono<Integer> run(Integer id) {

		return template.inTransaction().execute(action -> {

			return lookup(id) //
			        .filter(State.CREATED::equals)
			        .flatMap(process -> start(action, process))
			        .flatMap(this::verify)
			        .flatMap(process -> finish(action, process));

		}).next().map(Process::getId);
	}
}
```

## Declarative Reactive transactions

`ReactiveMongoTransactionManager` is the gateway to the reactive Spring transaction support. It lets applications use 
[the managed transaction features of Spring](http://docs.spring.io/spring/docs/{springVersion}/spring-framework-reference/data-access.html#transaction).
The `ReactiveMongoTransactionManager` adds the `ClientSession` to the `reactor.util.context.Context`. `ReactiveMongoTemplate` detects the session and operates
on these resources which are associated with the transaction accordingly.

```java
@EnableTransactionManagement
class Config extends AbstractReactiveMongoConfiguration {

	@Bean
	ReactiveTransactionManager transactionManager(ReactiveMongoDatabaseFactory factory) {
		return new ReactiveMongoTransactionManager(factory);
	}
	
	// ...
}


@Service
class ReactiveManagedTransitionService {

	@Transactional
	public Mono<Integer> run(Integer id) {

		return lookup(id)
				.flatMap(process -> start(template, process))
				.flatMap(it -> verify(it)) //
				.flatMap(process -> finish(template, process))
				.map(Process::getId);
	}
}
```

---

### Overview (`mongodb/vector-search/README.md`)

# Spring Data MongoDB - Vector Search Example

This project
contains [Vector Search](https://docs.spring.io/spring-data/mongodb/reference/5.0/mongodb/repositories/vector-search.html)
with Spring Data MongoDB.

## Vector Support

The Spring Data `Vector` type can be used in repository query methods.
Domain type properties of managed domain types are required to use a numeric array representation for embeddings.

```java

@Document
public class Comment {

    @Id
    private ObjectId id;

    private String country;
    private String description;

    private Vector embedding;

    // ...
}


public interface CommentRepository extends Repository<Comment, String> {

    @VectorSearch(indexName = "cosine-index", searchType = VectorSearchOperation.SearchType.ANN)
    SearchResults<Comment> searchTop10ByCountryAndEmbeddingNear(String country, Vector vector, Score distance);
}
```

This example contains a test class to illustrate vector search with a Repository in `MongoDBVectorSearchTest`.

---

### Overview (`redis/cluster-sentinel/README.md`)

# Spring Data Redis Example

This example was named a bit misleadingly as `cluster-sentinel`, a mix of Redis Cluster and Redis Sentinel.

Find dedicated examples here: [Redis Cluster](../cluster) and [Redis Sentinel](../sentinel).

---

### Overview (`redis/cluster/readme.md`)

# Spring Data Redis - Cluster Examples #

This project contains Redis 3 Cluster specific features of Spring Data Redis.

To run the code in this sample a running cluster environment is required. Please refer to the  [redis cluster-tutorial](http://redis.io/topics/cluster-tutorial) for detailed information or check the Cluster Setup section below. 

## Support for Cluster ##

Cluster Support uses the same building blocks as the non-clustered counterpart. We use `application.properties` to point to an initial set of known cluster nodes which will be picked up by the auto-configuration.

```properties
spring.redis.cluster.nodes[0]=127.0.0.1:30001
spring.redis.cluster.nodes[1]=127.0.0.1:30002
spring.redis.cluster.nodes[2]=127.0.0.1:30003
```

**INFORMATION:** The tests flush the db of all known instances during the JUnit _setup_ phase to allow inspecting data directly on the cluster nodes after a test is run.

## Cluster Setup ##

To quickly set up a cluster of 6 nodes (3 master | 3 slave) go to the `redis/utils/create-cluster` directory.


```bash
redis/utils/create-cluster $ ./create-cluster start
  Starting 30001
  Starting 30002
  Starting 30003
  Starting 30004
  Starting 30005
  Starting 30006
```

On first initialization cluster nodes need to form the cluster by joining and assigning slot allocations.
**INFO**: This has to be done only once.

```bash
redis/utils/create-cluster $ ./create-cluster create
  >>> Creating cluster
  >>> Performing hash slots allocation on 6 nodes...
  Using 3 masters:
    127.0.0.1:30001
    127.0.0.1:30002
    127.0.0.1:30003
  Adding replica 127.0.0.1:30004 to 127.0.0.1:30001
  Adding replica 127.0.0.1:30005 to 127.0.0.1:30002
  Adding replica 127.0.0.1:30006 to 127.0.0.1:30003

  M: 10696916f57e58c5edce34127b23ca7af1b669a0 127.0.0.1:30001
     slots:0-5460 (5461 slots) master
  M: 5b0e1b4cc87175326ba79d00ecfc6f5dbdb424a7 127.0.0.1:30002
     slots:5461-10922 (5462 slots) master
  M: 5f3e978fb40b1d9c910d904ea19a0494b78668aa 127.0.0.1:30003
     slots:10923-16383 (5461 slots) master
  S: d1717c418d03db93183ce2d791ba6f48be5cf028 127.0.0.1:30004
     replicates 10696916f57e58c5edce34127b23ca7af1b669a0
  S: c7dfcdb9cd1105e4251de51c4ade54de59bb063c 127.0.0.1:30005
     replicates 5b0e1b4cc87175326ba79d00ecfc6f5dbdb424a7
  S: 3219785a9145717f30648a27a2dd07359e9dd46f 127.0.0.1:30006
     replicates 5f3e978fb40b1d9c910d904ea19a0494b78668aa

  Can I set the above configuration? (type 'yes' to accept): yes

  [OK] All nodes agree about slots configuration.
       >>> Check for open slots...
       >>> Check slots coverage...
  [OK] All 16384 slots covered.
```

It is now possible to connect to the cluster using the `redis-cli`.

```bash
redis/src $ ./redis-cli -c -p 30001
  127.0.0.1:30001> cluster nodes

  106969... 127.0.0.1:30001 myself,master - 0 0 1 connected 0-5460
  5b0e1b... 127.0.0.1:30002 master - 0 1450765112345 2 connected 5461-10922
  5f3e97... 127.0.0.1:30003 master - 0 1450765112345 3 connected 10923-16383
  d1717c... 127.0.0.1:30004 slave 106969... 0 1450765112345 4 connected
  c7dfcd... 127.0.0.1:30005 slave 5b0e1b... 0 1450765113050 5 connected
  321978... 127.0.0.1:30006 slave 5f3e97... 0 1450765113050 6 connected
```

To shut down the cluster use the `create-cluster stop` command.

```bash
redis/utils/create-cluster $ ./create-cluster stop
```

---

### Overview (`redis/example/README.md`)

# Spring Data Redis - Examples

This project contains samples of specific features of Spring Data Redis.

---

### Overview (`redis/pubsub-listener/README.md`)

# Spring Data Redis - Annotated Listener Example

This project demonstrates **declarative Redis Pub/Sub listeners**.

## Features

- `@RedisListener` on component methods to subscribe to Redis channels
- `@EnableRedisListeners` to activate the listener infrastructure
- Receiving **string** messages on a channel
- Receiving **JSON** payloads deserialized to domain types (e.g. `Person`)

## Requirements

- **Docker** (for running integration tests with Testcontainers).

## Running the tests

Integration tests publish messages to Redis channels and assert that the annotated listeners receive and process them. They use Testcontainers to start a Redis container, so Docker must be running.

```bash
cd redis/listener
mvn test
```

---

### Overview (`redis/pubsub/README.md`)

# Spring Data Redis Pub/Sub Example

This project contains samples of specific features of Spring Data Redis.

---

### Overview (`redis/reactive/README.md`)

# Spring Data Redis 2.0 - Reactive examples

This project contains samples of reactive data access features with Spring Data (Redis).

## Prerequisites

This project contains samples of specific features of Spring Data Redis using reactive infrastructure.

---

### Overview (`redis/repositories/README.md`)

# Spring Data Redis - Repository Examples #

This project contains examples for Spring Data specific repository abstraction on top of Redis.

## Repository Support ##

Redis Repository support allows to convert, store, retrieve and index entities within Redis native data structures. To do, besides the `HASH` containing the actual properties several [Secondary Index](http://redis.io/topics/indexes) structures are set up and maintained.

```java
@RedisHash("persons")
class Person {

  @Id String id;

  @Indexed String firstname;
  @Indexed String lastname;

  Gender gender;
  Address address;

  @Reference List<Person> children;
}
```

The above entity would for example then be stored in a Redis [HASH](http://redis.io/topics/data-types#hashes) with key `persons:9b0ed8ee-14be-46ec-b5fa-79570aadb91d`.

```properties
_class=example.springdata.redis.domain.Person                <1>
id=9b0ed8ee-14be-46ec-b5fa-79570aadb91d
firstname=eddard                                             <2>
lastname=stark
gender=MALE
address.city=winterfell                                      <3>
address.country=the north
children.[0]=persons:41436096-aabe-42fa-bd5a-9a517fbf0260    <4>
children.[1]=persons:1973d8e7-fbd4-4f93-abab-a2e3a00b3f53
children.[2]=persons:440b24c6-ede2-495a-b765-2d8b8d6e3995
```
```
<1> The _class attribute is used to store the actual type and is required for object/hash conversion.
<2> Values are also included in Secondary Index when annotated with @Indexed.
<3> Complex types are flattened out and embedded into the HASH as long as there is no explicit Converter registered or a @Reference annotation present.
<4> Using @Reference stores only the key of a referenced object without embedding values like in <3>.
```

Additionally indexes are created for `firstname`, `lastname` and `address.city` containing the `id` of the actual entity.

```bash
redis/src $ ./redis-cli keys *
   1) "persons"                                             <1>
   2) "persons:9b0ed8ee-14be-46ec-b5fa-79570aadb91d"        <2>
   3) "persons:9b0ed8ee-14be-46ec-b5fa-79570aadb91d:idx"    <3>
   4) "persons:41436096-aabe-42fa-bd5a-9a517fbf0260"
   5) "persons:41436096-aabe-42fa-bd5a-9a517fbf0260:idx"
   6) "persons:1973d8e7-fbd4-4f93-abab-a2e3a00b3f53"
   7) "persons:1973d8e7-fbd4-4f93-abab-a2e3a00b3f53:idx"
   8) "persons:440b24c6-ede2-495a-b765-2d8b8d6e3995"
   9) "persons:440b24c6-ede2-495a-b765-2d8b8d6e3995:idx"
  10) "persons:firstname:eddard"                            <4>
  11) "persons:firstname:robb"
  12) "persons:firstname:sansa"
  13) "persons:firstname:arya"
  14) "persons:lastname:stark"                              <5>
  15) "persons:address.city:winterfell"                     <6>
```
```
<1> SET holding all ids known in the keyspace "persons".
<2> HASH holding property values for id "9b0ed8ee-14be-46ec-b5fa-79570aadb91d" in keyspace "persons".
<3> SET holding index information for CRUD operations.
<4> SET used for indexing entities with "firstname" equal to "eddard" within keyspace "persons".
<5> SET used for indexing entities with "lastname" equal to "stark"  within keyspace "persons".
<6> SET used for indexing entities with "address.city" equal to "winterfell"  within keyspace "persons".
```

## Configuration ##

The below configuration uses [Lettuce](https://github.com/lettuce-io/lettuce-core) to connect to Redis on its default port. Please note the usage of `@EnableRedisRepositories` to create `Repository` instances.

```java
@Configuration
@EnableRedisRepositories
class AppConfig {

  @Bean
  RedisConnectionFactory connectionFactory() {
    return new LettuceConnectionFactory();
  }

  @Bean
  RedisTemplate<?, ?> redisTemplate(RedisConnectionFactory connectionFactory) {

    RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
    template.setConnectionFactory(connectionFactory);

    return template;
  }
}
```

Having the infrastructure in place you can go on declaring and using the `Repository` interface.

```java
interface PersonRepository extends CrudRepository<Person, String> {

  List<Person> findByLastname(String lastname);

  Page<Person> findByLastname(String lastname, Pageable page);

  List<Person> findByFirstnameAndLastname(String firstname, String lastname);

  List<Person> findByFirstnameOrLastname(String firstname, String lastname);

  List<Person> findByAddress_City(String city);
}
```

## One Word of Caution ##

Maintaining complex types and index structures stands and falls with its usage. Please consider the following:

* Nested document structures increase object <> hash conversion overhead.
* Consider having only those indexes you really need instead of indexing each and every property.
* Pagination is a costly operation since the total number of elements is calculated before returning just a slice of data.
* Pagination gives no guarantee on information as elements might be added, moved or removed.

---

### Overview (`redis/sentinel/README.md`)

# Spring Data Redis - Sentinel Examples

This project contains samples of Sentinel specific features of Spring Data Redis.

## Support for Sentinel

```java
@Configuration
public class RedisSentinelApplicationConfig {

	static final RedisSentinelConfiguration SENTINEL_CONFIG = new RedisSentinelConfiguration().master("mymaster") //
			.sentinel("localhost", 26379) //
			.sentinel("localhost", 26380) //
			.sentinel("localhost", 26381);

	@Bean
	public RedisConnectionFactory connectionFactory() {
		return new LettuceConnectionFactory(sentinelConfig(), LettuceClientConfiguration.defaultConfiguration());
	}

	@Bean
	public RedisSentinelConfiguration sentinelConfig() {
		return SENTINEL_CONFIG;
	}

}
```

---

### Overview (`redis/streams/README.md`)

# Spring Data Redis - Streams Examples

The [Redis Stream](https://redis.io/topics/streams-intro) is a new data type introduced with Redis 5.0 modelling log data structure.
Spring Data Redis supports _Redis Streams_ via both the imperative and the reactive API.

## Imperative API

**Basic Usage**
```java
@Autowired 
RedisTemplate template;

StringRecord record = StreamRecords.string(…)
    .withStreamKey("my-stream");
RecordId id = template.streamOps().add(record);

List<...> records = template.streamOps().read(count(2), from(id));
```

**ContinuousRead Read**
```java
@Autowired 
RedisConnectionFactory factory;

StreamListener<String, MapRecord<…> listener = 
  (msg) -> {
    // ...
  };

StreamMessageListenerContainer container = StreamMessageListenerContainer.create(factory));

container.receive(StreamOffset.fromStart("my-stream"), listener);
```

## Reactive API

**Basic Usage**
```java
@Autowired 
ReactiveRedisTemplate template;

StringRecord record = StreamRecords.string(…)
    .withStreamKey("my-stream");
Mono<RecordId> id = template.streamOps().add(record);

Flux<...> records = template.streamOps().read(count(2), from(id));
```

**ContinuousRead Read**
```java
@Autowired 
ReactiveRedisConnectionFactory factory;

StreamReceiver receiver = StreamReceiver.create(factory));

container.receive(StreamOffset.fromStart("my-stream"))
    .doOnNext((msg) -> {
    	// ...
    })
    .subscribe();
```

---

### Overview (`rest/starbucks/README.md`)

# Spring Data REST - Starbucks example

This sample app exposes 10843 Starbucks coffee shops via a RESTful API that allows to access the stores in a hypermedia based way and exposes a resource to execute geolocation search for coffee shops.

## Quickstart

1. Install MongoDB (http://www.mongodb.org/downloads, unzip, run `mkdir data`, run `bin/mongod --dbpath=data`)
2. Build and run the app (`mvn spring-boot:run`)
3. Access the root resource (`curl http://localhost:8080/api`) and traverse hyperlinks.
4. Or access the location search directly (e.g. `http://localhost:8080/api/stores/search/findByAddressLocationNear?location=40.740337,-73.995146&distance=0.5miles`)

## Web UI

The application provides a custom web UI using the exposed REST API to display the search result on a Google Map. Point you browser to `http://localhost:8080`. The UI is rendered using Thymeleaf, driven by the `StoresController`. A tiny JavaScript progressively enhances the view by picking up and enhancing a URI template rendered into the view (`<div id="map" data-uri="…" />`).



The API itself can be discovered using the HAL browser pulled in through the corresponding Spring Data REST module (`spring-data-rest-hal-browser`). It's exposed at the API root at `http://localhost:8080/api`.

## Technologies used

- Spring Data REST & Spring Data MongoDB
- MongoDB
- Spring Batch (to read the CSV file containing the store data and pipe it into MongoDB)
- Spring Boot

---

### Overview (`web/example/README.md`)

# Spring Data - web support example

This example shows some of the Spring Data integration features with Spring MVC.

1. See how we plug into Spring MVC to create `Pageable` instances from request parameters in `UserController.users(…)`.
2. See how interfaces can be used to bind request payloads in `UserController.UserForm`. Spring Data creates a `Map`-backed proxy for you to easily create form-backing objects.

---

### Overview (`web/projection/README.md`)

# Spring Data Web - Projection example

This example shows how to use projection interfaces in combination with JSON Path or XPath expressions to bind payload data to an object instance.

The most interesting bit is the following projection interface declared in `UserController`:

```java
@ProjectedPayload
public interface UserPayload {

	@XBRead("//firstname")
	@JsonPath("$..firstname")
	String getFirstname();

	@XBRead("//lastname")
	@JsonPath("$..lastname")
	String getLastname();
}
```

This type is used in `UserController.index(…)` and basically combines two modes of operation.

## Binding request data via JSON Path expression

The `@JsonPath` annotations bind the values obtained by evaluating the expressions from the request. The sample is using a recursive property lookup for `firstname` and `lastname`. Using those expressions allows the payload that received to slightly changed and the code dealing with not having to be changed.

As an example using that on the server side can be found in `UserControllerIntegrationTests`. The tests send two different flavors of JSON to simulate a change in behavior of the client and the server can handle both representation formats without the need for a change.

This is also very useful on the client side which is simulated in `UserControllerClientTests` setting up a `RestTemplate` with the newly introduced `HttpMessageConverters` so that the projection interface can be used to access the payload. See how the test case accesses different HTTP resources, that simulate a change in the representation on the server side.

## Support for XPath expressions

The JSON Path support is automatically activated on the server side if the Jayway JSON Path library is on the classpath. Support for XPath is activated if XMLBeam is on the classpath, generally works the same and actually offers quite some more sophisticated features.

---

### Overview (`web/querydsl/README.md`)

# Spring Data Web - Querydsl example

This example shows some of the Spring Data Querydsl integration features with Spring MVC.

## Quickstart

1. Build and run the app (`mvn spring-boot:test-run`)
2. Access app directly via its UI (`http://localhost:8080/`).

## Interesting bits

The most core piece of interest here is `UserController` and how it consumes Querydsl `Predicate` instances derived from the request:

```java
@Controller
@RequiredArgsConstructor(onConstructor = @__(@Autowired) )
class UserController {

  private final UserRepository repository;

  @RequestMapping(value = "/", method = RequestMethod.GET)
  String index(Model model,
      @QuerydslPredicate(root = User.class) Predicate predicate, Pageable pageable,
      @RequestParam MultiValueMap<String, String> parameters) {

    … = userRepository.findAll(predicate, pageable);

  }
}
```

As you can see `Predicate` can be used as Spring MVC controller argument. It will automatically populate such a `Predicate` with values from the current request based on the type configured in `@QuerydslPredicate`. Explicit bindings can be configured by either explicitly defining one in the annotation, too. By default, we will inspect the domain types's repository for binding customizations. In this example, it looks like this:

```java
public interface UserRepository
    extends CrudRepository<User, String>, QueryDslPredicateExecutor<User>, QuerydslBinderCustomizer<QUser> {

  @Override
  default public void customize(QuerydslBindings bindings, QUser root) {

    bindings.bind(String.class).first((StringPath path, String value) -> path.containsIgnoreCase(value));
    bindings.excluding(root.password);
  }
}
```

The repository extends `QuerydslBinderCustomizer` which exposes a `QuerydslBindings` instance for customization. It allows for property based (by using Querydsl's metamodel types) and type based customizations of the value binding. The example here defines a `String`-properties to be bound using the `containsIgnoreCase(…)` operator. For further information checkout the JavaDoc of [QuerydslBindings](http://docs.spring.io/spring-data/commons/docs/1.11.0.RC1/api/org/springframework/data/querydsl/binding/QuerydslBindings.html).

## Technologies used

- Spring Data MongoDB, Spring MVC & Querydsl
- MongoDB
- Spring Batch (to read the CSV file containing the user data and pipe it into MongoDB)
- Spring Boot

---

--- METRICS ---
- Files Extracted: 43
- Estimated Token Budget: ~16816 tokens
- Canonical Reference: https://codewiki.google/github.com/spring-projects/spring-data-examples
