This minimal example shows two controllers in a Spring Data REST app with base path /api:
- One using
@BasePathAwareControllerβ link builder misses the base path. - One using
@RepositoryRestControllerβ link builder works correctly.
1. Setup Spring Boot and Dependencies
Add to pom.xml (or build.gradle):
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-rest</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-hateoas</artifactId> </dependency> </dependencies>
2. Configure Base Path
In application.properties:
spring.data.rest.base-path=/api
This sets the base path to /api.
3. Define a Sample Entity and Repository
@Entity
public class Book {
@Id @GeneratedValue
private Long id;
private String title;
// Constructors, getters, setters
}
@RepositoryRestResource(path = "books")
public interface BookRepository extends JpaRepository&;t;Book, Long> {}
Spring Data REST exposes /api/books.
4. Controller Using @BasePathAwareController
@BasePathAwareController
@RequestMapping("/books")
public class BasePathAwareBookController {
@GetMapping("/{id}")
public ResponseEntity<Book> getBook(@PathVariable Long id) {
// For demo, just a stub Book
Book book = new Book();
book.setId(id);
book.setTitle("Sample Book");
return ResponseEntity.ok(book);
}
@GetMapping("/{id}/link")
public ResponseEntity<String> getLink(@PathVariable Long id) {
Link link = WebMvcLinkBuilder.linkTo(
WebMvcLinkBuilder.methodOn(BasePathAwareBookController.class).getBook(id))
.withSelfRel();
return ResponseEntity.ok(link.getHref());
}
}
5. Controller Using @RepositoryRestController
@RepositoryRestController
@RequestMapping("/books")
public class RepositoryRestBookController {
@GetMapping("/{id}")
public ResponseEntity<Book> getBook(@PathVariable Long id) {
Book book = new Book();
book.setId(id);
book.setTitle("RepositoryRest Book");
return ResponseEntity.ok(book);
}
@GetMapping("/{id}/link")
public ResponseEntity<String> getLink(@PathVariable Long id) {
Link link = WebMvcLinkBuilder.linkTo(
WebMvcLinkBuilder.methodOn(RepositoryRestBookController.class).getBook(id))
.withSelfRel();
return ResponseEntity.ok(link.getHref());
}
}
6. Testing the Links
Run the app and test:
GET http://localhost:8080/api/books/1/link }
- For BasePathAwareBookController, the output will be:
/books/1
Notice: Missing /api prefix! This URL is broken because the actual endpoint is /api/books/1.
- For RepositoryRestBookController, the output will be:
/api/books/1
This URL is correct.
7. Conclusion
This demo proves:
@BasePathAwareControllercausesWebMvcLinkBuilderto omit the base path/api.@RepositoryRestControllerpreserves the base path correctly in generated links.
If your app uses hypermedia links with Spring Data REST, prefer @RepositoryRestController for custom controllers to avoid broken links.
Bonus: Manual Fix for Base Path
If you must use @BasePathAwareController, add the base path manually in the link:
String basePath = "/api"; Link link = WebMvcLinkBuilder.linkTo( WebMvcLinkBuilder.methodOn(BasePathAwareBookController.class).getBook(id)) .withSelfRel(); String fixedLink = basePath + link.getHref(); // prepend base path manually
But keep in mind this can become tedious and error-prone as your API grows.
Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy
Thank you!
We will contact you soon.
π Photo of Eleftheria Drosopoulou
Eleftheria DrosopoulouJune 5th, 2025Last Updated: May 31st, 2025
Eleftheria DrosopoulouJune 5th, 2025Last Updated: May 31st, 2025
0 1,138 1 minute read

This site uses Akismet to reduce spam. Learn how your comment data is processed.