diff --git a/workflows/cloud-client/resources/myFirstWorkflow.workflows.yaml b/workflows/cloud-client/resources/myFirstWorkflow.workflows.yaml new file mode 100644 index 00000000000..524e9befdce --- /dev/null +++ b/workflows/cloud-client/resources/myFirstWorkflow.workflows.yaml @@ -0,0 +1,47 @@ +# Copyright 2026 Google LLC +# +# 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 +# +# http://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. + +# [START workflows_myfirstworkflow_yaml_java] +# This workflow accepts an optional "searchTerm" argument for the Wikipedia API. +# If no input arguments are provided or "searchTerm" is absent, +# it will fetch the day of the week in Amsterdam and use it as the search term. + +main: + params: [input] + steps: + - validateSearchTermAndRedirectToReadWikipedia: + switch: + - condition: '${map.get(input, "searchTerm") != null}' + assign: + - searchTerm: '${input.searchTerm}' + next: readWikipedia + - getCurrentTime: + call: http.get + args: + url: https://timeapi.io/api/Time/current/zone?timeZone=Europe/Amsterdam + result: currentTime + - setFromCallResult: + assign: + - searchTerm: '${currentTime.body.dayOfWeek}' + - readWikipedia: + call: http.get + args: + url: 'https://en.wikipedia.org/w/api.php' + query: + action: opensearch + search: '${searchTerm}' + result: wikiResult + - returnOutput: + return: '${wikiResult.body[1]}' +# [END workflows_myfirstworkflow_yaml_java] \ No newline at end of file diff --git a/workflows/cloud-client/src/main/java/com/example/workflows/ExecuteWithArguments.java b/workflows/cloud-client/src/main/java/com/example/workflows/ExecuteWithArguments.java new file mode 100644 index 00000000000..4f7487bc614 --- /dev/null +++ b/workflows/cloud-client/src/main/java/com/example/workflows/ExecuteWithArguments.java @@ -0,0 +1,78 @@ +/* + * Copyright 2026 Google LLC + * + * 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 + * + * http://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 com.example.workflows; + +import com.google.cloud.workflows.executions.v1.CreateExecutionRequest; +import com.google.cloud.workflows.executions.v1.Execution; +import com.google.cloud.workflows.executions.v1.ExecutionsClient; +import com.google.cloud.workflows.executions.v1.WorkflowName; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +// [START workflows_execute_with_arguments] + +public class ExecuteWithArguments { + public static void main(String[] args) + throws IOException, InterruptedException, ExecutionException { + String projectId = "your-project-id"; + String location = "your-location"; // For example: us-central1 + String workflowId = "your-workflow-id"; + + executeWorkflowWithArguments(projectId, location, workflowId); + } + + public static void executeWorkflowWithArguments( + String projectId, String location, String workflowId) + throws IOException, InterruptedException, ExecutionException { + try (ExecutionsClient executionsClient = ExecutionsClient.create()) { + WorkflowName parent = WorkflowName.of(projectId, location, workflowId); + + CreateExecutionRequest executionRequest = + CreateExecutionRequest.newBuilder() + .setParent(parent.toString()) + .setExecution( + Execution.newBuilder().setArgument("{\"searchTerm\":\"Cloud\"}").build()) + .build(); + + Execution executionCreated = executionsClient.createExecution(executionRequest); + + System.out.println("Created execution: " + executionCreated.getName()); + + // Wait for execution to finish using exponential backoff + long backoffDelay = 1_000; + Execution execution; + System.out.println("Poll for result..."); + while (true) { + execution = executionsClient.getExecution(executionCreated.getName()); + + // Check if execution finished + if (execution.getState() != Execution.State.ACTIVE) { + break; + } + + // Wait using exponential backoff + System.out.println("- Waiting for results..."); + Thread.sleep(backoffDelay); + backoffDelay *= 2; + } + + System.out.println("Execution finished with state: " + execution.getState().name()); + System.out.println("Execution results: " + execution.getResult()); + } + } +} +// [END workflows_execute_with_arguments] diff --git a/workflows/cloud-client/src/main/java/com/example/workflows/ExecuteWithoutArguments.java b/workflows/cloud-client/src/main/java/com/example/workflows/ExecuteWithoutArguments.java new file mode 100644 index 00000000000..718973de0ed --- /dev/null +++ b/workflows/cloud-client/src/main/java/com/example/workflows/ExecuteWithoutArguments.java @@ -0,0 +1,77 @@ +/* + * Copyright 2026 Google LLC + * + * 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 + * + * http://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 com.example.workflows; + +// [START workflows_execute_without_arguments] + +import com.google.cloud.workflows.executions.v1.CreateExecutionRequest; +import com.google.cloud.workflows.executions.v1.Execution; +import com.google.cloud.workflows.executions.v1.ExecutionsClient; +import com.google.cloud.workflows.executions.v1.WorkflowName; +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +public class ExecuteWithoutArguments { + public static void main(String[] args) + throws IOException, InterruptedException, ExecutionException { + String projectId = "your-project-id"; + String location = "your-location"; // For example: us-central1 + String workflowId = "your-workflow-id"; + + executeWorkflowWithoutArguments(projectId, location, workflowId); + } + + public static void executeWorkflowWithoutArguments( + String projectId, String location, String workflowId) + throws IOException, InterruptedException, ExecutionException { + try (ExecutionsClient executionsClient = ExecutionsClient.create()) { + WorkflowName parent = WorkflowName.of(projectId, location, workflowId); + + CreateExecutionRequest executionRequest = + CreateExecutionRequest.newBuilder() + .setParent(parent.toString()) + .setExecution(Execution.newBuilder().build()) + .build(); + + Execution executionCreated = executionsClient.createExecution(executionRequest); + + System.out.println("Created execution: " + executionCreated.getName()); + + // Wait for execution to finish using exponential backoff + long backoffDelay = 1_000; + Execution execution; + System.out.println("Poll for result..."); + while (true) { + execution = executionsClient.getExecution(executionCreated.getName()); + + // Check if execution finished + if (execution.getState() != Execution.State.ACTIVE) { + break; + } + + // Wait using exponential backoff + System.out.println("- Waiting for results..."); + Thread.sleep(backoffDelay); + backoffDelay *= 2; + } + + System.out.println("Execution finished with state: " + execution.getState().name()); + System.out.println("Execution results: " + execution.getResult()); + } + } +} +// [END workflows_execute_without_arguments] diff --git a/workflows/cloud-client/src/test/java/com/example/workflows/ExecuteWithArgumentsIT.java b/workflows/cloud-client/src/test/java/com/example/workflows/ExecuteWithArgumentsIT.java new file mode 100644 index 00000000000..4dc5fe334f3 --- /dev/null +++ b/workflows/cloud-client/src/test/java/com/example/workflows/ExecuteWithArgumentsIT.java @@ -0,0 +1,72 @@ +/* + * Copyright 2026 Google LLC + * + * 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 + * + * http://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 com.example.workflows; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertNotNull; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class ExecuteWithArgumentsIT { + private static String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static String LOCATION = "us-central1"; + private static String WORKFLOW_ID = "java_myFirstWorkflow_" + UUID.randomUUID(); + private static ByteArrayOutputStream bout; + + private static void requireEnvVar(String varName) { + assertNotNull( + "Environment variable " + varName + " is required to perform these tests.", + System.getenv(varName)); + } + + @BeforeClass + public static void setUp() throws IOException, InterruptedException, ExecutionException { + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + + // Create workflow + Utils.createWorkflow(PROJECT_ID, LOCATION, WORKFLOW_ID); + + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + } + + @AfterClass + public static void tearDown() throws IOException, InterruptedException, ExecutionException { + // Delete workflow + Utils.deleteWorkflow(PROJECT_ID, LOCATION, WORKFLOW_ID); + + System.setOut(null); + } + + @Test + public void testExecuteWorkflowWithArguments() + throws IOException, InterruptedException, ExecutionException { + ExecuteWithArguments.executeWorkflowWithArguments(PROJECT_ID, LOCATION, WORKFLOW_ID); + + String output = bout.toString(); + assertThat(output).contains("Execution finished with state: SUCCEEDED"); + assertThat(output).contains("Execution results: "); + assertThat(output).contains("Cloud"); + } +} diff --git a/workflows/cloud-client/src/test/java/com/example/workflows/ExecuteWithoutArgumentsIT.java b/workflows/cloud-client/src/test/java/com/example/workflows/ExecuteWithoutArgumentsIT.java new file mode 100644 index 00000000000..91a29e42966 --- /dev/null +++ b/workflows/cloud-client/src/test/java/com/example/workflows/ExecuteWithoutArgumentsIT.java @@ -0,0 +1,71 @@ +/* + * Copyright 2026 Google LLC + * + * 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 + * + * http://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 com.example.workflows; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertNotNull; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class ExecuteWithoutArgumentsIT { + private static String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + private static String LOCATION = "us-central1"; + private static String WORKFLOW_ID = "java_myFirstWorkflow_" + UUID.randomUUID(); + private static ByteArrayOutputStream bout; + + private static void requireEnvVar(String varName) { + assertNotNull( + "Environment variable " + varName + " is required to perform these tests.", + System.getenv(varName)); + } + + @BeforeClass + public static void setUp() throws IOException, InterruptedException, ExecutionException { + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + + // Create workflow + Utils.createWorkflow(PROJECT_ID, LOCATION, WORKFLOW_ID); + + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + } + + @AfterClass + public static void tearDown() throws IOException, InterruptedException, ExecutionException { + // Delete workflow + Utils.deleteWorkflow(PROJECT_ID, LOCATION, WORKFLOW_ID); + + System.setOut(null); + } + + @Test + public void testExecuteWorkflowWithoutArguments() + throws IOException, InterruptedException, ExecutionException { + ExecuteWithoutArguments.executeWorkflowWithoutArguments(PROJECT_ID, LOCATION, WORKFLOW_ID); + + String output = bout.toString(); + assertThat(output).contains("Execution finished with state: SUCCEEDED"); + assertThat(output).contains("Execution results: "); + } +} diff --git a/workflows/cloud-client/src/test/java/com/example/workflows/Utils.java b/workflows/cloud-client/src/test/java/com/example/workflows/Utils.java new file mode 100644 index 00000000000..6c70f407635 --- /dev/null +++ b/workflows/cloud-client/src/test/java/com/example/workflows/Utils.java @@ -0,0 +1,49 @@ +/* + * Copyright 2026 Google LLC + * + * 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 + * + * http://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 com.example.workflows; + +import com.google.cloud.workflows.v1.LocationName; +import com.google.cloud.workflows.v1.Workflow; +import com.google.cloud.workflows.v1.WorkflowName; +import com.google.cloud.workflows.v1.WorkflowsClient; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.concurrent.ExecutionException; + +public class Utils { + public static void createWorkflow(String projectId, String location, String workflowId) + throws IOException, InterruptedException, ExecutionException { + + try (WorkflowsClient workflowsClient = WorkflowsClient.create()) { + LocationName parent = LocationName.of(projectId, location); + + String source = + new String(Files.readAllBytes(Paths.get("resources/myFirstWorkflow.workflows.yaml"))); + Workflow workflow = Workflow.newBuilder().setSourceContents(source).build(); + + workflowsClient.createWorkflowAsync(parent, workflow, workflowId).get(); + } + } + + public static void deleteWorkflow(String projectId, String location, String workflowId) + throws IOException, InterruptedException, ExecutionException { + try (WorkflowsClient workflowsClient = WorkflowsClient.create()) { + workflowsClient.deleteWorkflowAsync(WorkflowName.of(projectId, location, workflowId)).get(); + } + } +}