Haider
Haider

Reputation: 615

Getting 404 error when returning Mono Void

I am creating a web application for learning purpose using spring web flux, I have a function which first checks if records exits then it updates it else it throws custom NotFoundException. The issue is when i return Mono the controller throws 404 error but when i return the class object which was updated it runs fine and i don't want to return whole object.

The following code runs fine

public Mono<Application> publish(String id,boolean publish) 
{
    return appRepository.findById(id).flatMap( a -> {
        a.setPublished(publish);
        return appRepository.save(a);
    }).switchIfEmpty( Mono.error(new NotFoundException("Application Not Found")));
}

and below code where 404 error occurs

public Mono<Void> publish(String id,boolean publish) 
{
    return appRepository.findById(id).flatMap( a -> {
        a.setPublished(publish);
        appRepository.save(a);
        return Mono.empty().then();
    }).switchIfEmpty( Mono.error(new NotFoundException("Application Not Found")));
}

I have extended the repository from ReactiveMongoRepository and controller class is just calling the service function

@PutMapping(APP_ROOT_URL + "/{id}/publish")
public Mono<Void>  publish(@PathVariable("id") String id)
{
    return appService.publish(id, true);
}

Upvotes: 0

Views: 2066

Answers (1)

Abhinaba Chakraborty
Abhinaba Chakraborty

Reputation: 3671

The first method doesnt return 404 because:

appRepository.save(a) returns the persisted entity. Not an empty mono. So the switchIfEmpty clause is not triggered.

This is from the doc of ReactiveCrudRepository (one of the parent repositories of ReactiveMongoRepository)

   /**
     * Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
     * entity instance completely.
     *
     * @param entity must not be {@literal null}.
     * @return {@link Mono} emitting the saved entity.
     * @throws IllegalArgumentException in case the given {@literal entity} is {@literal null}.
     */
    <S extends T> Mono<S> save(S entity);

In second method, you are explicitly returning empty mono. That is why the switchIfEmpty clause is triggered.

One more thing, I would like to point out: The switchIfEmpty clause is not placed correctly. Since findById returns an empty mono if record is not found for an id, switchIfEmpty should come after that. If you place switchIfEmpty after save, it will never return an empty mono.

So you should have something like this:

public Mono<Application> publish(String id,boolean publish) 
{
    return appRepository.findById(id)
      .switchIfEmpty( Mono.error(new NotFoundException("Application Not Found")))
      .flatMap( a -> {
        a.setPublished(publish);
        return appRepository.save(a);
    });
}

And if you want the return type of the method to be Mono<Void> then simply have something like this:

public Mono<Void> publish(String id, boolean publish) 
{
    return appRepository.findById(id)
      .switchIfEmpty( Mono.error(new NotFoundException("Application Not Found")))
      .flatMap( a -> {
        a.setPublished(publish);
        return appRepository.save(a);
    })
    .then();
}

Upvotes: 2

Related Questions