Build a Reactive Spring Boot REST API with RxJava: Step‑by‑Step Guide
Learn how to create a reactive REST API using Spring Boot and RxJava, covering prerequisite knowledge, required dependencies, CRUD endpoint definitions, service layer implementation with RxJava Single, and web controller integration, plus essential Maven setup and tips to avoid common HttpMediaNotAcceptableException errors.
This article demonstrates how to develop a reactive REST API with Spring Boot and RxJava, assuming you are already familiar with these technologies.
1. Prerequisite Knowledge
Before proceeding, ensure you can create a simple REST API using Spring Boot and RxJava. If not, refer to resources such as Baeldung for Spring Boot and AndroidHive for RxJava.
2. Reactive REST API
Define the following CRUD endpoints for a basic author‑book service:
[POST] /api/authors – add an author
[POST] /api/books – add a book
[PUT] /api/books/{bookId} – update a book by its ID
[GET] /api/books?limit={limit}&page={page} – paginate book list
[GET] /api/book/{bookId} – get book details by ID
[DELETE] /api/book/{bookId} – delete a book
3. Dependencies
Add the following Maven dependencies to pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava</artifactId>
<version>1.3.8</version>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava-reactive-streams</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.199</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>1.18.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>2.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
<version>2.25.0</version>
</dependency>
</dependencies>Note: Adding the dependencies on lines 19‑23 (the RxJava reactive‑streams and test libraries) is essential; otherwise you will encounter HttpMediaNotAcceptableException when invoking the reactive API.
4. Service Layer
Service methods return RxJava Single objects. Below is an example that adds a new book:
@Override
public Single<String> addBook(AddBookRequest addBookRequest) {
return saveBookToRepository(addBookRequest);
}
private Single<String> saveBookToRepository(AddBookRequest addBookRequest) {
return Single.create(singleSubscriber -> {
Optional<Author> optionalAuthor = authorRepository.findById(addBookRequest.getAuthorId());
if (!optionalAuthor.isPresent()) {
singleSubscriber.onError(new EntityNotFoundException());
} else {
String addedBookId = bookRepository.save(toBook(addBookRequest)).getId();
singleSubscriber.onSuccess(addedBookId);
}
});
}
private Book toBook(AddBookRequest addBookRequest) {
Book book = new Book();
BeanUtils.copyProperties(addBookRequest, book);
book.setId(UUID.randomUUID().toString());
book.setAuthor(Author.builder().id(addBookRequest.getAuthorId()).build());
return book;
}5. Web Layer
The controller forwards requests to the service layer and returns a reactive response:
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Single<ResponseEntity<BaseWebResponse>> addBook(@RequestBody AddBookWebRequest addBookWebRequest) {
return bookService.addBook(toAddBookRequest(addBookWebRequest))
.subscribeOn(Schedulers.io())
.map(s -> ResponseEntity.created(URI.create("/api/books/" + s))
.body(BaseWebResponse.successNoData()));
}
private AddBookRequest toAddBookRequest(AddBookWebRequest addBookWebRequest) {
AddBookRequest addBookRequest = new AddBookRequest();
BeanUtils.copyProperties(addBookWebRequest, addBookRequest);
return addBookRequest;
}6. Conclusion
The complete source code, including unit tests, is available on GitHub.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
