Appendix A. Data Flow Template

As described in the previous chapter, Spring Cloud Data Flow’s functionality is completely exposed via REST endpoints. While you can use those endpoints directly, Spring Cloud Data Flow also provides a Java-based API, which makes using those REST endpoints even easier.

The central entrypoint is the DataFlowTemplate class in package org.springframework.cloud.dataflow.rest.client.

This class implements the interface DataFlowOperations and delegates to sub-templates that provide the specific functionality for each feature-set:

InterfaceDescription

StreamOperations

REST client for stream operations

CounterOperations

REST client for counter operations

FieldValueCounterOperations

REST client for field value counter operations

AggregateCounterOperations

REST client for aggregate counter operations

TaskOperations

REST client for task operations

JobOperations

REST client for job operations

AppRegistryOperations

REST client for app registry operations

CompletionOperations

REST client for completion operations

RuntimeOperations

REST Client for runtime operations

When the DataFlowTemplate is being initialized, the sub-templates will be discovered via the REST relations, which are provided by HATEOAS.[1]

[Important]Important

If a resource cannot be resolved, the respective sub-template will result in being NULL. A common cause is that Spring Cloud Data Flow offers for specific sets of features to be enabled/disabled when launching. For more information see Chapter 17, Feature Toggles.

A.1 Using the Data Flow Template

When using the Data Flow Template the only needed Data Flow dependency is the Spring Cloud Data Flow Rest Client:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-dataflow-rest-client</artifactId>
  <version>1.2.4.RELEASE</version>
</dependency>

With that dependency you will get the DataFlowTemplate class as well as all needed dependencies to make calls to a Spring Cloud Data Flow server.

When instantiating the DataFlowTemplate, you will also pass in a RestTemplate. Please be aware that the needed RestTemplate requires some additional configuration to be valid in the context of the DataFlowTemplate. When declaring a RestTemplate as a bean, the following configuration will suffice:

  @Bean
  public static RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.setErrorHandler(new VndErrorResponseErrorHandler(restTemplate.getMessageConverters()));
    for(HttpMessageConverter<?> converter : restTemplate.getMessageConverters()) {
      if (converter instanceof MappingJackson2HttpMessageConverter) {
        final MappingJackson2HttpMessageConverter jacksonConverter =
            (MappingJackson2HttpMessageConverter) converter;
        jacksonConverter.getObjectMapper()
            .registerModule(new Jackson2HalModule())
            .addMixIn(JobExecution.class, JobExecutionJacksonMixIn.class)
            .addMixIn(JobParameters.class, JobParametersJacksonMixIn.class)
            .addMixIn(JobParameter.class, JobParameterJacksonMixIn.class)
            .addMixIn(JobInstance.class, JobInstanceJacksonMixIn.class)
            .addMixIn(ExitStatus.class, ExitStatusJacksonMixIn.class)
            .addMixIn(StepExecution.class, StepExecutionJacksonMixIn.class)
            .addMixIn(ExecutionContext.class, ExecutionContextJacksonMixIn.class)
            .addMixIn(StepExecutionHistory.class, StepExecutionHistoryJacksonMixIn.class);
      }
    }
    return restTemplate;
  }

Now you can instantiate the DataFlowTemplate with:

DataFlowTemplate dataFlowTemplate = new DataFlowTemplate(
    new URI("http://localhost:9393/"), restTemplate);         1

1

The URI points to the ROOT of your Spring Cloud Data Flow Server.

Depending on your requirements, you can now make calls to the server. For instance, if you like to get a list of currently available applications you can execute:

PagedResources<AppRegistrationResource> apps = dataFlowTemplate.appRegistryOperations().list();

System.out.println(String.format("Retrieved %s application(s)",
    apps.getContent().size()));

for (AppRegistrationResource app : apps.getContent()) {
  System.out.println(String.format("App Name: %s, App Type: %s, App URI: %s",
    app.getName(),
    app.getType(),
    app.getUri()));
}


[1] HATEOAS stands for Hypermedia as the Engine of Application State