Spring Data REST

repository·main·Indexed 19 days ago

https://github.com/spring-projects/spring-data-rest

A library that automatically exposes Spring Data repositories as discoverable, HAL-compliant RESTful web services. It provides full CRUD and association management over domain models, supporting data stores such as JPA, MongoDB, Neo4j, Solr, Cassandra, and Gemfire. Key features include pagination, sorting, dynamic filtering, search resources for repository query methods, and the ability to define client-specific representations through projections.

Tokens
20.3K
Snippets
63
Records
88
Agent score
73%

What's inside Spring Data REST

  1. What is Spring Data REST?

    main

    Spring Data REST is a framework that automatically exports Spring Data repositories as RESTful web services. It is designed to reduce the boilerplate code required to implement RESTful services for multi-domain object systems.

    Key features include:

    • Automatic Exporting: It builds on top of Spring Data repositories to expose them as REST resources.
    • Hypermedia-Driven: It leverages hypermedia (HATEOAS) to allow clients to discover available functionality and integrate resources into hypermedia-based workflows.
    • Foundation: It works alongside Spring MVC or Spring WebFlux to provide a complete web service layer.
  2. Overview of Spring Data REST

    main

    Spring Data REST provides a flexible and configurable mechanism for exposing Spring Data repositories as RESTful web services over HTTP. It allows for full CRUD capabilities over your entities, including managing associations, and automatically fronts your domain model with a discoverable REST API using HAL (Hypertext Application Language) as the media type.

    Key capabilities include:

    • Exposing collection, item, and association resources.
    • Supporting pagination and sorting via navigational links.
    • Dynamic filtering of collection resources.
    • Exposing search resources for repository query methods.
    • Hooking into REST request handling via Spring ApplicationEvents.
    • Exposing model metadata as ALPS and JSON Schema.
    • Defining client-specific representations through projections.
    • Supporting multiple data stores: JPA, MongoDB, Neo4j, Solr, Cassandra, and Gemfire.
  3. Define and use Projections to alter resource views

    main

    Projections allow you to create simplified or reduced views of your domain models. By default, Spring Data REST exports all attributes of an entity. You can define a projection using a Java interface annotated with @Projection to specify exactly which fields should be exposed.

    How to define a projection

    1. Create a Java interface.
    2. Annotate it with @Projection(name = "<projection-name>", types = { <TargetEntity>.class }).
    3. Add getter methods for the fields you want to include in the view.

    How to use a projection

    To apply a projection to a specific resource, use the projection query parameter in your GET request. The value must match the name attribute defined in the @Projection annotation, not the interface name.

    Example Request: GET http://localhost:8080/persons/1?projection=noAddresses

    @Projection(name = "noAddresses", types = { Person.class })
    interface NoAddresses {
      String getFirstName();
      String getLastName();
    }
  4. Use ETags and If-Match for conditional updates

    main

    Spring Data REST uses the ETag header to tag resources, typically derived from a field annotated with @Version. This allows for optimistic locking to prevent clients from overwriting each other's changes.

    Implementation

    1. Annotate your domain model: Use the JPA @Version annotation (if using Spring Data JPA) or the Spring Data org.springframework.data.annotation.Version annotation (for other modules) on a version field.
    2. Perform conditional updates: When sending PUT, PATCH, or DELETE requests, include the If-Match header containing the previously received ETag value.

    Behavior

    • Success: If the current server-side ETag matches the If-Match header, the operation proceeds.
    • Failure: If the ETag has changed (meaning another client updated the resource), the server returns an HTTP 412 Precondition Failed status. The client should then fetch the latest version and reconcile changes.
    curl -v -X PATCH -H 'If-Match: <value of previous ETag>' ...
  5. Compare `@RepositoryRestController` and `@BasePathAwareController`

    main

    Choose the correct annotation based on whether your custom logic is tied to specific entities or general API operations:

    AnnotationUse CaseBehavior
    @RepositoryRestControllerWhen you want to extend specific resource/entity operations.Integrates with repository URI space, applies CORS based on the repository path, and enables OpenEntityManagerInViewInterceptor for JPA.
    @BasePathAwareControllerWhen you want to build custom operations (like Spring MVC views) under the API basePath without being tied to specific entities.Serves content from the API base path but does not provide the entity-specific integration features of @RepositoryRestController.
    @RestController / @ControllerStandard Spring MVC controllers.Warning: These are completely outside the scope of Spring Data REST. They will not use SDR's message converters, exception handling, or base path settings.
  6. Understand Application-Level Profile Semantics (ALPS) metadata

    main

    Spring Data REST provides ALPS (Application-Level Profile Semantics) documents for every exported repository. ALPS describes the application-level semantics, including available RESTful transitions (operations) and the attributes of each resource.

    To access ALPS metadata:

    1. Navigate to the root of the application to find the profile link.
    2. Follow the profile link to find specific metadata links for each resource (e.g., /profile/persons).
    3. Use the Accept: application/alps+json header to ensure the profile link serves ALPS content.

    ALPS metadata includes:

    • Descriptors: Detailed listings of resource attributes (e.g., firstName, lastName) and their types.
    • Hypermedia Control Types: Descriptions of supported operations (e.g., GET, POST, PUT, DELETE) categorized by their impact on system state.
    • Projections: If projections are defined, they are listed within the relevant operations, showing which attributes are included in each projection.
    // Example ALPS descriptor for a resource attribute
    {
      "id" : "person-representation",
      "descriptors" : [ {
        "name" : "firstName",
        "type" : "SEMANTIC"
      }, {
        "name" : "address",
        "type" : "SAFE",
        "rt" : "http://localhost:8080/profile/addresses#address"
      } ]
    }
  7. How the Spring Data REST exporter creates representations

    main

    The Spring Data REST exporter uses a Converter<Entity, EntityModel> registered within an internal ConversionService to transform entities into their JSON representations.

    This converter is responsible for:

    1. Iterating over @Entity properties.
    2. Creating links for properties managed by a Repository (the standard _links behavior).
    3. Copying across embedded or simple properties.

    If you need to completely change the output format, you can replace the default behavior by registering your own ConversionService and a custom Converter<Entity, EntityModel> in your ApplicationContext. This allows you to return a custom implementation of EntityModel.

  8. Set the Repository Detection Strategy

    main

    Spring Data REST uses a RepositoryDetectionStrategy to decide which repositories are exported as REST resources. You can choose from the following RepositoryDiscoveryStrategies values:

    NameDescription
    DEFAULTExposes all public repository interfaces but respects the exported flag of @(Repository)RestResource.
    ALLExposes all repositories regardless of type visibility or annotations.
    ANNOTATEDOnly repositories annotated with @(Repository)RestResource are exposed (unless exported=false).
    VISIBILITYOnly public repositories that are annotated are exposed.
  9. How Spring Data REST handles domain object representations

    main

    Spring Data REST automatically returns a representation of a domain object based on the Accept header specified in the HTTP request.

    Currently, only JSON representations are supported. Spring Data REST uses a specially configured ObjectMapper equipped with intelligent serializers designed to convert domain objects into links (and vice versa) to maintain HATEOAS compliance. While it attempts to serialize unmanaged beans as standard POJOs and managed beans as links, complex domain models may require custom Jackson configuration to ensure correct JSON translation.

  10. Use If-None-Match for conditional GET queries

    main

    The If-None-Match header allows for conditional queries to reduce unnecessary data transfer. When performing a GET request, you can provide the ETag of the resource you already have.

    Behavior

    • No Change: If the server-side ETag matches the If-None-Match header, Spring Data REST returns an HTTP 304 Not Modified status without a response body.
    • Changed: If the ETag does not match, the server returns the full resource and a new ETag header.
    curl -v -H 'If-None-Match: <value of previous etag>' ...
  11. Discover resources using HATEOAS and HAL

    main

    Spring Data REST follows HATEOAS principles, making resources discoverable via links. By default, it uses the HAL (Hypertext Application Language) format to render responses.

    To discover available resources, issue an HTTP GET request to the root URL of your application. The returned JSON object contains a _links property with relation types pointing to available resources (like collections or the ALPS profile).

    Example Discovery

    curl -v http://localhost:8080/

    Response Example:

    {
     "_links" : {
        "orders" : {
          "href" : "http://localhost:8080/orders"
        },
        "profile" : {
          "href" : "http://localhost:8080/api/alps"
        }
      }
    }