8

私は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、例外をスローする場合、Promise値は設定されていませんが、コンソールで次のようになります:

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. おそらくこの機能はまだ実装されていません

4

2 に答える 2

4

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<T>、サービスのメソッド (おそらくビジネス ロジック) の結果として使用する必要があることです。そのため、サービスを使用する人は誰でも、サービスのStream性質に気付き、その結果、Stream他のメソッドに流れ込みます。コードの一部、たとえばawait()、サービスを使用するコードで使用する必要がある場合があります。

完全なアプリケーションはhttps://github.com/evgeniysharapov/spring-reactor-demoで入手できます

于 2015-05-07T21:09:52.100 に答える