2015-05-06 16 views
5

Sto usando reattore 2 e Spring 4. Ecco il codice tipico che ho - un Consumer lavorare con un repositoryGestione delle eccezioni di Reactor Primavera

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

Poi ho un controller che passa la richiesta a un eventBus in cui mi passa le richieste e restituisce un 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; 
    } 

} 

le cose funzionano, ma in caso di ApplicationService un'eccezione Promise s valore non è impostato, ma ottengo seguente in th e console:

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={}, [email protected], key=/applications/id, data=2860c555-0bc4-45e6-95ea-f724ae3f4464} 

domande sono:

  1. posso utilizzare reattore e eventBus in modo sbagliato? e se sì, qual è il modo giusto

  2. forse questa funzionalità non è ancora implementato

+0

'eventBus.sendAndReceive ("/ applicazioni/id", Event.wrap (id), p);' esso non cuase errore di casting? –

+0

@AnadiMisra a che punto? – EvgeniySharapov

+0

Stavo provando il tuo codice per curiosità e ho ottenuto questo 'Il metodo sendAndReceive (Oggetto, Evento , Consumer ) nel tipo EventBus non è applicabile per gli argomenti (String, Evento >)' a quello line, my Promise object 'Promise > response = Promises.prepare (env);' –

risposta

3

Credo rivalutato la strategia di utilizzo del reattore nella mia applicazione primavera.

Ora il mio controller sembra

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

E il servizio sembra

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

Cosa c'è di male è che ora devo usare Stream<T> come risultato del metodo del servizio (che è presumibilmente una logica di business), quindi chiunque usi il servizio è ora a conoscenza della natura del servizio Stream e di conseguenza Stream sanguina in altre parti del codice, ad esempio ora potrei dover usare await() nel codice usando il servizio.

applicazione completa è disponibile presso https://github.com/evgeniysharapov/spring-reactor-demo