Skip to content
This repository was archived by the owner on Jul 19, 2022. It is now read-only.

Implement TaskLaunchRequestFunction #20

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions function/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,43 @@ Transform incoming message payload based on a SpEL expression and produces an ou
`filter-function`

Filter an incoming message based on a boolean SpEL expression and produces that message or nothing according expression result.

`task-launch-request-function`

Transform input Message to a Message<TaskLaunchRequest>. The `TaskLaunchRequest` can be used as input to the `tasklauncher-function`.

==== Task Launch Request

The `TaskLaunchRequest` is a value object that is used to launch a task using a Data Flow server.
The TaskLaunchRequest contains the name of the task to launch. This must the name of a defined task in Data Flow.
You may optionally provide command line arguments and deployment properties. For more details, see `tasklauncher-function`.

===== Task Name

The task name is a required field. This may be statically configured by setting `task.launch.request.task-name`,
or extracted from the Message by setting `task.launch.request.task-name-expression`.
You may also provide a custom implementation of the `TaskNameMessageMapper` bean to enable more complex task name mappings.

===== Task Command Line Arguments

The task to be launched often requires additional data which is passed to the task as command line arguments.
The `task.launch.request.args` property accepts a comma delimited string of key-value pairs, for example
`key1=val1,key2=val2`. In addition, the `task.launch.request.arg-expressions` property allows you to use SpEL expressions to evaluate
message contents to extract command line arguments.
For example, `task.launch.request.arg-expressions=foo=payload.toUpperCase(),bar=payload.substring(0,2)`.

You may also provide a custom implementation of the `CommandLineArgumentsMessageMapper` bean to implement more complex logic.

===== Task Deployment Properties

Deployment properties are platform-specific configuration used by the `TaskLauncher` and are always statically configured by
setting `task.launch.request.deployment-properties` and apply to every task launch request.

NOTE: When embedding the `task-launch-request-function` into a Spring Boot application, it should be imported with
`@ImportAutoConfiguration(TaskLaunchRequestFunctionConfiguration.class)`.
This is required when providing custom bean definitions, as described above.
Otherwise, the function configuration will not detect the provided beans.

`TaskLaunchRequestFunctionTests` provides some configuration examples.


37 changes: 37 additions & 0 deletions function/task-launch-request-function/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>io.pivotal.java.function</groupId>
<artifactId>spring-functions-parent</artifactId>
<version>1.0.0.BUILD-SNAPSHOT</version>
<relativePath>../../spring-functions-parent</relativePath>
</parent>

<modelVersion>4.0.0</modelVersion>

<artifactId>task-launch-request-function</artifactId>
<name>task-launch-request-function</name>

<dependencies>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.pivotal.java.function.tasklaunchrequest.function;

import io.pivotal.java.function.tasklaunchrequest.function.support.TaskNameMessageMapper;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.messaging.Message;

public class ExpressionEvaluatingTaskNameMessageMapper implements TaskNameMessageMapper {

private final Expression expression;
private final EvaluationContext evaluationContext;

public ExpressionEvaluatingTaskNameMessageMapper(Expression expression, EvaluationContext evaluationContext) {
this.evaluationContext = evaluationContext;
this.expression = expression;
}

@Override
public String processMessage(Message<?> message) {
return expression.getValue(evaluationContext, message).toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.pivotal.java.function.tasklaunchrequest.function;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.springframework.util.StringUtils;

/**
* Parses a comma delimited list of key value pairs in which the values can contain commas as well.
*
* @author Chris Schaeffer
* @author David Turanski
**/
abstract class KeyValueListParser {

static Map<String, String> parseCommaDelimitedKeyValuePairs(String value) {
Map<String, String> keyValuePairs = new HashMap<>();

if (StringUtils.isEmpty(value)) {
return keyValuePairs;
}

ArrayList<String> pairs = new ArrayList<>();

String[] candidates = StringUtils.commaDelimitedListToStringArray(value);

for (int i = 0; i < candidates.length; i++) {
if (i > 0 && !candidates[i].contains("=")) {
pairs.add(pairs.get(pairs.size() - 1) + "," + candidates[i]);
}
else {
pairs.add(candidates[i]);
}
}

for (String pair : pairs) {
addKeyValuePair(pair, keyValuePairs);
}

return keyValuePairs;
}

private static void addKeyValuePair(String pair, Map<String, String> properties) {
int firstEquals = pair.indexOf('=');
if (firstEquals != -1) {
properties.put(pair.substring(0, firstEquals).trim(), pair.substring(firstEquals + 1).trim());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.pivotal.java.function.tasklaunchrequest.function;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TaskLaunchRequest {
@JsonProperty("args")
private List<String> commandlineArguments = new ArrayList<>();

@JsonProperty("deploymentProps")
private Map<String, String> deploymentProperties = new HashMap<>();

@JsonProperty("name")
private String taskName;

public void setCommandlineArguments(List<String> commandlineArguments) {
this.commandlineArguments = new ArrayList<>(commandlineArguments);
}

public List<String> getCommandlineArguments() {
return this.commandlineArguments;
}

public void setDeploymentProperties(Map<String, String> deploymentProperties) {
this.deploymentProperties = deploymentProperties;
}

public Map<String, String> getDeploymentProperties() {
return this.deploymentProperties;
}

public void setTaskName(String taskName) {
this.taskName = taskName;
}

public String getTaskName() {
return this.taskName;
}

public TaskLaunchRequest addCommmandLineArguments(Collection<String> args) {
this.commandlineArguments.addAll(args);
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.pivotal.java.function.tasklaunchrequest.function;

import java.util.function.Function;

import org.springframework.messaging.Message;

/**
* A marker interface useful for unambiguous dependency injection of this Function.
*
* @author David Turanski
**/
@FunctionalInterface
public interface TaskLaunchRequestFunction extends Function<Message<?>, Message<TaskLaunchRequest>> {

}
Loading