Getting Started Spring Content with Fulltext

What you'll build

We'll build on the previous guide Getting Started with Spring Content REST API.

What you'll need

  • About 30 minutes

  • A favorite text editor or IDE

  • JDK 1.8 or later

  • Maven 3.0+

How to complete this guide

Before we begin let's set up our development environment:

  • Download and unzip the source repository for this guide, or clone it using Git: git clone https://github.com/paulcwarren/spring-content-gettingstarted.git

  • We are going to start where Getting Started with Spring Content REST API leaves off so cd into spring-content-gettingstarted/spring-content-rest/complete

When you’re finished, you can check your results against the code in spring-content-gettingstarted/spring-content-with-fulltext/complete.

Update dependencies

Add the com.github.paulcwarren:spring-content-elasticsearch-boot-starter and org.elasticsearch.client:elasticsearch-rest-high-level-client dependencies.

pom.xml


<?xml version="1.0" encoding="UTF-8"?>

    <modelVersion>4.0.0</modelVersion>

    <artifactId>spring-content-with-fulltext</artifactId>

    <parent>
        <groupId>com.github.paulcwarren</groupId>
        <artifactId>gettingstarted-spring-content</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../../pom.xml</relativePath>
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>3.3.2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.paulcwarren</groupId>
            <artifactId>spring-content-fs-boot-starter</artifactId>
            <version>${spring.content.version}</version>
        </dependency>
        <dependency>
            <groupId>com.github.paulcwarren</groupId>
            <artifactId>spring-content-rest-boot-starter</artifactId>
            <version>${spring.content.version}</version>
        </dependency>
        <dependency>
            <groupId>com.github.paulcwarren</groupId>
            <artifactId>spring-content-elasticsearch-boot-starter</artifactId>
            <version>${spring.content.version}</version>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.17.23</version>
        </dependency>
        <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
        </dependency>

        <!-- Test dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.jupiter</groupId>
                    <artifactId>junit-jupiter-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.junit.jupiter</groupId>
                    <artifactId>junit-jupiter-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>spring-mock-mvc</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.github.paulcwarren</groupId>
            <artifactId>ginkgo4j</artifactId>
            <version>${ginkgo.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.github.grantwest.eventually</groupId>
            <artifactId>hamcrest-eventually-matchers</artifactId>
            <version>0.0.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>1.20.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Update FileContentStore

So that we can perform full-text searches make your FileContentStore extend Searchable.

src/main/java/gettingstarted/FileContentStore.java


package gettingstarted;

import org.springframework.content.commons.store.ContentStore;
import org.springframework.content.commons.search.Searchable;
import org.springframework.stereotype.Component;

@Component  // just to keep the ide happy!
public interface FileContentStore extends ContentStore<File, String>, Searchable<String> {
}

Build an executable JAR

If you are using Maven, you can run the application using mvn spring-boot:run. Or you can build the JAR file with mvn clean package and run the JAR by typing:

java -jar target/gettingstarted-spring-content-with-versions-0.0.1.jar

Start an Elasticsearch Server

Using docker, start an elasticsearch server:

docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" paulcwarren/elasticsearch:latest

Create an Entity

Create an entity:

curl -X POST -H 'Content-Type:application/hal+json' -d '{}' http://localhost:8080/files/

Associate content with that entity:

curl -X PUT -H 'Content-Type:text/plain' -d 'Hello Spring World!' http://localhost:8080/files/1/content

Create a second entity:

curl -X POST -H 'Content-Type:application/hal+json' -d '{}' http://localhost:8080/files/

Associate content with the second entity:

curl -X PUT -H 'Content-Type:text/plain' -d 'Hello Spring Content World!' http://localhost:8080/files/2/content

Perform a fulltext search using the /searchContent endpoint:

curl -H 'Accept:application/hal+json' http://localhost:8080/files/searchContent?queryString=Content

And you should see a response like this:

{
  "_embedded" : {
    "files" : [ {
      "name" : null,
      "created" : "2020-05-14T06:05:07.633+0000",
      "summary" : null,
      "contentId" : "527638d0-4f08-469d-a7d7-b271316af3da",
      "contentLength" : 27,
      "mimeType" : "text/plain",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/files/2"
        },
        "file" : {
          "href" : "http://localhost:8080/files/2"
        },
        "files" : {
          "href" : "http://localhost:8080/files/2"
        }
      }
    } ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/files/searchContent?queryString=Content"
    }
  }
}

Spring Content found the second document that we added because its content included the keyword "Content" that we searched for.

Summary

Congratulations! You've just written a simple application that uses Spring Content with Elasticsearch to index content so that searches can be performed against that content.

This guide demonstrates the Spring Content Elasticsearch Module. Spring Content also supports Solr with the Spring Content Solr Module. To use Solr, simply update the spring-content-elasticsearch-boot-starter dependency for spring-content-solr-boot-starter.