Given the following method:
private Mono<UserProfileUpdate> upsertUserIdentifier(UserProfileUpdate profileUpdate, String id){ return userIdentifierRepository.findUserIdentifier(id) .switchIfEmpty(Mono.defer(() -> { profileUpdate.setNewUser(true); return createProfileIdentifier(profileUpdate.getType(), id); })) .map(userIdentifier -> { profileUpdate.setProfileId(userIdentifier.getProfileId()); return profileUpdate; }); }
switchIfEmpty
and map
operators mutate the profileUpdate
object. Is it safe to mutate in switchIfEmpty
operator? Regarding map
, if I have understood correctly, this is not safe and object profileUpdate
must be immutable, right? eg:
private Mono<UserProfileUpdate> upsertUserIdentifier(UserProfileUpdate profileUpdate, String id){ return userIdentifierRepository.findUserIdentifier(id) .switchIfEmpty(Mono.defer(() -> { profileUpdate.setNewUser(true); return createProfileIdentifier(profileUpdate.getType(), id); })) .map(userIdentifier -> profileUpdate.withProfileId(userIdentifier.getProfileId())); }
Later in the chain, another method mutates the object:
public Mono<UserProfileUpdate> transform(UserProfileUpdate profUpdate) { if (profUpdate.isNewUser()) { profUpdate.getAttributesToSet().putAll(profUpdate.getAttributesToSim()); } else if (!profUpdate.getAttributesToSim().isEmpty()) { return userProfileRepository.findUserProfileById(profUpdate.getProfileId()) .map(profile -> { profUpdate.getAttributesToSet().putAll( collectMissingAttributes(profUpdate.getAttributesToSim(), profile.getAttributes().keySet())); return profUpdate; }); } return Mono.just(profUpdate); }
The above methods are called as follows:
Mono.just(update) .flatMap(update -> upsertUserIdentifier(update, id)) .flatMap(this::transform)
Advertisement
Answer
Nebulous answer, but… it depends!
The danger of mutating an input parameter in the returned Mono
or Flux
comes from the fact that said Mono
or Flux
could be subscribed multiple times. In such a case, suddenly you have a shared resource on your hands, and it can lead to puzzling issues.
But if the methods in question are called from a well controlled context, it can be safe.
In your case, flatMap
ensures that the inner publishers are subscribed to only once. So as long as you only use these methods inside such flatMaps, they can safely mutate their input parameter (it is kept in the scope of the flatmapping function).