Event driven microservices tutorial (#15646)
* even driven microservices tutorial * restructure the project * remove mvn files * formatting
This commit is contained in:
parent
25c40ac1ca
commit
dcb4eecaf5
27
microservices-modules/event-driven-microservice/.gitignore
vendored
Normal file
27
microservices-modules/event-driven-microservice/.gitignore
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
|
replay_pid*
|
||||||
|
|
||||||
|
.idea/
|
||||||
|
target/
|
13
microservices-modules/event-driven-microservice/README.md
Normal file
13
microservices-modules/event-driven-microservice/README.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Event Driven Microservices using Conductor
|
||||||
|
|
||||||
|
This is an example project showing how to build event driven applications using [Conductor](https://github.com/conductor-oss/conductor)
|
||||||
|
|
||||||
|
# Pre-requisites
|
||||||
|
1. Docker
|
||||||
|
2. Running conductor server
|
||||||
|
|
||||||
|
**Start the conductor server**
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker run --init -p 8080:8080 -p 1234:5000 conductoross/conductor-standalone:3.15.0
|
||||||
|
```
|
76
microservices-modules/event-driven-microservice/pom.xml
Normal file
76
microservices-modules/event-driven-microservice/pom.xml
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>3.2.0</version>
|
||||||
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>io.orkes.demo</groupId>
|
||||||
|
<artifactId>event-driven-microservice</artifactId>
|
||||||
|
<version>0.1</version>
|
||||||
|
|
||||||
|
<name>event-driven-microservice</name>
|
||||||
|
<description>Demo Project for Orkes Conductor on Spring Boot</description>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.orkes.conductor</groupId>
|
||||||
|
<artifactId>orkes-conductor-client</artifactId>
|
||||||
|
<version>${conductor.client.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springdoc</groupId>
|
||||||
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
|
<version>${spring.webmvc.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>17</java.version>
|
||||||
|
<conductor.client.version>2.0.8</conductor.client.version>
|
||||||
|
<spring.webmvc.version>2.1.0</spring.webmvc.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,28 @@
|
|||||||
|
package io.orkes.demo.banking;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.netflix.conductor.common.config.ObjectMapperProvider;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@SpringBootApplication
|
||||||
|
@ComponentScan(basePackages = { "io.orkes" })
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectMapper instance used for JSON serialization - can be modified to configure additional modules
|
||||||
|
@Bean
|
||||||
|
public ObjectMapper getObjectMapper() {
|
||||||
|
return new ObjectMapperProvider().getObjectMapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package io.orkes.demo.banking.controller;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import io.orkes.demo.banking.pojos.DepositDetail;
|
||||||
|
import io.orkes.demo.banking.service.FraudCheckService;
|
||||||
|
import io.orkes.demo.banking.service.WorkflowService;
|
||||||
|
import io.orkes.demo.banking.workers.FraudCheckResult;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@AllArgsConstructor
|
||||||
|
@RestController
|
||||||
|
public class APIController {
|
||||||
|
|
||||||
|
private final FraudCheckService fraudCheckService;
|
||||||
|
|
||||||
|
private final WorkflowService workflowService;
|
||||||
|
|
||||||
|
@PostMapping(value = "/triggerDeposit", produces = "application/json")
|
||||||
|
public ResponseEntity<FraudCheckResult> triggerDeposit(@RequestBody DepositDetail depositDetail) {
|
||||||
|
log.info("Checking for fraud: {}", depositDetail);
|
||||||
|
return ResponseEntity.ok(fraudCheckService.checkForFraud(depositDetail));
|
||||||
|
}
|
||||||
|
|
||||||
|
// docs-marker-start-1
|
||||||
|
@PostMapping(value = "/checkForFraud", produces = "application/json")
|
||||||
|
public Map<String, Object> checkForFraud(@RequestBody DepositDetail depositDetail) throws Exception {
|
||||||
|
log.info("Checking if fraud check is required for: {}", depositDetail);
|
||||||
|
return workflowService.executeWorkflow(depositDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
// docs-marker-end-1
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package io.orkes.demo.banking.pojos;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class DepositDetail {
|
||||||
|
|
||||||
|
private String accountId;
|
||||||
|
private BigDecimal amount;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package io.orkes.demo.banking.service;
|
||||||
|
|
||||||
|
import static io.orkes.demo.banking.workers.FraudCheckResult.Result.FAIL;
|
||||||
|
import static io.orkes.demo.banking.workers.FraudCheckResult.Result.PASS;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import io.orkes.demo.banking.pojos.DepositDetail;
|
||||||
|
import io.orkes.demo.banking.workers.FraudCheckResult;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class FraudCheckService {
|
||||||
|
|
||||||
|
public FraudCheckResult checkForFraud(DepositDetail depositDetail) {
|
||||||
|
FraudCheckResult fcr = new FraudCheckResult();
|
||||||
|
if (depositDetail.getAmount()
|
||||||
|
.compareTo(BigDecimal.valueOf(100000)) > 0) {
|
||||||
|
fcr.setResult(FAIL);
|
||||||
|
fcr.setReason("Amount too large");
|
||||||
|
} else {
|
||||||
|
fcr.setResult(PASS);
|
||||||
|
fcr.setReason("All good!");
|
||||||
|
}
|
||||||
|
return fcr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
package io.orkes.demo.banking.service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest;
|
||||||
|
|
||||||
|
import io.orkes.conductor.client.WorkflowClient;
|
||||||
|
import io.orkes.conductor.common.model.WorkflowRun;
|
||||||
|
import io.orkes.demo.banking.pojos.DepositDetail;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Service
|
||||||
|
public class WorkflowService {
|
||||||
|
|
||||||
|
private final WorkflowClient workflowClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the workflow execution asynchronously
|
||||||
|
* @param depositDetail
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map<String, Object> startDepositWorkflow(DepositDetail depositDetail) {
|
||||||
|
StartWorkflowRequest request = new StartWorkflowRequest();
|
||||||
|
request.setName("microservice_orchestration");
|
||||||
|
Map<String, Object> inputData = new HashMap<>();
|
||||||
|
inputData.put("amount", depositDetail.getAmount());
|
||||||
|
inputData.put("accountId", depositDetail.getAccountId());
|
||||||
|
request.setInput(inputData);
|
||||||
|
|
||||||
|
String workflowId = workflowClient.startWorkflow(request);
|
||||||
|
log.info("Workflow id: {}", workflowId);
|
||||||
|
return Map.of("workflowId", workflowId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the workflow, waits for it to complete and returns the output of the workflow
|
||||||
|
* @param depositDetail
|
||||||
|
* @return
|
||||||
|
* @throws ExecutionException
|
||||||
|
* @throws InterruptedException
|
||||||
|
* @throws TimeoutException
|
||||||
|
*/
|
||||||
|
public Map<String, Object> executeWorkflow(DepositDetail depositDetail) throws ExecutionException, InterruptedException, TimeoutException {
|
||||||
|
StartWorkflowRequest request = new StartWorkflowRequest();
|
||||||
|
request.setName("microservice_orchestration");
|
||||||
|
request.setVersion(1);
|
||||||
|
Map<String, Object> inputData = new HashMap<>();
|
||||||
|
inputData.put("amount", depositDetail.getAmount());
|
||||||
|
inputData.put("accountId", depositDetail.getAccountId());
|
||||||
|
request.setInput(inputData);
|
||||||
|
|
||||||
|
CompletableFuture<WorkflowRun> workflowRun = workflowClient.executeWorkflow(request, UUID.randomUUID()
|
||||||
|
.toString(), 10);
|
||||||
|
log.info("Workflow id: {}", workflowRun);
|
||||||
|
|
||||||
|
return workflowRun.get(10, TimeUnit.SECONDS)
|
||||||
|
.getOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package io.orkes.demo.banking.workers;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.netflix.conductor.sdk.workflow.task.InputParam;
|
||||||
|
import com.netflix.conductor.sdk.workflow.task.WorkerTask;
|
||||||
|
|
||||||
|
import io.orkes.demo.banking.pojos.DepositDetail;
|
||||||
|
import io.orkes.demo.banking.service.FraudCheckService;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class ConductorWorkers {
|
||||||
|
|
||||||
|
private final FraudCheckService fraudCheckService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param amount
|
||||||
|
* @return Given the amount, the service check if the fraud check should done before executing the transaction
|
||||||
|
*/
|
||||||
|
@WorkerTask(value = "fraud-check-required")
|
||||||
|
public FraudCheckResult simpleWorker(@InputParam("amount") BigDecimal amount) {
|
||||||
|
DepositDetail dd = new DepositDetail();
|
||||||
|
dd.setAmount(amount);
|
||||||
|
return fraudCheckService.checkForFraud(dd);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package io.orkes.demo.banking.workers;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class FraudCheckResult {
|
||||||
|
|
||||||
|
public enum Result {
|
||||||
|
PASS,
|
||||||
|
FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result result;
|
||||||
|
private String reason;
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
# swagger-ui custom path
|
||||||
|
springdoc.swagger-ui.path=/swagger-ui.html
|
||||||
|
management.endpoints.enabled-by-default=false
|
||||||
|
management.endpoint.info.enabled=false
|
||||||
|
server.port=8081
|
||||||
|
# If you want to use Orkes Playground, then change the server url to https://play.orkes.io/api/
|
||||||
|
# Obtain key and secret by logging into
|
||||||
|
# and navigating to applications menu, create an application and generate key/secret
|
||||||
|
conductor.security.client.key-id=CHANGE_ME
|
||||||
|
conductor.security.client.secret=CHANGE_ME
|
||||||
|
conductor.server.url=https://play.orkes.io/api/
|
@ -0,0 +1,14 @@
|
|||||||
|
package io.orkes.demo.banking;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
class ApplicationTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void contextLoads() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
65
microservices-modules/event-driven-microservice/style.xml
Normal file
65
microservices-modules/event-driven-microservice/style.xml
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<code_scheme name="baeldung-formatter" version="173">
|
||||||
|
<option name="RIGHT_MARGIN" value="260"/>
|
||||||
|
<option name="FORMATTER_TAGS_ENABLED" value="true"/>
|
||||||
|
<JavaCodeStyleSettings>
|
||||||
|
<option name="SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENT" value="true"/>
|
||||||
|
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="100"/>
|
||||||
|
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="100"/>
|
||||||
|
<option name="IMPORT_LAYOUT_TABLE">
|
||||||
|
<value>
|
||||||
|
<package name="" withSubpackages="true" static="true"/>
|
||||||
|
<emptyLine/>
|
||||||
|
<package name="java" withSubpackages="true" static="false"/>
|
||||||
|
<emptyLine/>
|
||||||
|
<package name="javax" withSubpackages="true" static="false"/>
|
||||||
|
<emptyLine/>
|
||||||
|
<package name="org" withSubpackages="true" static="false"/>
|
||||||
|
<emptyLine/>
|
||||||
|
<package name="com" withSubpackages="true" static="false"/>
|
||||||
|
<emptyLine/>
|
||||||
|
<package name="" withSubpackages="true" static="false"/>
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="ENABLE_JAVADOC_FORMATTING" value="false"/>
|
||||||
|
</JavaCodeStyleSettings>
|
||||||
|
<codeStyleSettings language="JAVA">
|
||||||
|
<option name="RIGHT_MARGIN" value="160"/>
|
||||||
|
<option name="KEEP_LINE_BREAKS" value="false"/>
|
||||||
|
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false"/>
|
||||||
|
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false"/>
|
||||||
|
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1"/>
|
||||||
|
<option name="KEEP_BLANK_LINES_IN_CODE" value="1"/>
|
||||||
|
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1"/>
|
||||||
|
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1"/>
|
||||||
|
<option name="ALIGN_MULTILINE_PARAMETERS" value="false"/>
|
||||||
|
<option name="ALIGN_MULTILINE_THROWS_LIST" value="true"/>
|
||||||
|
<option name="SPACE_WITHIN_ARRAY_INITIALIZER_BRACES" value="true"/>
|
||||||
|
<option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true"/>
|
||||||
|
<option name="CALL_PARAMETERS_WRAP" value="1"/>
|
||||||
|
<option name="METHOD_PARAMETERS_WRAP" value="1"/>
|
||||||
|
<option name="RESOURCE_LIST_WRAP" value="5"/>
|
||||||
|
<option name="EXTENDS_LIST_WRAP" value="1"/>
|
||||||
|
<option name="THROWS_LIST_WRAP" value="1"/>
|
||||||
|
<option name="EXTENDS_KEYWORD_WRAP" value="1"/>
|
||||||
|
<option name="THROWS_KEYWORD_WRAP" value="1"/>
|
||||||
|
<option name="METHOD_CALL_CHAIN_WRAP" value="2"/>
|
||||||
|
<option name="BINARY_OPERATION_WRAP" value="1"/>
|
||||||
|
<option name="TERNARY_OPERATION_WRAP" value="1"/>
|
||||||
|
<option name="KEEP_SIMPLE_LAMBDAS_IN_ONE_LINE" value="true"/>
|
||||||
|
<option name="ARRAY_INITIALIZER_WRAP" value="1"/>
|
||||||
|
<option name="IF_BRACE_FORCE" value="3"/>
|
||||||
|
<option name="DOWHILE_BRACE_FORCE" value="3"/>
|
||||||
|
<option name="WHILE_BRACE_FORCE" value="3"/>
|
||||||
|
<option name="FOR_BRACE_FORCE" value="3"/>
|
||||||
|
<option name="ENUM_CONSTANTS_WRAP" value="2"/>
|
||||||
|
<option name="KEEP_BUILDER_METHODS_INDENTS" value="true"/>
|
||||||
|
<indentOptions>
|
||||||
|
<option name="CONTINUATION_INDENT_SIZE" value="4"/>
|
||||||
|
<option name="SMART_TABS" value="true"/>
|
||||||
|
</indentOptions>
|
||||||
|
<arrangement>
|
||||||
|
<groups/>
|
||||||
|
<rules/>
|
||||||
|
</arrangement>
|
||||||
|
</codeStyleSettings>
|
||||||
|
</code_scheme>
|
@ -22,6 +22,7 @@
|
|||||||
<module>msf4j</module>
|
<module>msf4j</module>
|
||||||
<module>open-liberty</module>
|
<module>open-liberty</module>
|
||||||
<module>rest-express</module>
|
<module>rest-express</module>
|
||||||
|
<module>event-driven-microservice</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
Loading…
x
Reference in New Issue
Block a user