Return null or something nullable from lambda in transformation mehtod WebFlux
Asked Answered
S

1

10

In a Spring WebFlux chain I use a map operation which sometimes may return null and I get a warning :
Return null or something nullable from lambda in transformation mehtod.
I believe when data is null it doesn't actually map input to null but it will raise an exception instead.
What is the best way to handle the scenario ?

Map method which is nullable :

public Pojo parseJson(String json) {
    try {
        // parse 
        return pojo;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

My reactive chain :

public Mono<Pojo> query(long id) {

    Integer value = idMapper.getValue(id);

    if (value != null) {
        return repo.query(value)

                        Parse Method
                             |
                             v
                .map(this::parse);
    }
    return null;
}
Stephanus answered 21/12, 2019 at 14:28 Comment(4)
It's unclear how the two code snippets are connected. Also, why do you return null from a method returning a Mono? It should return a Mono, not null. Same for parseJson: why do you ignore all the exceptions that happen there, instead of propagating them?Usurp
@JBNizet I edited my question to make it more clear about the connection. Can you give me a sample in the way you are talking about.Stephanus
Initialise the return "pojo" variable before hand as null. And initialise the pojo inside the try catch method. If there's an error set pojo = null and return pojo.Shrieve
Here's what I mean: gist.github.com/jnizet/492c0f796e6dc54e48a3ed1772368267Usurp
L
18

When working in a functional/reactive world you should try to avoid all null checks and try to never return null from any methods.

Instead return Optional<T> when there is a risk for a null return, and return Mono.error when there is an error in a function that returns Mono. Or return Mono.empty if you just want to skip returning something.

By using optional you can rewrite the code to something much cleaner.

public Optional<Pojo> parseJson(String json) {
    // Return an optional if there is risk for a null.
    return Optional.ofNullable(new Pojo());
}

private final IdMapper idMapper = new IdMapper();
private final Repo repo = new Repo();

public Mono<Pojo> query(long id) {

    // By returning an optional from the idMapper 
    // you can chain on and avoid null checks.
    return idMapper.getValue(id).map(integer -> repo.query(integer)
            .map(s -> parseJson(s).map(Mono::just)
                    .orElse(Mono.empty())))
            .orElse(Mono.error(() -> new NotFoundException("No Pojo with ID could be found")));
}

class Pojo {
    // Some pojo class
}

class Repo {
    public Mono<String> query(long id) {
        return Mono.just("Foo");
    }
}

class IdMapper {

    public Optional<Integer> getValue(long id) {
        // Here return an Optional instead of null!
        return Optional.of(1);
    }
}

Here i return Optionals and a make some decisions to either return a Mono.empty or a Mono.error depending on what happens.

Leighannleighland answered 21/12, 2019 at 16:28 Comment(2)
If you are using WebFlux for reactive programming, use flatMap instead of map like this: .flatMap(s -> parseJson(s).map(Mono::just).orElse(Mono.empty())))Aquavit
It depends on the usercase. flatMap and map have different usercases, so you dont ”have to” use flatmapLeighannleighland

© 2022 - 2024 — McMap. All rights reserved.