Un'introduzione a Spring Cloud Task

1. Panoramica

L'obiettivo di Spring Cloud Task è fornire la funzionalità per la creazione di microservizi di breve durata per l'applicazione Spring Boot .

In Spring Cloud Task, abbiamo la flessibilità di eseguire qualsiasi attività in modo dinamico, allocando risorse su richiesta e recuperando i risultati dopo il completamento dell'attività.

Tasks è una nuova primitiva all'interno di Spring Cloud Data Flow che consente agli utenti di eseguire praticamente qualsiasi applicazione Spring Boot come attività di breve durata .

2. Sviluppo di un'applicazione per attività semplice

2.1. Aggiunta di dipendenze rilevanti

Per iniziare, possiamo aggiungere la sezione di gestione delle dipendenze con spring-cloud-task-dependencies:

   org.springframework.cloud spring-cloud-task-dependencies 2.2.3.RELEASE pom import   

Questa gestione delle dipendenze gestisce le versioni delle dipendenze tramite l'ambito di importazione.

Dobbiamo aggiungere le seguenti dipendenze:

 org.springframework.cloud spring-cloud-starter-task   org.springframework.cloud spring-cloud-task-core 

Questo è il collegamento al Maven Central di spring-cloud-task-core .

Ora, per avviare la nostra applicazione Spring Boot, abbiamo bisogno di spring-boot-starter con il genitore pertinente.

Utilizzeremo Spring Data JPA come strumento ORM, quindi dobbiamo aggiungere anche la dipendenza per questo:

 org.springframework.boot spring-boot-starter-data-jpa 2.2.6.RELEASE 

I dettagli del bootstrap di una semplice applicazione Spring Boot con Spring Data JPA sono disponibili qui.

Siamo in grado di controllare la versione più recente della primavera-boot-starter-genitore o n Maven centrale.

2.2. L' annotazione @EnableTask

Per eseguire il bootstrap della funzionalità di Spring Cloud Task, dobbiamo aggiungere l' annotazione @EnableTask :

@SpringBootApplication @EnableTask public class TaskDemo { // ... } 

L'annotazione porta la classe SimpleTaskConfiguration nell'immagine che a sua volta registra il TaskRepository e la sua infrastruttura . Per impostazione predefinita, viene utilizzata una mappa in memoria per memorizzare lo stato del TaskRepository .

Le informazioni principali di TaskRepository sono modellate nella classe TaskExecution . I campi annotati di questa classe sono taskName , startTime , endTime , exitMessage . L'ExitMessage memorizza le informazioni disponibili al tempo di uscita.

Se un'uscita è causata da un errore in qualsiasi caso dell'applicazione, la traccia completa dello stack delle eccezioni verrà archiviata qui.

Spring Boot fornisce un'interfaccia ExitCodeExceptionMapper che mappa le eccezioni non rilevate ai codici di uscita consentendo un debug analizzato . L'attività cloud archivia le informazioni nell'origine dati per analisi future.

2.3. Configurazione di un DataSource per TaskRepository

La mappa in memoria per archiviare TaskRepository svanirà al termine dell'attività e perderemo i dati relativi agli eventi dell'attività . Per archiviare in una memoria permanente, utilizzeremo MySQL come origine dati con Spring Data JPA.

L'origine dati è configurata nel file application.yml . Per configurare Spring Cloud Task per utilizzare l'origine dati fornita come archiviazione di TaskRepository , è necessario creare una classe che estenda DefaultTaskConfigurer .

Ora possiamo inviare l' origine dati configurata come argomento del costruttore al costruttore della superclasse:

@Autowired private DataSource dataSource; public class HelloWorldTaskConfigurer extends DefaultTaskConfigurer{ public HelloWorldTaskConfigurer(DataSource dataSource){ super(dataSource); } }

Per avere la configurazione di cui sopra in azione, dobbiamo annotare un'istanza di DataSource con l' annotazione @Autowired e inserire l'istanza come argomento del costruttore di un bean HelloWorldTaskConfigurer definito sopra:

@Bean public HelloWorldTaskConfigurer getTaskConfigurer() { return new HelloWorldTaskConfigurer(dataSource); }

Questo completa la configurazione per memorizzare TaskRepository nel database MySQL.

2.4. Implementazione

In Spring Boot, possiamo eseguire qualsiasi attività appena prima che l'applicazione termini il suo avvio. Possiamo usare le interfacce ApplicationRunner o CommandLineRunner per creare un semplice Task.

Dobbiamo implementare il metodo run di queste interfacce e dichiarare la classe di implementazione come un bean:

@Component public static class HelloWorldApplicationRunner implements ApplicationRunner { @Override public void run(ApplicationArguments arg0) throws Exception { System.out.println("Hello World from Spring Cloud Task!"); } }

Ora, se eseguiamo la nostra applicazione, dovremmo fare in modo che il nostro compito produca l'output necessario con le tabelle richieste create nel nostro database MySQL registrando i dati dell'evento dell'attività.

3. Ciclo di vita di un'attività Spring Cloud

All'inizio creiamo una voce nel TaskRepository . Questa è l'indicazione che tutti i bean sono pronti per essere utilizzati nell'applicazione e il metodo di esecuzione dell'interfaccia Runner è pronto per essere eseguito.

Al termine dell'esecuzione del metodo di esecuzione o in qualsiasi errore dell'evento ApplicationContext , TaskRepository verrà aggiornato con un'altra voce.

Durante il ciclo di vita delle applicazioni, siamo in grado di registrare gli ascoltatori disponibili da TaskExecutionListener interfaccia . Abbiamo bisogno di una classe che implementa l'interfaccia con tre metodi: onTaskEnd , onTaksFailed e onTaskStartup attivati ​​nei rispettivi eventi del Task.

Dobbiamo dichiarare il bean della classe di implementazione nella nostra classe TaskDemo :

@Bean public TaskListener taskListener() { return new TaskListener(); }

4. Integrazione con Spring Batch

We can execute Spring Batch Job as a Task and log events of the Job execution using Spring Cloud Task. To enable this feature we need to add Batch dependencies pertaining to Boot and Cloud:

