Reputation: 3497
In my application I have servers and users, each user can have multiple servers. The servers list in User
is a @DBref
:
@DBRef
private List<Server> servers;
In the controller where I want to create a server I first create and save the server, after that I add the server to the server list in user and save the user:
@PostMapping
public Mono create(@Valid @RequestBody Server server, Mono<Authentication> authentication) {
return this.serverRepository.save(server) // This works, the server is saved.
.and(authentication.map(value -> {
User user = (User) value.getDetails();
System.out.println(user); // This works, so this function is called.
if (user.getServers() == null) {
// Create empty list so .add can be used.
user.setServers(new ArrayList<>());
}
user.getServers().add(server);
return userRepository.save(user); // Isn't working, in the UserCascadeSaveMongoEventListener I don't see it.
}));
}
I think the way I use .and()
isn't right.
To save the relation I have the UserCascadeSaveMongoEventListener
:
public class UserCascadeSaveMongoEventListener extends AbstractMongoEventListener<Object> {
@Autowired
private MongoOperations mongoOperations;
@Override
public void onBeforeConvert(BeforeConvertEvent<Object> event) {
Object source = event.getSource();
System.out.println(source); // On server create only the Server is shown, User is not shown.
if ((source instanceof User) && (((User) source).getServers() != null)) {
mongoOperations.save(((User) source).getServers());
}
}
}
But this class doesn't matter at the moment because the user isn't save at all.
The repositories used are all normal ReactiveCrudRepositories.
What is the right way to reactively call multiple repositories with multiple Mono's?
Upvotes: 1
Views: 1688
Reputation: 59086
the save
call does not actually save, it's setting up a reactive pipeline that you can use to save. The operation is only performed when something subscribes to it:
Mono<User> savedUser = userRepository.save(user);
So you should compose the various bits in your controller method and make sure that no reactive type is left hanging alone.
You could have seen that by adding a log()
operator after the save operation - nothing subscribes to it so the operation is not performed.
Your code should look like (that's if you want to return the created user as a response; if you don't want to return anything, you can add a final then()
operator right at the end and make your controller method return a Mono<Void>
that signals when the operation is done):
@PostMapping
public Mono<User> create(@Valid @RequestBody Server server, Mono<Authentication> authentication) {
return this.serverRepository.save(server) // This works, the server is saved.
.then(authentication.flatMap(value -> {
User user = (User) value.getDetails();
System.out.println(user); // This works, so this function is called.
if (user.getServers() == null) {
// Create empty list so .add can be used.
user.setServers(new ArrayList<>());
}
user.getServers().add(server);
return userRepository.save(user);
}));
}
Upvotes: 2