【问题标题】:Spring Webflux: Do I need to catch(Throwable) for triggering Mono.doOnError?Spring Webflux:我需要 catch(Throwable) 来触发 Mono.doOnError 吗?
【发布时间】:2021-07-14 09:12:26
【问题描述】:

我有以下代码创建一个产品,然后在某种历史服务(journalClient)中记录创建成功。

如果日志客户端出现错误,我想回滚产品创建。

@Service
public class ProductService {

    public Mono<ProductRS> createProduct(final ProductRQ rq) {
       return productclient.createProduct(rq).flatMap(produktfamilieRS -> {
         return journalClient.createJournalEntry("Dummy-Entry").thenReturn(productRS)
             .doOnError(throwable -> {
                 log.error("Error creating journal Entry - Starting rollback of transaction.");
                 rollbackCreateProduct(productRS.getId());
          });
    });

    private void rollbackCreateProduktfamilie(long id) {
       productClient.deleteProduct(id).subscribe();
    }
@Service
public class JournalClientMockImpl implements JournalClientMock {

  public Mono<Void> createJournalEntry(String body, boolean error) {
    throw new RuntimeExcpeption("Test Error");
  }

我的问题是,我在 JournalClient 中抛出的 RuntimeException 不会触发 ProductService.createProduct 中的 Mono.doOnError()。

关键点:我发现返回 Mono.error 会触发外部 doOnError:

@Service
public class JournalClientMockImpl implements JournalClientMock {

  public Mono<Void> createJournalEntry(String body, boolean error) {
      return Mono.error(new RuntimeException("Beabsichtiger Fehler im JournalServiceMock"));
  }

但我的问题是,我的业务逻辑中可能存在错误,导致 RuntimeExceptions 不会以 Mono.error 结尾。

我的坏主意:我唯一的想法就是做这样的事情......用一个包罗万象的东西包围整个代码:

  public Mono<Void> createJournalEntry(String body, boolean error) {
    try{
      // do some business logic
      // ...
      // call journal web service
      // ...
      return Mono.empty();
    } catch (Throwable e){
      return Mono.error(new RuntimeException("Error in JournalServiceMock"));
    }
   
  }

这应该是解决方案吗?这闻起来像非常糟糕的设计。 如何正确执行此操作?

非常感谢

【问题讨论】:

  • Do on error 仅用于副作用,例如日志记录等。如果您希望切换到另一个发布者,您应该使用例如 onErrorResume。

标签: spring spring-webflux reactive


【解决方案1】:

尝试 .onErrorResume 而不是 .doOnError

@Service
public class ProductService {

    public Mono<ProductRS> createProduct(final ProductRQ rq) {
       return productclient.createProduct(rq).flatMap(produktfamilieRS -> {
         return journalClient.createJournalEntry("Dummy-Entry").thenReturn(productRS)
             .onErrorResume(throwable -> {
                 log.error("Error creating journal Entry - Starting rollback of transaction.");
                 rollbackCreateProduct(productRS.getId());
          });
    });

    private void rollbackCreateProduktfamilie(long id) {
       productClient.deleteProduct(id).subscribe();
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-15
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 1970-01-01
    • 2011-01-14
    • 2015-07-22
    相关资源
    最近更新 更多