 org.springframework.boot spring-boot-starter-batch   org.springframework.cloud spring-cloud-task-batch 

Here is the link to the Maven Central of spring-cloud-task-batch.

To configure a job as a Task we need to have the Job bean registered in the JobConfiguration class:

@Bean public Job job2() { return jobBuilderFactory.get("job2") .start(stepBuilderFactory.get("job2step1") .tasklet(new Tasklet(){ @Override public RepeatStatus execute( StepContribution contribution, ChunkContext chunkContext) throws Exception { System.out.println("This job is from Baeldung"); return RepeatStatus.FINISHED; } }).build()).build(); }

We need to decorate the TaskDemo class with @EnableBatchProcessing annotation:

//..Other Annotation.. @EnableBatchProcessing public class TaskDemo { // ... }

The @EnableBatchProcessing annotation enables Spring Batch features with a base configuration required to set up batch jobs.

Now, if we run the application, the @EnableBatchProcessing annotation will trigger the Spring Batch Job execution and Spring Cloud Task will log the events of the executions of all batch jobs with the other Task executed in the springcloud database.

5. Launching a Task from Stream

We can trigger Tasks from Spring Cloud Stream. To serve this purpose, we have the @EnableTaskLaucnher annotation. Once, we add the annotation with Spring Boot app, a TaskSink will be available:

@SpringBootApplication @EnableTaskLauncher public class StreamTaskSinkApplication { public static void main(String[] args) { SpringApplication.run(TaskSinkApplication.class, args); } }

The TaskSink receives the message from a stream that contains a GenericMessage containing TaskLaunchRequest as a payload. Then it triggers a Task-based on co-ordinate provided in the Task launch request.

To have TaskSink functional, we require a bean configured that implements TaskLauncher interface. For testing purpose, we're mocking the implementation here:

@Bean public TaskLauncher taskLauncher() { return mock(TaskLauncher.class); }

We need to note here that the TaskLauncher interface is only available after adding the spring-cloud-deployer-local dependency:

 org.springframework.cloud spring-cloud-deployer-local 2.3.1.RELEASE 

We can test whether the Task launched by invoking input of the Sink interface:

public class StreamTaskSinkApplicationTests { @Autowired private Sink sink; // }

Ora creiamo un'istanza di TaskLaunchRequest e la inviamo come payload dell'oggetto GenericMessage . Quindi possiamo invocare il canale di input del Sink mantenendo l' oggetto GenericMessage nel canale.

6. Conclusione

In questo tutorial, abbiamo esplorato come esegue Spring Cloud Task e come configurarlo per registrare i suoi eventi in un database. Abbiamo anche osservato come il lavoro Spring Batch viene definito e archiviato nel TaskRepository . Infine, abbiamo spiegato come possiamo attivare Task dall'interno di Spring Cloud Stream.

Come sempre, il codice è disponibile su GitHub.