I am pretty new to Spring web flux reactive programming. So this is little confusing.
I am writing update API with spring web flux. Passed request body tp the update method is a Mono of request. So My problem is How can I get the request body and perform with? . Please check the commented line in following code.
public Mono<User> updateUser(String userId, Mono<UserRequest> user){
return userRepository.findById(userId)
.switchIfEmpty(Mono.error(new NotFoundException("User not found")))
.flatMap(foundUser -> {
// How to get passed user object from Mono<UserRequest>
modelMapper.map(source, foundUser);
return Mono.just(userRepository.save(foundUser))
})
}
Thank you.
CodePudding user response:
You can add .zipWith(user, (foundUser, user) -> ...
(or simples .zipWith(user)
that returns Tuple
).
Samples:
@Test
void x1() {
Mono<String> m1 = Mono.just("S1");
Mono<String> m2 = Mono.just("S2");
m1
.switchIfEmpty(Mono.error(new NotFoundException("User not found")))
.zipWith(m2, (s1, s2) -> s1.concat(s2)) // can be simplified to 'String::concat'
.as(StepVerifier::create)
.assertNext(s -> assertThat(s)
.isEqualTo("S1S2")
)
.verifyComplete();
}
@Test
void x2() {
Mono<String> m1 = Mono.just("S1");
Mono<String> m2 = Mono.error(new RuntimeException("some-error"));
m1
.switchIfEmpty(Mono.error(new NotFoundException("User not found")))
.zipWith(m2, String::concat)
.as(StepVerifier::create)
.expectErrorSatisfies(throwable -> assertThat(throwable)
.isInstanceOf(RuntimeException.class)
.hasMessage("some-error")
)
.verify();
}
@Test
void x3() {
Mono<String> m1 = Mono.error(new RuntimeException("some-error"));
Mono<String> m2 = Mono.just("S2");
m1
.switchIfEmpty(Mono.error(new NotFoundException("User not found")))
.zipWith(m2, String::concat)
.as(StepVerifier::create)
.expectErrorSatisfies(throwable -> assertThat(throwable)
.isInstanceOf(RuntimeException.class)
.hasMessage("some-error")
)
.verify();
}
@Test
void x4() {
Mono<String> m1 = Mono.empty();
Mono<String> m2 = Mono.just("S2");
m1
.switchIfEmpty(Mono.error(new NotFoundException("User not found")))
.zipWith(m2, String::concat)
.as(StepVerifier::create)
.expectErrorSatisfies(throwable -> assertThat(throwable)
.isInstanceOf(NotFoundException.class)
.hasMessage("User not found")
)
.verify();
}
Btw, there is a super-handy documentation from reactor: https://projectreactor.io/docs/core/release/reference/#which-operator
I am also wondering why you pass Mono<UserRequest> user
- where does it come from and why you cannot use plain UserRequest user
?
Also, your repository is suspicious - why findById
returns a reactive object, while save
does not? It looks like a blocking call, hence you loose benefits of webflux/reactor.
CodePudding user response:
// How to get passed user object from Mono
Start with that Mono (the repository calls are non-reactive operations anyway):
public Mono<User> updateUser(String userId, Mono<UserRequest> user){
return user.map(request -> ...);
}