mirror of https://github.com/dapr/java-sdk.git
Adding examples to Spring Boot (duration, zoneddatetime and suspend/resume) (#1413)
* implementing createtime with zoneddatetime Signed-off-by: salaboy <Salaboy@gmail.com> * adding duration and zoneddatetime examples Signed-off-by: salaboy <Salaboy@gmail.com> * using external event wf to test suspend resume Signed-off-by: salaboy <Salaboy@gmail.com> --------- Signed-off-by: salaboy <Salaboy@gmail.com> Signed-off-by: sirivarma <siri.varma@outlook.com>
This commit is contained in:
parent
982b2874fe
commit
85f82f2e54
|
|
@ -14,23 +14,19 @@ limitations under the License.
|
|||
package io.dapr.workflows;
|
||||
|
||||
import io.dapr.durabletask.CompositeTaskFailedException;
|
||||
import io.dapr.durabletask.FailureDetails;
|
||||
import io.dapr.durabletask.RetryContext;
|
||||
import io.dapr.durabletask.RetryHandler;
|
||||
import io.dapr.durabletask.Task;
|
||||
import io.dapr.durabletask.TaskCanceledException;
|
||||
import io.dapr.durabletask.TaskOptions;
|
||||
import io.dapr.durabletask.TaskOrchestrationContext;
|
||||
|
||||
import io.dapr.workflows.runtime.DefaultWorkflowContext;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.ZonedDateTime;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ import io.dapr.springboot.examples.wfp.fanoutin.FanOutInWorkflow;
|
|||
import io.dapr.springboot.examples.wfp.fanoutin.Result;
|
||||
import io.dapr.springboot.examples.wfp.remoteendpoint.Payload;
|
||||
import io.dapr.springboot.examples.wfp.remoteendpoint.RemoteEndpointWorkflow;
|
||||
import io.dapr.springboot.examples.wfp.suspendresume.SuspendResumeWorkflow;
|
||||
import io.dapr.springboot.examples.wfp.timer.DurationTimerWorkflow;
|
||||
import io.dapr.springboot.examples.wfp.timer.ZonedDateTimeTimerWorkflow;
|
||||
import io.dapr.workflows.client.DaprWorkflowClient;
|
||||
import io.dapr.workflows.client.WorkflowInstanceStatus;
|
||||
import org.slf4j.Logger;
|
||||
|
|
@ -156,7 +157,7 @@ public class WorkflowPatternsRestController {
|
|||
|
||||
@PostMapping("wfp/suspendresume")
|
||||
public String suspendResume(@RequestParam("orderId") String orderId) {
|
||||
String instanceId = daprWorkflowClient.scheduleNewWorkflow(SuspendResumeWorkflow.class);
|
||||
String instanceId = daprWorkflowClient.scheduleNewWorkflow(ExternalEventWorkflow.class);
|
||||
logger.info("Workflow instance " + instanceId + " started");
|
||||
ordersToApprove.put(orderId, instanceId);
|
||||
return instanceId;
|
||||
|
|
@ -189,4 +190,16 @@ public class WorkflowPatternsRestController {
|
|||
.waitForInstanceCompletion(instanceId, null, true);
|
||||
return workflowInstanceStatus.readOutputAs(Decision.class);
|
||||
}
|
||||
|
||||
@PostMapping("wfp/durationtimer")
|
||||
public String durationTimerWorkflow() {
|
||||
return daprWorkflowClient.scheduleNewWorkflow(DurationTimerWorkflow.class);
|
||||
}
|
||||
|
||||
@PostMapping("wfp/zoneddatetimetimer")
|
||||
public String zonedDateTimeTimerWorkflow() {
|
||||
return daprWorkflowClient.scheduleNewWorkflow(ZonedDateTimeTimerWorkflow.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2025 The Dapr 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
|
||||
* 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 io.dapr.springboot.examples.wfp.timer;
|
||||
|
||||
import io.dapr.workflows.Workflow;
|
||||
import io.dapr.workflows.WorkflowStub;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
public class DurationTimerWorkflow implements Workflow {
|
||||
@Override
|
||||
public WorkflowStub create() {
|
||||
return ctx -> {
|
||||
ctx.getLogger().info("Starting Workflow: {}, instanceId: {}", ctx.getName(), ctx.getInstanceId());
|
||||
|
||||
ctx.getLogger().info("Let's call the first LogActivity at {}", new Date());
|
||||
ctx.callActivity(LogActivity.class.getName()).await();
|
||||
|
||||
ctx.getLogger().info("Let's schedule a 10 seconds timer at {}", new Date());
|
||||
ctx.createTimer(Duration.ofSeconds(10)).await();
|
||||
|
||||
ctx.getLogger().info("Let's call the second LogActivity at {}", new Date());
|
||||
ctx.callActivity(LogActivity.class.getName()).await();
|
||||
|
||||
ctx.complete(true);
|
||||
ctx.getLogger().info("Workflow completed at {}", new Date());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright 2025 The Dapr 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
|
||||
* 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 io.dapr.springboot.examples.wfp.timer;
|
||||
|
||||
import io.dapr.workflows.WorkflowActivity;
|
||||
import io.dapr.workflows.WorkflowActivityContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
public class LogActivity implements WorkflowActivity {
|
||||
|
||||
@Autowired
|
||||
private TimerLogService logService;
|
||||
|
||||
@Override
|
||||
public Object run(WorkflowActivityContext ctx) {
|
||||
Logger logger = LoggerFactory.getLogger(LogActivity.class);
|
||||
Date now = new Date();
|
||||
logger.info("Running Activity: {} at {}", ctx.getName(), now);
|
||||
logService.logDate(now);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2025 The Dapr 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
|
||||
* 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 io.dapr.springboot.examples.wfp.timer;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class TimerLogService {
|
||||
private final List<Date> logDates = new ArrayList<>();
|
||||
|
||||
public void logDate(Date date){
|
||||
logDates.add(date);
|
||||
}
|
||||
|
||||
public void clearLog(){
|
||||
logDates.clear();
|
||||
}
|
||||
|
||||
public List<Date> getLogDates(){
|
||||
return logDates;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2025 The Dapr 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
|
||||
* 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 io.dapr.springboot.examples.wfp.timer;
|
||||
|
||||
import io.dapr.workflows.Workflow;
|
||||
import io.dapr.workflows.WorkflowStub;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Date;
|
||||
|
||||
@Component
|
||||
public class ZonedDateTimeTimerWorkflow implements Workflow {
|
||||
@Override
|
||||
public WorkflowStub create() {
|
||||
return ctx -> {
|
||||
ctx.getLogger().info("Starting Workflow: {}, instanceId: {}", ctx.getName(), ctx.getInstanceId());
|
||||
|
||||
ctx.getLogger().info("Let's call the first LogActivity at {}", new Date());
|
||||
ctx.callActivity(LogActivity.class.getName()).await();
|
||||
|
||||
ZonedDateTime now = ZonedDateTime.now();
|
||||
//Let's create a ZonedDateTime 10 seconds in the future
|
||||
ZonedDateTime inTheFuture = now.plusSeconds(10);
|
||||
ctx.getLogger().info("Creating a timer that due {} at: {}", inTheFuture, new Date());
|
||||
ctx.createTimer(inTheFuture).await();
|
||||
ctx.getLogger().info("The timer fired at: {}", new Date());
|
||||
|
||||
ctx.getLogger().info("Let's call the second LogActivity at {}", new Date());
|
||||
ctx.callActivity(LogActivity.class.getName()).await();
|
||||
|
||||
ctx.complete(true);
|
||||
ctx.getLogger().info("Workflow completed at {}", new Date());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ package io.dapr.springboot.examples.wfp;
|
|||
import io.dapr.springboot.DaprAutoConfiguration;
|
||||
import io.dapr.springboot.examples.wfp.continueasnew.CleanUpLog;
|
||||
import io.dapr.springboot.examples.wfp.remoteendpoint.Payload;
|
||||
import io.dapr.springboot.examples.wfp.timer.TimerLogService;
|
||||
import io.dapr.workflows.client.WorkflowRuntimeStatus;
|
||||
import io.github.microcks.testcontainers.MicrocksContainersEnsemble;
|
||||
import io.restassured.RestAssured;
|
||||
|
|
@ -25,10 +26,13 @@ import org.junit.jupiter.api.Test;
|
|||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
|
@ -42,10 +46,14 @@ class WorkflowPatternsAppTests {
|
|||
@Autowired
|
||||
private MicrocksContainersEnsemble ensemble;
|
||||
|
||||
@Autowired
|
||||
private TimerLogService logService;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
RestAssured.baseURI = "http://localhost:" + 8080;
|
||||
org.testcontainers.Testcontainers.exposeHostPorts(8080);
|
||||
logService.clearLog();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -201,4 +209,64 @@ class WorkflowPatternsAppTests {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDurationTimer() throws InterruptedException {
|
||||
|
||||
String instanceId = given()
|
||||
.when()
|
||||
.post("/wfp/durationtimer")
|
||||
.then()
|
||||
.statusCode(200).extract().asString();
|
||||
|
||||
assertNotNull(instanceId);
|
||||
|
||||
// Check that the workflow completed successfully
|
||||
await().atMost(Duration.ofSeconds(30))
|
||||
.pollDelay(500, TimeUnit.MILLISECONDS)
|
||||
.pollInterval(500, TimeUnit.MILLISECONDS)
|
||||
.until(() -> {
|
||||
System.out.println("Log Size: " + logService.getLogDates().size());
|
||||
if( logService.getLogDates().size() == 2 ) {
|
||||
long diffInMillis = Math.abs(logService.getLogDates().get(1).getTime() - logService.getLogDates().get(0).getTime());
|
||||
long diff = TimeUnit.SECONDS.convert(diffInMillis, TimeUnit.MILLISECONDS);
|
||||
System.out.println("First Log at: " + logService.getLogDates().get(0));
|
||||
System.out.println("Second Log at: " + logService.getLogDates().get(1));
|
||||
System.out.println("Diff in seconds: " + diff);
|
||||
// The updated time differences should be between 9 and 11 seconds
|
||||
return diff >= 9 && diff <= 11;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testZonedDateTimeTimer() throws InterruptedException {
|
||||
|
||||
String instanceId = given()
|
||||
.when()
|
||||
.post("/wfp/zoneddatetimetimer")
|
||||
.then()
|
||||
.statusCode(200).extract().asString();
|
||||
|
||||
assertNotNull(instanceId);
|
||||
|
||||
// Check that the workflow completed successfully
|
||||
await().atMost(Duration.ofSeconds(30))
|
||||
.pollDelay(500, TimeUnit.MILLISECONDS)
|
||||
.pollInterval(500, TimeUnit.MILLISECONDS)
|
||||
.until(() -> {
|
||||
System.out.println("Log Size: " + logService.getLogDates().size());
|
||||
if( logService.getLogDates().size() == 2 ) {
|
||||
long diffInMillis = Math.abs(logService.getLogDates().get(1).getTime() - logService.getLogDates().get(0).getTime());
|
||||
long diff = TimeUnit.SECONDS.convert(diffInMillis, TimeUnit.MILLISECONDS);
|
||||
System.out.println("First Log at: " + logService.getLogDates().get(0));
|
||||
System.out.println("Second Log at: " + logService.getLogDates().get(1));
|
||||
System.out.println("Diff in seconds: " + diff);
|
||||
// The updated time differences should be between 9 and 11 seconds
|
||||
return diff >= 9 && diff <= 11;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue