2014-10-12 10 views
14

Sto costruendo un'applicazione java della riga di comando utilizzando Spring Boot per farlo funzionare rapidamente.Come chiudere un'applicazione di riga di comando Spring Boot

L'applicazione carica diversi tipi di file (ad esempio CSV) e li carica in un database Cassandra. NON usa componenti web, non è un'applicazione web.

Il problema che sto avendo è quello di interrompere l'applicazione quando il lavoro è finito. Sto usando l'interfaccia Spring CommandLineRunner con un @Component per eseguire le attività, come mostrato di seguito, ma quando il lavoro è completato l'applicazione non si ferma, continua a funzionare per qualche motivo e non riesco a trovare un modo per fermarlo.

@Component 
public class OneTimeRunner implements CommandLineRunner { 

    @Autowired 
    private CassandraOperations cassandra; 

    @Autowired 
    private ConfigurableApplicationContext context; 

    @Override 
    public void run(String... args) throws Exception { 
     // do some work here and then quit 
     context.close(); 
    } 
} 

UPDATE: il problema sembra essere spring-cassandra, dal momento che non c'è niente altro nel progetto. Qualcuno sa perché mantiene i thread in esecuzione in background che impediscono l'arresto dell'applicazione?

UPDATE: il problema è scomparso con l'aggiornamento all'ultima versione di avvio di primavera.

+0

Qualsiasi soluzione a questo? Succede con il normale avvio a molla (senza cassandra) – ACV

+1

@ ACV no, io vivo solo con esso. Ho appreso che alcuni moduli molla generano i propri thread, ad es. Cassandra dispone di un pool di thread per le connessioni o RabbitMQ quando si utilizzano contenitori listener. Questi richiedono del tempo per spegnersi dopo aver chiamato 'context.close()' per fermare l'applicazione. – ESala

+0

Vedere la risposta sotto – ACV

risposta

8

La risposta dipende da cosa sta ancora facendo il lavoro. Probabilmente puoi scoprirlo con un dump del thread (es. Usando jstack). Ma se è tutto ciò che è stato avviato da Spring, dovresti essere in grado di usare ConfigurableApplicationContext.close() per fermare l'app nel tuo metodo main() (o nel CommandLineRunner).

+0

Ok, ho eseguito il debug dell'applicazione con un breakpoint e ci sono 17: Thread [New I/O worker # (1-17)].Devo indagare su questo. Informazioni su ConfigurableApplicationContext.close(), ci vogliono circa 30 secondi per fermare l'applicazione, è normale ?? – ESala

+0

Dovrà aspettare per qualunque cosa stia funzionando per rilasciare i thread. Sembra un timeout per me. –

+0

Esattamente, ho il sospetto che la Spring Cassandra stia mantenendo in funzione questi thread per qualche motivo. – ESala

9

Ho trovato una soluzione. È possibile utilizzare questo:

public static void main(String[] args) { 
    SpringApplication.run(RsscollectorApplication.class, args).close(); 
    System.out.println("done"); 
} 

Basta usare. Chiudere sulla corsa.

+0

beh si ... se guardi il codice della domanda, sto facendo proprio questo. 'SpringApplication.run (Main.class, args)' restituisce un 'ConfigurableApplicationContext' che puoi memorizzare o' @ Autowire' più tardi come faccio io. Il problema che sto avendo su questa domanda è che dopo aver chiamato 'close()' nel contesto, l'applicazione si blocca per un po 'di tempo. – ESala

+0

OK, chiaro. Potrebbe essere che i file richiedano tempo per essere scaricati nel database – ACV

4

Ho anche riscontrato questo problema nel mio progetto corrente (applicazione di avvio a molla). La mia soluzione è:

// releasing all resources 
((ConfigurableApplicationContext) ctx).close(); 
// Close application 
System.exit(0); 

context.close() non si fermano la nostra applicazione di console, è solo liberando le risorse.

0

Utilizzare org.springframework.boot.SpringApplication#exit. Per esempio.

@Component 
public class OneTimeRunner implements CommandLineRunner { 

    @Autowired 
    private ConfigurableApplicationContext context; 

    @Override 
    public void run(String... args) throws Exception { 
     SpringApplication.exit(context); 
    } 
} 
1

Questa è una combinazione di @EliuX risposta con @Quan Vo uno. Grazie ad entrambi!

La differenza principale è che il codice di risposta SpringApplication.exit (contesto) viene passato come parametro a System.exit(), quindi se si verifica un errore durante la chiusura del contesto Spring si noterà.

SpringApplication.exit() chiuderà il contesto Spring.

System.exit() chiude l'applicazione.

@Component 
public class OneTimeRunner implements CommandLineRunner { 

    @Autowired 
    private ConfigurableApplicationContext context; 

    @Override 
    public void run(String... args) throws Exception { 
     System.exit(SpringApplication.exit(context)); 
    } 
}