[appendix]
[[dataflow-template]]
== Data Flow Template

As described in API Guide chapter, Spring Cloud Data Flow's functionality is completely exposed through 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 entry point is the `DataFlowTemplate` class in the `org.springframework.cloud.dataflow.rest.client` package.

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

|===
| Interface | Description

| `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 can be discovered through the REST relations, which are provided by HATEOAS (Hypermedia as the Engine of Application State).

IMPORTANT: If a resource cannot be resolved, the respective sub-template results
in NULL. A common cause is that Spring Cloud Data Flow allows for specific
sets of features to be enabled or disabled when launching. For more information, see one of the <<configuration-local-enable-disable-specific-features, local>>, <<configuration-cloudfoundry-enable-disable-specific-features, Cloud Foundry>>, or <<configuration-kubernetes-enable-disable-specific-features, Kubernetes>> configuration chapters, depending on where you deploy your application.

=== Using the Data Flow Template

When you use the Data Flow Template, the only needed Data Flow dependency is the
Spring Cloud Data Flow Rest Client, as shown in the following Maven snippet:

====
[source,xml,subs=attributes]
----
&lt;dependency&gt;
  &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
  &lt;artifactId&gt;spring-cloud-dataflow-rest-client&lt;/artifactId&gt;
  &lt;version&gt;{project-version}&lt;/version&gt;
&lt;/dependency&gt;
----
====

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

When instantiating the `DataFlowTemplate`, you also pass in a `RestTemplate`.
Note 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 suffices:

====
[source,java]
----
  @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;
  }
----
====

TIP: You can also get a pre-configured `RestTemplate` by using
`DataFlowTemplate.getDefaultDataflowRestTemplate();`

Now you can instantiate the `DataFlowTemplate` with the following code:

====
[source,java]
----
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 want to get a list of the currently available applications, you can run the following code:

====
[source,java]
----
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()));
}
----
====

=== Data Flow Template and Security

When using the `DataFlowTemplate`, you can also provide all the security-related
options as if you were using the _Data Flow Shell_. In fact, the _Data Flow Shell_
uses the `DataFlowTemplate` for all its operations.

To let you get started, we provide a `HttpClientConfigurer` that uses the builder
pattern to set the various security-related options:

====
[source,java]
----
	HttpClientConfigurer
		.create(targetUri)                                             # <1>
		.basicAuthCredentials(username, password)                      # <2>
		.skipTlsCertificateVerification()                              # <3>
		.withProxyCredentials(proxyUri, proxyUsername, proxyPassword)  # <4>
		.addInterceptor(interceptor)                                   # <5>
		.buildClientHttpRequestFactory()                               # <6>
----

<1> Creates a HttpClientConfigurer with the provided target URI.
<2> Sets the credentials for basic authentication (Using OAuth2 Password Grant)
<3> Skip SSL certificate verification (*Use for DEVELOPMENT ONLY!*)
<4> Configure any Proxy settings
<5> Add a custom interceptor e.g. to set the OAuth2 Authorization header. This allows
you to pass an OAuth2 Access Token instead of username/password credentials.
<6> Builds the `ClientHttpRequestFactory` that can be set on the `RestTemplate`.
====

Once the `HttpClientConfigurer` is configured, you can use its `buildClientHttpRequestFactory`
to build the `ClientHttpRequestFactory` and then set the corresponding
property on the `RestTemplate`. You can then instantiate the actual `DataFlowTemplate`
using that `RestTemplate`.

To configure _Basic Authentication_, the following setup is required:

====
[source,java]
----
	RestTemplate restTemplate = DataFlowTemplate.getDefaultDataflowRestTemplate();
	HttpClientConfigurer httpClientConfigurer = HttpClientConfigurer.create("http://localhost:9393");

	httpClientConfigurer.basicAuthCredentials("my_username", "my_password");
	restTemplate.setRequestFactory(httpClientConfigurer.buildClientHttpRequestFactory());

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

