简体   繁体   中英

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);
}

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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM