Reputation: 3495
Given following method:
Flux<Person> getAllPerson(Criteria criteria)
How do i process the flux by changing a field in each of the Person object in the flux?
getAllPerson(criteria)
.map(person -> person.setLastUpdated(new Date())
The setLastUpdated(new Date()) returns void
I've tried a lot of different ways but i can't figure out the way to make it compile, for e.g.:
getAllPerson(criteria)
.map(person -> {
person.setLastUpdated(new Date())
return person;
});
Upvotes: 3
Views: 5299
Reputation: 1
You leverage Flux's handle method instead of map (see https://projectreactor.io/docs/core/release/reference/index.html#_handle). With handle you can managed errors that can occur while processing your records.
Date date = new Date();
getAllPerson(criteria)
.handle(p, sink) -> {
Person p1 = p; // clone p if needed
try {
// assuming your mutation can generate errors
person.withLastUpdated(date);
sink.next(p1);
} catch(Exception e) {
sink.error(e);
}
})
Upvotes: 0
Reputation: 72284
Your second example:
getAllPerson(criteria)
.map(person -> {
person.setLastUpdated(new Date())
return person;
});
...won't compile, but only because it's missing a semicolon on the setLastUpdated()
line.
However, by far the best thing to do here (as suggested already) is to make your Person
class immutable. You can then use the "wither" pattern (either using lombok or your own implementation) to simply do:
getAllPerson(criteria)
.map(person -> person.withLastUpdated(new Date()));
If you can't make Person
immutable (either because it's an external library, or its mutability is simply too baked into existing code), then all is not lost. You can still produce an immutable wrapper quite easily, eg:
class ImmutablePerson {
Person person;
public ImmutablePerson(Person p) {
this.person = p;
}
public Person withFirstName(String name) {
return new Person(name, person.getLastName(), person.getLastUpdated());
}
public Person withLastName(String name) {
return new Person(person.getFirstName(), name, person.getLastUpdated());
}
public Person withLastUpdated(Date date) {
return new Person(person.getFirstName(), person.getLastName(), date);
}
public String getFirstName() {return person.getFirstName();}
public String getLastName() {return person.getLastName();}
public Date getLastUpdated() {return person.getLastUpdated();}
public Person toPerson() {return new Person(person.getFirstName(), person.getLastName(), person.getLastUpdated());}
}
You can then just map to ImmutablePerson
in the first step of your reactive chain like so:
getAllPerson(criteria)
.map(ImmutablePerson::new)
.map(p -> p.withLastUpdated(new Date()))
//etc.
Upvotes: 1
Reputation: 9947
You can use the doOnNext
operator which is intended to execute this kind of side-effect operations.
Although, generally it is a better approach to keep the Person class immutable and when you would need to modify something you would just create a copy of it, in that case you would be able to use the map operator as expected.
Upvotes: 2