Daniel Fernández opened SPR-15551 and commented
In one of the Thymeleaf sample applications using WebFlux, I have a Formatter
like this:
public class VarietyFormatter implements Formatter<Variety> {
...
public Variety parse(final String text, final Locale locale) throws ParseException {
final Integer varietyId = Integer.valueOf(text);
// There is no Formatter API yet that allows us to return a Publisher, so we need to block
return this.varietyService.findById(varietyId).block();
}
}
This is what I think could be a quite common pattern: a Formatter
being used for transforming
a PK (perhaps coming from a form field) into a complete entity object, coming from the database.
The problem is, the service method that this needs to call is reactive:
public Mono<Variety> findById(final Integer id) {
...
}
So either the Formatter#parse()
method calls .block()
, or it returns Mono<Variety>
. But in the latter case, that would mean changing the formatter class's specification to:
public class VarietyFormatter implements Formatter<Mono<Variety>> {
...
}
And this would force us to block at the Formatter#print()
method:
public String print(final Mono<Variety> object, final Locale locale) {
final Variety variety = object.block();
return (variety != null ? variety.getId().toString() : "");
}
Why not return Mono<String>
there? because the Formatter<T>
interface extends from Printer<T>
, and the Printer#print(...)
method is defined as:
String print(T object, Locale locale);
So it seems to me that there is no way to support this scenario in a non-blocking manner right now…
Affects: 5.0 RC1
Comment From: bclozel
Sorry for replying so late.
I don't think the Formatter
interface was meant for such use cases involving remote I/O. This resolution should be done at a different stage / using other infrastructure. We don't plan on offering a reactive variant for this contract at the moment. I'm declining this issue as a result.