【问题标题】:Handling exceptions by Reactor SpringReactor Spring 处理异常
【发布时间】:2015-07-17 05:14:16
【问题描述】:

我正在使用 Reactor 2 和 Spring 4。这是我拥有的典型代码 - Consumer 使用存储库

@Consumer
public class ApplicationService {

   @Selector(value="/applications/id", type = SelectorType.URI)
   @ReplyTo
   public Application byApplicationId(String id) throws ApplicationNotFoundException {
      Application app = appRepo.findOne(id);
      if(app == null) 
        throw new ApplicationNotFoundException("Application `" + id + "` could not be found.");
      return app;
   }
}

然后我有一个控制器将请求传递给eventBus,我将请求传递到其中并返回Promise

@RestController
@RequestMapping("/applications")
public class ApplicationsController {
   @RequestMapping(value = "/{id}", method = GET, produces = APPLICATION_JSON_VALUE)
   public Promise<Event<Application>> byApplicationId(@PathVariable final String id) {
      final Promise<Event<Application>> p = Promises.prepare(env);
      eventBus.sendAndReceive("/applications/id", Event.wrap(id), p);
      return p;
   }

}

一切正常,但如果ApplicationService 抛出异常,Promises 值未设置,但我确实在控制台中得到以下信息:

16:46:58.003 [main] ERROR reactor.bus.EventBus - null
java.lang.reflect.UndeclaredThrowableException
    at org.springframework.util.ReflectionUtils.rethrowRuntimeException(ReflectionUtils.java:302)
...
Caused by: com.metlife.harmony.exceptions.ApplicationNotFoundException: Application `2860c555-0bc4-45e6-95ea-f724ae3f4464` could not be found.
    at com.metlife.harmony.services.ApplicationService.byApplicationId(ApplicationService.java:46) ~[classes/:?]
...
Caused by: reactor.core.support.Exceptions$ValueCause: Exception while signaling value: reactor.bus.Event.class : Event{id=null, headers={}, replyTo=reactor.bus.selector.Selectors$AnonymousKey@4, key=/applications/id, data=2860c555-0bc4-45e6-95ea-f724ae3f4464}

问题是:

  1. 我是否以错误的方式使用 Reactor 和 eventBus?如果是这样,正确的方法是什么

  2. 也许这个功能还没有实现

【问题讨论】:

  • eventBus.sendAndReceive("/applications/id", Event.wrap(id), p); 不会导致转换错误?
  • @AnadiMisra 在什么时候?
  • 出于好奇尝试了您的代码,我在该行得到了这个 The method sendAndReceive(Object, Event&lt;?&gt;, Consumer&lt;T&gt;) in the type EventBus is not applicable for the arguments (String, Event&lt;Trainee&gt;, Promise&lt;ResponseEntity&lt;String&gt;&gt;),我的 Promise 对象 Promise&lt;ResponseEntity&lt;String&gt;&gt; response = Promises.prepare(env);
  • 发生这种情况是因为T 中的Promise&lt;T&gt; 变量应该扩展Event。可能需要更大的上下文,但您也许可以使用原始类型 Promise p = Promises.prepare(env)

标签: java spring spring-mvc reactor project-reactor


【解决方案1】:

我想我重新评估了在我的 Spring 应用程序中使用 Reactor 的策略。

现在我的控制器看起来像

@RestController
public class GreetingController {

    @Autowired
    private GreetingService greetingService;

    @RequestMapping("/greeting")
    public Promise<ResponseEntity<?>> greeting(final @RequestParam(value = "name", defaultValue = "World") String name) {
        return greetingService.provideGreetingFor(name).map(new Function<Greeting, ResponseEntity<?>>() {
            @Override
            public ResponseEntity<?> apply(Greeting t) {
                return new ResponseEntity<>(t, HttpStatus.OK);
            }
        }).onErrorReturn(WrongNameException.class, new Function<WrongNameException, ResponseEntity<?>>() {
            @Override
            public ResponseEntity<?> apply(WrongNameException t) {
                return new ResponseEntity<>(t.getMessage(), HttpStatus.BAD_REQUEST);
            }
        }).next();
    }
}

服务看起来像

@Service
public class GreetingService {
    @Autowired
    private Environment env;

    private static final String template = "Hello, %s!";
    private final AtomicLong counter = new AtomicLong();

    public Stream<Greeting> provideGreetingFor(String name) {
        return Streams.just(name).dispatchOn(env).map(new Function<String, Greeting>() {
            @Override
            public Greeting apply(String t) {
                if (t == null || t.matches(".*\\d+.*"))
                    throw new WrongNameException();
                return new Greeting(counter.incrementAndGet(), String.format(template, t));
            }
        });
    }
}

糟糕的是,现在我必须使用 Stream&lt;T&gt; 作为服务中的方法的结果(这应该是一种业务逻辑),所以使用该服务的任何人现在都知道 Stream-ish 的性质服务,因此Stream 渗入代码的其他部分,例如现在我可能不得不在使用服务的代码中使用await()

完整申请可在https://github.com/evgeniysharapov/spring-reactor-demo获取

【讨论】:

    【解决方案2】:

    反应式参考中处理异常和错误的专门章节在这里阅读:

    https://projectreactor.io/docs/core/release/reference/#error.handling

    在任何情况下,反应式管道在其中性含义上都是“连续的”。您几乎无法阻止它被您的方法的使用者注意到。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-07-04
      • 2023-03-28
      • 2016-10-31
      • 2019-06-02
      • 2017-01-27
      • 2020-12-09
      • 1970-01-01
      相关资源
      最近更新 更多