2014-10-14 9 views
8

Sto usando spring-cloud-starter (ovvero .. avvio a molla con tutte le funzionalità dei microservizi). Quando creo il metodo hystrix in un componente annotato utilizzando javanica @HystrixCommand, segui le istruzioni sul sito javanica github (https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica) per fare in modo che quel metodo esegua async, indipendentemente dal fatto che io usi il "futuro <>" o l'esecuzione reattiva "Osservabile < > ', niente esegue/esegue e ottengo
java.lang.ClassCastException: springbootdemo.EricComponent$1 cannot be cast to springbootdemo.Eric ogni volta che tento di estrarre il risultato (nel caso di Future <>) o ottenere una richiamata (in caso di Esecuzione reattiva .. e non si innesca println così non è stato eseguito correttamente).I metodi asstrix di Hystrix all'interno di javanica non sono in esecuzione nell'applicazione java spring-boot

public class Application { ... 
} 
@RestController 
@RequestMapping(value = "/makebunchofcalls/{num}") 
class EricController { .. 

    @RequestMapping(method={RequestMethod.POST}) 
    ArrayList<Eric> doCalls(@PathVariable Integer num) throws IOException { 
     ArrayList<Eric> ale = new ArrayList<Eric>(num); 
     for (int i =0; i<num; i++) { 
      rx.Observable<Eric> oe = this.ericComponent.doRestTemplateCallAsync(i); 
      oe.subscribe(new Action1<Eric>() { 
       @Override 
       public void call(Eric e) { // AT RUNTIME, ClassCastException 
        ale.add(e); 
       } 
      }); 
     } 

     return ale; 
    } 

@Component 
class EricComponent { ... 

    // async version =========== using reactive execution via rx library from netflix ============== 

    @HystrixCommand(fallbackMethod = "defaultRestTemplateCallAsync", commandKey = "dogeAsync") 
    public rx.Observable<Eric> doRestTemplateCallAsync(int callNum) { 
     return new ObservableResult<Eric>() { 
      @Override 
      public Eric invoke() { // NEVER CALLED 
       try { 
        ResponseEntity<String> result = restTemplate.getForEntity("http://doges/doges/24232/photos", String.class); // actually make a call 
        System.out.println("*************** call successfull: " + new Integer(callNum).toString() + " *************"); 
       } catch (Exception ex) { 
        System.out.println("=============== call " + new Integer(callNum).toString() + " not successfull: " + ex.getMessage() + " ============="); 
       } 
       return new Eric(new Integer(callNum).toString(), "ok"); 
      } 
     }; 
    } 

    public rx.Observable<Eric> defaultRestTemplateCallAsync(int callNum) { 
     return new ObservableResult<Eric>() { 
      @Override 
      public Eric invoke() { 
       System.out.println("!!!!!!!!!!!!! call bombed " + new Integer(callNum).toString() + "!!!!!!!!!!!!!"); 
       return new Eric(new Integer(callNum).toString(), "bomb"); 
      } 
     }; 
    } 
} 

Perché dovrei essere sempre di nuovo un EricComponent$1 invece di un Eric? btw, Eric è solo una semplice classe con 2 stringhe ... il suo omesso.

Sto calcolando che devo eseguire esplicitamente, ma che mi allude perché: 1) Farlo con Future <> il metodo queue() non è disponibile come afferma la documentazione e 2) farlo con Observable <> non c'è davvero un modo per eseguirlo che ottengo.

risposta

3

Hai l'annotazione @EnableHystrix nella classe dell'applicazione?

Il metodo subscribe è asincrono e si sta tentando di compilare un elenco in un metodo di controllo sincrono in modo che possa esserci un problema. Puoi cambiare il subscribe in toBlockingObservable().forEach() e vedere se questo aiuta?

Aggiornamento n. 1 Sono stato in grado di duplicare. Il tuo metodo predefinito non dovrebbe restituire uno Observable<Eric>, solo uno Eric.

public Eric defaultRestTemplateCallAsync(final int callNum) { 
    System.out.println("!!!!!!!!!!!!! call bombed " + new Integer(callNum) + "!!!!!!!!!!!!!"); 
    return new Eric(new Integer(callNum).toString(), "bomb"); 
} 

Aggiornamento # 2 Vedere il mio codice qui https://github.com/spencergibb/communityanswers/tree/so26372319

Update # 3 Quando ho commentato l'attributo fallbackMethod, si lamentava che non riusciva a trovare una versione pubblica di EricComponent per AOP. Ho fatto EricComponentpublic static e ha funzionato. Una classe di primo livello nel proprio file avrebbe funzionato. Il mio codice, collegato sopra, funziona (supponendo che la chiamata restTemplate funzioni) e restituisce n OK.

+0

Grazie a @spencergibb per il tempo che ci hai dedicato. Ho avuto @EnableHystrix .. ed è stato in grado di evitare ClassCastException in base al tuo suggerimento per sostituire 'Observable ' in 'Eric' dal valore predefinito. Qualcuno dovrebbe aggiornare la documentazione Javanica per dichiararlo. Tuttavia, quando eseguo questo, ottengo tutte le stampe "call bombardate". Inoltre il metodo 'richiamare()' 'sulla ObservableResult ' tornato ancora non viene mai eseguito. – RubesMN

+0

Per l'aggiornamento n. 3, risulta che la separazione di EricComponent nel proprio file ha funzionato perfettamente. Tutto funziona ora. Inoltre, il passaggio al blocco tramite BlockingObservables e non-blocking tramite normali Observables funziona anch'esso e mi fornisce ciò di cui avevo bisogno per il mio POC. Grazie ancora a @spencergibb. – RubesMN