James
James

Reputation: 3184

How do I configure Spring Data REST to return links with templated ID such as users/{id}

Suppose I have Spring Data repository for a User entity. Then, Spring Data REST produces the following HAL JSON at its base path:

{
  "_links": {
    "users": {
      "href": "http://localhost:8080/users"
    }
  }
}

I also want my clients to know that they can call http://localhost:8080/users/{id} to get a specific user (e.g., http://localhost:8080/users/25)

How can I configure Spring Data REST to produce this link for all my entities? For example, I would like Spring Data REST to return something like this:

{
  "_links": {
    "users": {
      "href": "http://localhost:8080/users/{id}",
      "templated": true
    }
  }
}

Update

A good example of what I'm trying to achieve is at https://api.github.com/. The API clearly indicates that https://api.github/users/{user} is part of the API. For example, https://api.github.com/users/odrotbohm is a valid call.

How can I get Spring Data REST to indicate that htts://localhost:8080/users/{id} is part of my API?

Update 2

Does the CrudRepository provide a templated link http://localhost:8080/users/{id}? I don't see that it does. I'm using Javascript Traverson HAL and without this link I cannot traverse to a specific user.

Update 3

Here is a complete sample of the problem (that I also posted on github):

build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.1.2'
    id 'io.spring.dependency-management' version '1.1.2'
}

group = 'com.example'
version = '1.0'

java {
    sourceCompatibility = '17'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-data-rest'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

In com.example package:

TaversonIssueApplication.java

@SpringBootApplication
public class TaversonIssueApplication {

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

}

User.java

@Entity
@Table(name="`User`")
@Data
public class User {
 
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    
}

UserRepository.java

public interface UserRepository extends CrudRepository<User, Long> {
}

In /src/main/resources:

INSERT INTO "user" (name) VALUES ('bob');
INSERT INTO "user" (name) VALUES ('sally');

Once application is started, a request to http://localhost:8080/ results in:

{
  "_links" : {
    "users" : {
      "href" : "http://localhost:8080/users"
    },
    "profile" : {
      "href" : "http://localhost:8080/profile"
    }
  }
}

From this response, a client has know way of knowing that http://localhost:8080/users/1 is a valid link. A Traverson HAL client cannot follow the link from http://localhost:8080/ to http://localhost:8080/users/1. This is because no templated link is provided such as ``http://localhost:8080/users/{id}`.

Is there a way for Spring Data REST to provide such a templated link. Could Spring Data REST produce the following in response to http://localhost:8080/:

{
  "_links" : {
    "users" : {
      "href" : "http://localhost:8080/users/{id}"
    },
    "profile" : {
      "href" : "http://localhost:8080/profile"
    }
  }
}

Upvotes: 1

Views: 426

Answers (1)

Angshuman
Angshuman

Reputation: 60

Just extend the PagingAndSortingRepository interface. It also provides additional methods for paging & sorting data.

@RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserRepository extends PagingAndSortingRepository<User, Long>, CrudRepository<User, Long> {
}

Please mind the @RepositoryRestResource annotation. It allows changing the export details like the name of the collection in the JSON response or as well as the base path for the repository. Please take a look at this official Spring guide

Upvotes: 1

Related Questions