first commit
This commit is contained in:
4
app/Dockerfile
Executable file
4
app/Dockerfile
Executable file
@@ -0,0 +1,4 @@
|
||||
FROM openjdk:8u212-jdk-alpine
|
||||
COPY target/*SNAPSHOT.jar app.jar
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["java","-Xmx400M","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar","--spring.profiles.active=docker"]
|
||||
103
app/cloudbuild.yaml
Executable file
103
app/cloudbuild.yaml
Executable file
@@ -0,0 +1,103 @@
|
||||
steps:
|
||||
### Test
|
||||
# - id: 'test'
|
||||
# name: 'gcr.io/cloud-builders/mvn'
|
||||
# args: [
|
||||
# 'test',
|
||||
# '-Dspring.profiles.active=test'
|
||||
# ]
|
||||
### Build
|
||||
- id: 'build'
|
||||
name: 'gcr.io/cloud-builders/mvn'
|
||||
args: [
|
||||
'clean',
|
||||
'package'
|
||||
# '-Dmaven.test.skip=true'
|
||||
]
|
||||
# waitFor: ['test']
|
||||
### docker Build
|
||||
- id: 'docker build'
|
||||
name: 'gcr.io/cloud-builders/docker'
|
||||
args:
|
||||
- 'build'
|
||||
- '--tag=gcr.io/$PROJECT_ID/$_PROJECT_NAME:latest'
|
||||
- '.'
|
||||
### Publish
|
||||
- id: 'publish'
|
||||
name: 'gcr.io/cloud-builders/docker'
|
||||
entrypoint: 'bash'
|
||||
args:
|
||||
- '-c'
|
||||
- |
|
||||
docker push gcr.io/$PROJECT_ID/$_PROJECT_NAME:latest
|
||||
### deploy
|
||||
- id: 'deploy'
|
||||
name: 'gcr.io/cloud-builders/gcloud'
|
||||
entrypoint: 'bash'
|
||||
args:
|
||||
- '-c'
|
||||
- |
|
||||
PROJECT=$$(gcloud config get-value core/project)
|
||||
gcloud container clusters get-credentials "$${CLOUDSDK_CONTAINER_CLUSTER}" \
|
||||
--project "$${PROJECT}" \
|
||||
--zone "$${CLOUDSDK_COMPUTE_ZONE}"
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: $_PROJECT_NAME
|
||||
labels:
|
||||
app: $_PROJECT_NAME
|
||||
spec:
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: $_PROJECT_NAME
|
||||
EOF
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: $_PROJECT_NAME
|
||||
labels:
|
||||
app: $_PROJECT_NAME
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: $_PROJECT_NAME
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: $_PROJECT_NAME
|
||||
spec:
|
||||
containers:
|
||||
- name: $_PROJECT_NAME
|
||||
image: gcr.io/$PROJECT_ID/$_PROJECT_NAME:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
timeoutSeconds: 2
|
||||
periodSeconds: 5
|
||||
failureThreshold: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health
|
||||
port: 8080
|
||||
initialDelaySeconds: 120
|
||||
timeoutSeconds: 2
|
||||
periodSeconds: 5
|
||||
failureThreshold: 5
|
||||
EOF
|
||||
substitutions:
|
||||
_PROJECT_NAME: app
|
||||
options:
|
||||
env:
|
||||
# # location/name of GKE cluster (used by all kubectl commands)
|
||||
- CLOUDSDK_COMPUTE_ZONE=asia-northeast1-a
|
||||
- CLOUDSDK_CONTAINER_CLUSTER=cluster-1
|
||||
37
app/kubernetes/deployment.yml
Executable file
37
app/kubernetes/deployment.yml
Executable file
@@ -0,0 +1,37 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: app
|
||||
labels:
|
||||
app: app
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: app
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: app
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: username/app:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: '/actuator/health'
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
timeoutSeconds: 2
|
||||
periodSeconds: 5
|
||||
failureThreshold: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: '/actuator/health'
|
||||
port: 8080
|
||||
initialDelaySeconds: 120
|
||||
timeoutSeconds: 2
|
||||
periodSeconds: 5
|
||||
failureThreshold: 5
|
||||
12
app/kubernetes/service.yaml
Executable file
12
app/kubernetes/service.yaml
Executable file
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: app
|
||||
labels:
|
||||
app: app
|
||||
spec:
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: app
|
||||
90
app/pom.xml
Executable file
90
app/pom.xml
Executable file
@@ -0,0 +1,90 @@
|
||||
<?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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.1.9.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>fooddelivery</groupId>
|
||||
<artifactId>app</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>app</name>
|
||||
<description>Demo project for Spring Boot</description>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
|
||||
<spring-cloud-stream.version>Germantown.SR1</spring-cloud-stream.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-rest</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- kafka streams -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-stream-kafka</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-dependencies</artifactId>
|
||||
<version>${spring-cloud-stream.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
78
app/src/main/java/fooddelivery/AbstractEvent.java
Executable file
78
app/src/main/java/fooddelivery/AbstractEvent.java
Executable file
@@ -0,0 +1,78 @@
|
||||
package fooddelivery;
|
||||
|
||||
import fooddelivery.config.kafka.KafkaProcessor;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class AbstractEvent {
|
||||
|
||||
String eventType;
|
||||
String timestamp;
|
||||
|
||||
public AbstractEvent(){
|
||||
this.setEventType(this.getClass().getSimpleName());
|
||||
SimpleDateFormat defaultSimpleDateFormat = new SimpleDateFormat("YYYYMMddHHmmss");
|
||||
this.timestamp = defaultSimpleDateFormat.format(new Date());
|
||||
}
|
||||
|
||||
public String toJson(){
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
String json = null;
|
||||
|
||||
try {
|
||||
json = objectMapper.writeValueAsString(this);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException("JSON format exception", e);
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public void publish(){
|
||||
this.publish(this.toJson());
|
||||
}
|
||||
public void publish(String json){
|
||||
if( json != null ){
|
||||
|
||||
/**
|
||||
* spring streams 방식
|
||||
*/
|
||||
KafkaProcessor processor = Application.applicationContext.getBean(KafkaProcessor.class);
|
||||
MessageChannel outputChannel = processor.outboundTopic();
|
||||
|
||||
outputChannel.send(MessageBuilder
|
||||
.withPayload(json)
|
||||
.setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON)
|
||||
.build());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
public void setEventType(String eventType) {
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
public String getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(String timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public boolean isMe(){
|
||||
return getEventType().equals(getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
18
app/src/main/java/fooddelivery/Application.java
Executable file
18
app/src/main/java/fooddelivery/Application.java
Executable file
@@ -0,0 +1,18 @@
|
||||
package fooddelivery;
|
||||
import fooddelivery.config.kafka.KafkaProcessor;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.cloud.stream.annotation.EnableBinding;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableBinding(KafkaProcessor.class)
|
||||
@EnableFeignClients
|
||||
public class Application {
|
||||
protected static ApplicationContext applicationContext;
|
||||
public static void main(String[] args) {
|
||||
applicationContext = SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
||||
57
app/src/main/java/fooddelivery/Order.java
Executable file
57
app/src/main/java/fooddelivery/Order.java
Executable file
@@ -0,0 +1,57 @@
|
||||
package fooddelivery;
|
||||
|
||||
import javax.persistence.*;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
||||
@Entity
|
||||
@Table(name="주문_table")
|
||||
public class Order {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy=GenerationType.AUTO)
|
||||
private Long id;
|
||||
private String item;
|
||||
private Integer 수량;
|
||||
|
||||
@PostPersist
|
||||
public void onPostPersist(){
|
||||
|
||||
//Following code causes dependency to external APIs
|
||||
// it is NOT A GOOD PRACTICE. instead, Event-Policy mapping is recommended.
|
||||
|
||||
fooddelivery.external.결제이력 결제이력 = new fooddelivery.external.결제이력();
|
||||
// mappings goes here
|
||||
Application.applicationContext.getBean(fooddelivery.external.결제이력Service.class)
|
||||
.결제(결제이력);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public void setItem(String item) {
|
||||
this.item = item;
|
||||
}
|
||||
public Integer get수량() {
|
||||
return 수량;
|
||||
}
|
||||
|
||||
public void set수량(Integer 수량) {
|
||||
this.수량 = 수량;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
22
app/src/main/java/fooddelivery/PolicyHandler.java
Executable file
22
app/src/main/java/fooddelivery/PolicyHandler.java
Executable file
@@ -0,0 +1,22 @@
|
||||
package fooddelivery;
|
||||
|
||||
import fooddelivery.config.kafka.KafkaProcessor;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.stream.annotation.StreamListener;
|
||||
import org.springframework.messaging.handler.annotation.Payload;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PolicyHandler{
|
||||
|
||||
@StreamListener(KafkaProcessor.INPUT)
|
||||
public void whenever배달시작됨_주문상태변경(@Payload 배달시작됨 배달시작됨){
|
||||
|
||||
if(배달시작됨.isMe()){
|
||||
System.out.println("##### listener 주문상태변경 : " + 배달시작됨.toJson());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
19
app/src/main/java/fooddelivery/config/kafka/KafkaProcessor.java
Executable file
19
app/src/main/java/fooddelivery/config/kafka/KafkaProcessor.java
Executable file
@@ -0,0 +1,19 @@
|
||||
package fooddelivery.config.kafka;
|
||||
|
||||
import org.springframework.cloud.stream.annotation.Input;
|
||||
import org.springframework.cloud.stream.annotation.Output;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.SubscribableChannel;
|
||||
|
||||
public interface KafkaProcessor {
|
||||
|
||||
String INPUT = "event-in";
|
||||
String OUTPUT = "event-out";
|
||||
|
||||
@Input(INPUT)
|
||||
SubscribableChannel inboundTopic();
|
||||
|
||||
@Output(OUTPUT)
|
||||
MessageChannel outboundTopic();
|
||||
|
||||
}
|
||||
33
app/src/main/java/fooddelivery/external/결제이력.java
vendored
Executable file
33
app/src/main/java/fooddelivery/external/결제이력.java
vendored
Executable file
@@ -0,0 +1,33 @@
|
||||
package fooddelivery.external;
|
||||
|
||||
public class 결제이력 {
|
||||
|
||||
private Long id;
|
||||
private String orderId;
|
||||
private Double 금액;
|
||||
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getOrderId() {
|
||||
return orderId;
|
||||
}
|
||||
|
||||
public void setOrderId(String orderId) {
|
||||
this.orderId = orderId;
|
||||
}
|
||||
public Double get금액() {
|
||||
return 금액;
|
||||
}
|
||||
|
||||
public void set금액(Double 금액) {
|
||||
this.금액 = 금액;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
21
app/src/main/java/fooddelivery/external/결제이력Service.java
vendored
Executable file
21
app/src/main/java/fooddelivery/external/결제이력Service.java
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
|
||||
package fooddelivery.external;
|
||||
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by uengine on 2018. 11. 21..
|
||||
*/
|
||||
|
||||
@FeignClient(name="pay", url="http://localhost:8082")//, fallback = 결제이력ServiceFallback.class)
|
||||
public interface 결제이력Service {
|
||||
|
||||
@RequestMapping(method= RequestMethod.POST, path="/결제이력s")
|
||||
public void 결제(@RequestBody 결제이력 결제이력);
|
||||
|
||||
}
|
||||
13
app/src/main/java/fooddelivery/external/결제이력ServiceFallback.java
vendored
Normal file
13
app/src/main/java/fooddelivery/external/결제이력ServiceFallback.java
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
package fooddelivery.external;
|
||||
|
||||
/**
|
||||
* Created by uengine on 2020. 4. 18..
|
||||
*/
|
||||
public class 결제이력ServiceFallback implements 결제이력Service {
|
||||
@Override
|
||||
public void 결제(결제이력 주문) {
|
||||
//do nothing if you want to forgive it
|
||||
|
||||
System.out.println("Circuit breaker has been opened. Fallback returned instead.");
|
||||
}
|
||||
}
|
||||
39
app/src/main/java/fooddelivery/배달시작됨.java
Executable file
39
app/src/main/java/fooddelivery/배달시작됨.java
Executable file
@@ -0,0 +1,39 @@
|
||||
package fooddelivery;
|
||||
|
||||
|
||||
public class 배달시작됨 extends AbstractEvent {
|
||||
|
||||
private Long id;
|
||||
private String 요리종류;
|
||||
private String 배달지주소;
|
||||
private String orderId;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String get요리종류() {
|
||||
return 요리종류;
|
||||
}
|
||||
|
||||
public void set요리종류(String 요리종류) {
|
||||
this.요리종류 = 요리종류;
|
||||
}
|
||||
public String get배달지주소() {
|
||||
return 배달지주소;
|
||||
}
|
||||
|
||||
public void set배달지주소(String 배달지주소) {
|
||||
this.배달지주소 = 배달지주소;
|
||||
}
|
||||
public String getOrderId() {
|
||||
return orderId;
|
||||
}
|
||||
|
||||
public void setOrderId(String orderId) {
|
||||
this.orderId = orderId;
|
||||
}
|
||||
}
|
||||
15
app/src/main/java/fooddelivery/주문Controller.java
Executable file
15
app/src/main/java/fooddelivery/주문Controller.java
Executable file
@@ -0,0 +1,15 @@
|
||||
package fooddelivery;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
public class 주문Controller {
|
||||
|
||||
}
|
||||
8
app/src/main/java/fooddelivery/주문Repository.java
Executable file
8
app/src/main/java/fooddelivery/주문Repository.java
Executable file
@@ -0,0 +1,8 @@
|
||||
package fooddelivery;
|
||||
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
|
||||
public interface 주문Repository extends PagingAndSortingRepository<Order, Long>{
|
||||
|
||||
|
||||
}
|
||||
34
app/src/main/java/fooddelivery/주문됨.java
Executable file
34
app/src/main/java/fooddelivery/주문됨.java
Executable file
@@ -0,0 +1,34 @@
|
||||
package fooddelivery;
|
||||
|
||||
public class 주문됨 extends AbstractEvent {
|
||||
|
||||
private Long id;
|
||||
private String 품목;
|
||||
private Integer 수량;
|
||||
|
||||
public 주문됨(){
|
||||
super();
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String get품목() {
|
||||
return 품목;
|
||||
}
|
||||
|
||||
public void set품목(String 품목) {
|
||||
this.품목 = 품목;
|
||||
}
|
||||
public Integer get수량() {
|
||||
return 수량;
|
||||
}
|
||||
|
||||
public void set수량(Integer 수량) {
|
||||
this.수량 = 수량;
|
||||
}
|
||||
}
|
||||
18
app/src/main/java/fooddelivery/주문취소됨.java
Executable file
18
app/src/main/java/fooddelivery/주문취소됨.java
Executable file
@@ -0,0 +1,18 @@
|
||||
package fooddelivery;
|
||||
|
||||
public class 주문취소됨 extends AbstractEvent {
|
||||
|
||||
private Long id;
|
||||
|
||||
public 주문취소됨(){
|
||||
super();
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
82
app/src/main/resources/application.yml
Executable file
82
app/src/main/resources/application.yml
Executable file
@@ -0,0 +1,82 @@
|
||||
server:
|
||||
port: 8080
|
||||
---
|
||||
|
||||
spring:
|
||||
profiles: default
|
||||
jpa:
|
||||
properties:
|
||||
hibernate:
|
||||
show_sql: true
|
||||
format_sql: true
|
||||
cloud:
|
||||
stream:
|
||||
kafka:
|
||||
binder:
|
||||
brokers: localhost:9092
|
||||
streams:
|
||||
binder:
|
||||
configuration:
|
||||
default:
|
||||
key:
|
||||
serde: org.apache.kafka.common.serialization.Serdes$StringSerde
|
||||
value:
|
||||
serde: org.apache.kafka.common.serialization.Serdes$StringSerde
|
||||
bindings:
|
||||
event-in:
|
||||
group: app
|
||||
destination: fooddelivery
|
||||
contentType: application/json
|
||||
event-out:
|
||||
destination: fooddelivery
|
||||
contentType: application/json
|
||||
|
||||
logging:
|
||||
level:
|
||||
org.hibernate.type: trace
|
||||
org.springframework.cloud: debug
|
||||
server:
|
||||
port: 8081
|
||||
|
||||
feign:
|
||||
hystrix:
|
||||
enabled: true
|
||||
|
||||
# To set thread isolation to SEMAPHORE
|
||||
#hystrix:
|
||||
# command:
|
||||
# default:
|
||||
# execution:
|
||||
# isolation:
|
||||
# strategy: SEMAPHORE
|
||||
|
||||
hystrix:
|
||||
command:
|
||||
# 전역설정
|
||||
default:
|
||||
execution.isolation.thread.timeoutInMilliseconds: 610
|
||||
---
|
||||
|
||||
spring:
|
||||
profiles: docker
|
||||
cloud:
|
||||
stream:
|
||||
kafka:
|
||||
binder:
|
||||
brokers: my-kafka.kafka.svc.cluster.local:9092
|
||||
streams:
|
||||
binder:
|
||||
configuration:
|
||||
default:
|
||||
key:
|
||||
serde: org.apache.kafka.common.serialization.Serdes$StringSerde
|
||||
value:
|
||||
serde: org.apache.kafka.common.serialization.Serdes$StringSerde
|
||||
bindings:
|
||||
event-in:
|
||||
group: app
|
||||
destination: fooddelivery
|
||||
contentType: application/json
|
||||
event-out:
|
||||
destination: fooddelivery
|
||||
contentType: application/json
|
||||
9
customer/Dockerfile.command.handler
Executable file
9
customer/Dockerfile.command.handler
Executable file
@@ -0,0 +1,9 @@
|
||||
FROM python:2.7-slim
|
||||
WORKDIR /app
|
||||
ADD . /app
|
||||
RUN pip install --trusted-host pypi.python.org -r requirements.txt
|
||||
ENV NAME World
|
||||
EXPOSE 8090
|
||||
CMD ["python", "command-handler.py"]
|
||||
|
||||
|
||||
9
customer/Dockerfile.policy.handler
Executable file
9
customer/Dockerfile.policy.handler
Executable file
@@ -0,0 +1,9 @@
|
||||
FROM python:2.7-slim
|
||||
WORKDIR /app
|
||||
ADD . /app
|
||||
RUN pip install --trusted-host pypi.python.org -r requirements.txt
|
||||
ENV NAME World
|
||||
EXPOSE 8090
|
||||
CMD ["python", "policy-handler.py"]
|
||||
|
||||
|
||||
21
customer/LICENSE
Executable file
21
customer/LICENSE
Executable file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 msaez-template
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
1
customer/README.md
Executable file
1
customer/README.md
Executable file
@@ -0,0 +1 @@
|
||||
# python
|
||||
18
customer/command-handler.py
Executable file
18
customer/command-handler.py
Executable file
@@ -0,0 +1,18 @@
|
||||
from flask import Flask
|
||||
from redis import Redis, RedisError
|
||||
from kafka import KafkaConsumer
|
||||
import os
|
||||
import socket
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/customer")
|
||||
def hello():
|
||||
|
||||
html = "<h3>Hello {name}!</h3>" \
|
||||
"<b>Hostname:</b> {hostname}<br/>"
|
||||
|
||||
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname())
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host='0.0.0.0', port=8084)
|
||||
23
customer/kubernetes/deployment.yml
Executable file
23
customer/kubernetes/deployment.yml
Executable file
@@ -0,0 +1,23 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: customer
|
||||
labels:
|
||||
app: customer
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: customer
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: customer
|
||||
spec:
|
||||
containers:
|
||||
- name: command-handler
|
||||
image: username/customer-command-handler:latest
|
||||
ports:
|
||||
- containerPort: 8084
|
||||
- name: policy-handler
|
||||
image: username/customer-policy-handler:latest
|
||||
12
customer/kubernetes/service.yaml
Executable file
12
customer/kubernetes/service.yaml
Executable file
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: customer
|
||||
labels:
|
||||
app: customer
|
||||
spec:
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: customer
|
||||
17
customer/policy-handler.py
Executable file
17
customer/policy-handler.py
Executable file
@@ -0,0 +1,17 @@
|
||||
from flask import Flask
|
||||
from redis import Redis, RedisError
|
||||
from kafka import KafkaConsumer
|
||||
import os
|
||||
import socket
|
||||
|
||||
|
||||
# To consume latest messages and auto-commit offsets
|
||||
consumer = KafkaConsumer('fooddelivery',
|
||||
group_id='',
|
||||
bootstrap_servers=['localhost:9092'])
|
||||
for message in consumer:
|
||||
print ("%s:%d:%d: key=%s value=%s" % (message.topic, message.partition,
|
||||
message.offset, message.key,
|
||||
message.value))
|
||||
|
||||
|
||||
4
customer/requirements.txt
Executable file
4
customer/requirements.txt
Executable file
@@ -0,0 +1,4 @@
|
||||
Flask
|
||||
Redis
|
||||
kafka-python
|
||||
|
||||
4
gateway/Dockerfile
Executable file
4
gateway/Dockerfile
Executable file
@@ -0,0 +1,4 @@
|
||||
FROM openjdk:8u212-jdk-alpine
|
||||
COPY target/*SNAPSHOT.jar app.jar
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["java","-Xmx400M","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar","--spring.profiles.active=docker"]
|
||||
85
gateway/cloudbuild.yaml
Executable file
85
gateway/cloudbuild.yaml
Executable file
@@ -0,0 +1,85 @@
|
||||
steps:
|
||||
- id: 'build'
|
||||
name: 'gcr.io/cloud-builders/mvn'
|
||||
args: [
|
||||
'clean',
|
||||
'package',
|
||||
'-Dmaven.test.skip=true'
|
||||
]
|
||||
### Build
|
||||
- id: 'docker build'
|
||||
name: 'gcr.io/cloud-builders/docker'
|
||||
entrypoint: 'bash'
|
||||
args:
|
||||
- '-c'
|
||||
- |
|
||||
echo '$COMMIT_SHA =' $COMMIT_SHA
|
||||
docker build -t gcr.io/$PROJECT_ID/$_PROJECT_NAME:$COMMIT_SHA .
|
||||
### Test
|
||||
### Publish
|
||||
- id: 'publish'
|
||||
name: 'gcr.io/cloud-builders/docker'
|
||||
entrypoint: 'bash'
|
||||
args:
|
||||
- '-c'
|
||||
- |
|
||||
docker push gcr.io/$PROJECT_ID/$_PROJECT_NAME:$COMMIT_SHA
|
||||
### deploy
|
||||
- id: 'deploy'
|
||||
name: 'gcr.io/cloud-builders/gcloud'
|
||||
entrypoint: 'bash'
|
||||
args:
|
||||
- '-c'
|
||||
- |
|
||||
PROJECT=$$(gcloud config get-value core/project)
|
||||
gcloud container clusters get-credentials "$${CLOUDSDK_CONTAINER_CLUSTER}" \
|
||||
--project "$${PROJECT}" \
|
||||
--zone "$${CLOUDSDK_COMPUTE_ZONE}"
|
||||
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: $_PROJECT_NAME
|
||||
labels:
|
||||
app: $_PROJECT_NAME
|
||||
spec:
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: $_PROJECT_NAME
|
||||
type:
|
||||
LoadBalancer
|
||||
EOF
|
||||
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: $_PROJECT_NAME
|
||||
labels:
|
||||
app: $_PROJECT_NAME
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: $_PROJECT_NAME
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: $_PROJECT_NAME
|
||||
spec:
|
||||
containers:
|
||||
- name: $_PROJECT_NAME
|
||||
image: gcr.io/$PROJECT_ID/$_PROJECT_NAME:$COMMIT_SHA
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
EOF
|
||||
substitutions:
|
||||
_PROJECT_NAME: gateway
|
||||
options:
|
||||
env:
|
||||
# # location/name of GKE cluster (used by all kubectl commands)
|
||||
- CLOUDSDK_COMPUTE_ZONE=asia-northeast1-a
|
||||
- CLOUDSDK_CONTAINER_CLUSTER=standard-cluster-1
|
||||
54
gateway/pom.xml
Executable file
54
gateway/pom.xml
Executable file
@@ -0,0 +1,54 @@
|
||||
<?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 http://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>2.1.1.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>boot-camp-gateway</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>boot-camp-gateway</name>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- Add Stackdriver Trace Starter -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-gateway</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
18
gateway/src/main/java/com/example/Application.java
Executable file
18
gateway/src/main/java/com/example/Application.java
Executable file
@@ -0,0 +1,18 @@
|
||||
package com.example;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
public static ApplicationContext applicationContext;
|
||||
public static void main(String[] args) {
|
||||
applicationContext = SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
74
gateway/src/main/resources/application.yml
Executable file
74
gateway/src/main/resources/application.yml
Executable file
@@ -0,0 +1,74 @@
|
||||
server:
|
||||
port: 8088
|
||||
|
||||
---
|
||||
|
||||
spring:
|
||||
profiles: default
|
||||
cloud:
|
||||
gateway:
|
||||
routes:
|
||||
- id: app
|
||||
uri: http://localhost:8081
|
||||
predicates:
|
||||
- Path=/주문/** /메뉴판/**/통합주문상태/**
|
||||
- id: pay
|
||||
uri: http://localhost:8082
|
||||
predicates:
|
||||
- Path=/결제이력/**
|
||||
- id: store
|
||||
uri: http://localhost:8083
|
||||
predicates:
|
||||
- Path=/주문관리/** /주문상세보기/**
|
||||
- id: customer
|
||||
uri: http://localhost:8084
|
||||
predicates:
|
||||
- Path=
|
||||
globalcors:
|
||||
corsConfigurations:
|
||||
'[/**]':
|
||||
allowedOrigins:
|
||||
- "*"
|
||||
allowedMethods:
|
||||
- "*"
|
||||
allowedHeaders:
|
||||
- "*"
|
||||
allowCredentials: true
|
||||
|
||||
|
||||
---
|
||||
|
||||
spring:
|
||||
profiles: docker
|
||||
cloud:
|
||||
gateway:
|
||||
routes:
|
||||
- id: app
|
||||
uri: http://app:8080
|
||||
predicates:
|
||||
- Path=/주문/** /메뉴판/**/통합주문상태/**
|
||||
- id: pay
|
||||
uri: http://pay:8080
|
||||
predicates:
|
||||
- Path=/결제이력/**
|
||||
- id: store
|
||||
uri: http://store:8080
|
||||
predicates:
|
||||
- Path=/주문관리/** /주문상세보기/**
|
||||
- id: customer
|
||||
uri: http://customer:8080
|
||||
predicates:
|
||||
- Path=
|
||||
globalcors:
|
||||
corsConfigurations:
|
||||
'[/**]':
|
||||
allowedOrigins:
|
||||
- "*"
|
||||
allowedMethods:
|
||||
- "*"
|
||||
allowedHeaders:
|
||||
- "*"
|
||||
allowCredentials: true
|
||||
|
||||
server:
|
||||
port: 8080
|
||||
4
pay/Dockerfile
Executable file
4
pay/Dockerfile
Executable file
@@ -0,0 +1,4 @@
|
||||
FROM openjdk:8u212-jdk-alpine
|
||||
COPY target/*SNAPSHOT.jar app.jar
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["java","-Xmx400M","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar","--spring.profiles.active=docker"]
|
||||
103
pay/cloudbuild.yaml
Executable file
103
pay/cloudbuild.yaml
Executable file
@@ -0,0 +1,103 @@
|
||||
steps:
|
||||
### Test
|
||||
# - id: 'test'
|
||||
# name: 'gcr.io/cloud-builders/mvn'
|
||||
# args: [
|
||||
# 'test',
|
||||
# '-Dspring.profiles.active=test'
|
||||
# ]
|
||||
### Build
|
||||
- id: 'build'
|
||||
name: 'gcr.io/cloud-builders/mvn'
|
||||
args: [
|
||||
'clean',
|
||||
'package'
|
||||
# '-Dmaven.test.skip=true'
|
||||
]
|
||||
# waitFor: ['test']
|
||||
### docker Build
|
||||
- id: 'docker build'
|
||||
name: 'gcr.io/cloud-builders/docker'
|
||||
args:
|
||||
- 'build'
|
||||
- '--tag=gcr.io/$PROJECT_ID/$_PROJECT_NAME:latest'
|
||||
- '.'
|
||||
### Publish
|
||||
- id: 'publish'
|
||||
name: 'gcr.io/cloud-builders/docker'
|
||||
entrypoint: 'bash'
|
||||
args:
|
||||
- '-c'
|
||||
- |
|
||||
docker push gcr.io/$PROJECT_ID/$_PROJECT_NAME:latest
|
||||
### deploy
|
||||
- id: 'deploy'
|
||||
name: 'gcr.io/cloud-builders/gcloud'
|
||||
entrypoint: 'bash'
|
||||
args:
|
||||
- '-c'
|
||||
- |
|
||||
PROJECT=$$(gcloud config get-value core/project)
|
||||
gcloud container clusters get-credentials "$${CLOUDSDK_CONTAINER_CLUSTER}" \
|
||||
--project "$${PROJECT}" \
|
||||
--zone "$${CLOUDSDK_COMPUTE_ZONE}"
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: $_PROJECT_NAME
|
||||
labels:
|
||||
app: $_PROJECT_NAME
|
||||
spec:
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: $_PROJECT_NAME
|
||||
EOF
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: $_PROJECT_NAME
|
||||
labels:
|
||||
app: $_PROJECT_NAME
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: $_PROJECT_NAME
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: $_PROJECT_NAME
|
||||
spec:
|
||||
containers:
|
||||
- name: $_PROJECT_NAME
|
||||
image: gcr.io/$PROJECT_ID/$_PROJECT_NAME:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
timeoutSeconds: 2
|
||||
periodSeconds: 5
|
||||
failureThreshold: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health
|
||||
port: 8080
|
||||
initialDelaySeconds: 120
|
||||
timeoutSeconds: 2
|
||||
periodSeconds: 5
|
||||
failureThreshold: 5
|
||||
EOF
|
||||
substitutions:
|
||||
_PROJECT_NAME: pay
|
||||
options:
|
||||
env:
|
||||
# # location/name of GKE cluster (used by all kubectl commands)
|
||||
- CLOUDSDK_COMPUTE_ZONE=asia-northeast1-a
|
||||
- CLOUDSDK_CONTAINER_CLUSTER=cluster-1
|
||||
37
pay/kubernetes/deployment.yml
Executable file
37
pay/kubernetes/deployment.yml
Executable file
@@ -0,0 +1,37 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: pay
|
||||
labels:
|
||||
app: pay
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: pay
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: pay
|
||||
spec:
|
||||
containers:
|
||||
- name: pay
|
||||
image: username/pay:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: '/actuator/health'
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
timeoutSeconds: 2
|
||||
periodSeconds: 5
|
||||
failureThreshold: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: '/actuator/health'
|
||||
port: 8080
|
||||
initialDelaySeconds: 120
|
||||
timeoutSeconds: 2
|
||||
periodSeconds: 5
|
||||
failureThreshold: 5
|
||||
12
pay/kubernetes/service.yaml
Executable file
12
pay/kubernetes/service.yaml
Executable file
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: pay
|
||||
labels:
|
||||
app: pay
|
||||
spec:
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: pay
|
||||
90
pay/pom.xml
Executable file
90
pay/pom.xml
Executable file
@@ -0,0 +1,90 @@
|
||||
<?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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.1.9.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>fooddelivery</groupId>
|
||||
<artifactId>pay</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>pay</name>
|
||||
<description>Demo project for Spring Boot</description>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
|
||||
<spring-cloud-stream.version>Germantown.SR1</spring-cloud-stream.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-rest</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- kafka streams -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-stream-kafka</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-dependencies</artifactId>
|
||||
<version>${spring-cloud-stream.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
78
pay/src/main/java/fooddelivery/AbstractEvent.java
Executable file
78
pay/src/main/java/fooddelivery/AbstractEvent.java
Executable file
@@ -0,0 +1,78 @@
|
||||
package fooddelivery;
|
||||
|
||||
import fooddelivery.config.kafka.KafkaProcessor;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class AbstractEvent {
|
||||
|
||||
String eventType;
|
||||
String timestamp;
|
||||
|
||||
public AbstractEvent(){
|
||||
this.setEventType(this.getClass().getSimpleName());
|
||||
SimpleDateFormat defaultSimpleDateFormat = new SimpleDateFormat("YYYYMMddHHmmss");
|
||||
this.timestamp = defaultSimpleDateFormat.format(new Date());
|
||||
}
|
||||
|
||||
public String toJson(){
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
String json = null;
|
||||
|
||||
try {
|
||||
json = objectMapper.writeValueAsString(this);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException("JSON format exception", e);
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public void publish(){
|
||||
this.publish(this.toJson());
|
||||
}
|
||||
public void publish(String json){
|
||||
if( json != null ){
|
||||
|
||||
/**
|
||||
* spring streams 방식
|
||||
*/
|
||||
KafkaProcessor processor = Application.applicationContext.getBean(KafkaProcessor.class);
|
||||
MessageChannel outputChannel = processor.outboundTopic();
|
||||
|
||||
outputChannel.send(MessageBuilder
|
||||
.withPayload(json)
|
||||
.setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON)
|
||||
.build());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
public void setEventType(String eventType) {
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
public String getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(String timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public boolean isMe(){
|
||||
return getEventType().equals(getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
18
pay/src/main/java/fooddelivery/Application.java
Executable file
18
pay/src/main/java/fooddelivery/Application.java
Executable file
@@ -0,0 +1,18 @@
|
||||
package fooddelivery;
|
||||
import fooddelivery.config.kafka.KafkaProcessor;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.cloud.stream.annotation.EnableBinding;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableBinding(KafkaProcessor.class)
|
||||
@EnableFeignClients
|
||||
public class Application {
|
||||
protected static ApplicationContext applicationContext;
|
||||
public static void main(String[] args) {
|
||||
applicationContext = SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
||||
22
pay/src/main/java/fooddelivery/PolicyHandler.java
Executable file
22
pay/src/main/java/fooddelivery/PolicyHandler.java
Executable file
@@ -0,0 +1,22 @@
|
||||
package fooddelivery;
|
||||
|
||||
import fooddelivery.config.kafka.KafkaProcessor;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.stream.annotation.StreamListener;
|
||||
import org.springframework.messaging.handler.annotation.Payload;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PolicyHandler{
|
||||
|
||||
@StreamListener(KafkaProcessor.INPUT)
|
||||
public void whenever주문취소됨_결재취소함(@Payload 주문취소됨 주문취소됨){
|
||||
|
||||
if(주문취소됨.isMe()){
|
||||
System.out.println("##### listener 결재취소함 : " + 주문취소됨.toJson());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
19
pay/src/main/java/fooddelivery/config/kafka/KafkaProcessor.java
Executable file
19
pay/src/main/java/fooddelivery/config/kafka/KafkaProcessor.java
Executable file
@@ -0,0 +1,19 @@
|
||||
package fooddelivery.config.kafka;
|
||||
|
||||
import org.springframework.cloud.stream.annotation.Input;
|
||||
import org.springframework.cloud.stream.annotation.Output;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.SubscribableChannel;
|
||||
|
||||
public interface KafkaProcessor {
|
||||
|
||||
String INPUT = "event-in";
|
||||
String OUTPUT = "event-out";
|
||||
|
||||
@Input(INPUT)
|
||||
SubscribableChannel inboundTopic();
|
||||
|
||||
@Output(OUTPUT)
|
||||
MessageChannel outboundTopic();
|
||||
|
||||
}
|
||||
34
pay/src/main/java/fooddelivery/결제승인됨.java
Executable file
34
pay/src/main/java/fooddelivery/결제승인됨.java
Executable file
@@ -0,0 +1,34 @@
|
||||
package fooddelivery;
|
||||
|
||||
public class 결제승인됨 extends AbstractEvent {
|
||||
|
||||
private Long id;
|
||||
private String orderId;
|
||||
private Double 금액;
|
||||
|
||||
public 결제승인됨(){
|
||||
super();
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getOrderId() {
|
||||
return orderId;
|
||||
}
|
||||
|
||||
public void setOrderId(String orderId) {
|
||||
this.orderId = orderId;
|
||||
}
|
||||
public Double get금액() {
|
||||
return 금액;
|
||||
}
|
||||
|
||||
public void set금액(Double 금액) {
|
||||
this.금액 = 금액;
|
||||
}
|
||||
}
|
||||
57
pay/src/main/java/fooddelivery/결제이력.java
Executable file
57
pay/src/main/java/fooddelivery/결제이력.java
Executable file
@@ -0,0 +1,57 @@
|
||||
package fooddelivery;
|
||||
|
||||
import javax.persistence.*;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name="결제이력_table")
|
||||
public class 결제이력 {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy=GenerationType.AUTO)
|
||||
private Long id;
|
||||
private String orderId;
|
||||
private Double 금액;
|
||||
|
||||
@PrePersist
|
||||
public void onPrePersist(){
|
||||
결제승인됨 결제승인됨 = new 결제승인됨();
|
||||
BeanUtils.copyProperties(this, 결제승인됨);
|
||||
결제승인됨.publish();
|
||||
|
||||
|
||||
try {
|
||||
Thread.currentThread().sleep((long) (400 + Math.random() * 220));
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getOrderId() {
|
||||
return orderId;
|
||||
}
|
||||
|
||||
public void setOrderId(String orderId) {
|
||||
this.orderId = orderId;
|
||||
}
|
||||
public Double get금액() {
|
||||
return 금액;
|
||||
}
|
||||
|
||||
public void set금액(Double 금액) {
|
||||
this.금액 = 금액;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
15
pay/src/main/java/fooddelivery/결제이력Controller.java
Executable file
15
pay/src/main/java/fooddelivery/결제이력Controller.java
Executable file
@@ -0,0 +1,15 @@
|
||||
package fooddelivery;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
public class 결제이력Controller {
|
||||
|
||||
}
|
||||
8
pay/src/main/java/fooddelivery/결제이력Repository.java
Executable file
8
pay/src/main/java/fooddelivery/결제이력Repository.java
Executable file
@@ -0,0 +1,8 @@
|
||||
package fooddelivery;
|
||||
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
|
||||
public interface 결제이력Repository extends PagingAndSortingRepository<결제이력, Long>{
|
||||
|
||||
|
||||
}
|
||||
18
pay/src/main/java/fooddelivery/결제취소됨.java
Executable file
18
pay/src/main/java/fooddelivery/결제취소됨.java
Executable file
@@ -0,0 +1,18 @@
|
||||
package fooddelivery;
|
||||
|
||||
public class 결제취소됨 extends AbstractEvent {
|
||||
|
||||
private Long id;
|
||||
|
||||
public 결제취소됨(){
|
||||
super();
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
15
pay/src/main/java/fooddelivery/주문취소됨.java
Executable file
15
pay/src/main/java/fooddelivery/주문취소됨.java
Executable file
@@ -0,0 +1,15 @@
|
||||
package fooddelivery;
|
||||
|
||||
|
||||
public class 주문취소됨 extends AbstractEvent {
|
||||
|
||||
private Long id;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
64
pay/src/main/resources/application.yml
Executable file
64
pay/src/main/resources/application.yml
Executable file
@@ -0,0 +1,64 @@
|
||||
server:
|
||||
port: 8080
|
||||
---
|
||||
|
||||
spring:
|
||||
profiles: default
|
||||
jpa:
|
||||
properties:
|
||||
hibernate:
|
||||
show_sql: true
|
||||
format_sql: true
|
||||
cloud:
|
||||
stream:
|
||||
kafka:
|
||||
binder:
|
||||
brokers: localhost:9092
|
||||
streams:
|
||||
binder:
|
||||
configuration:
|
||||
default:
|
||||
key:
|
||||
serde: org.apache.kafka.common.serialization.Serdes$StringSerde
|
||||
value:
|
||||
serde: org.apache.kafka.common.serialization.Serdes$StringSerde
|
||||
bindings:
|
||||
event-in:
|
||||
group: pay
|
||||
destination: fooddelivery
|
||||
contentType: application/json
|
||||
event-out:
|
||||
destination: fooddelivery
|
||||
contentType: application/json
|
||||
|
||||
logging:
|
||||
level:
|
||||
org.hibernate.type: trace
|
||||
org.springframework.cloud: debug
|
||||
server:
|
||||
port: 8082
|
||||
---
|
||||
|
||||
spring:
|
||||
profiles: docker
|
||||
cloud:
|
||||
stream:
|
||||
kafka:
|
||||
binder:
|
||||
brokers: my-kafka.kafka.svc.cluster.local:9092
|
||||
streams:
|
||||
binder:
|
||||
configuration:
|
||||
default:
|
||||
key:
|
||||
serde: org.apache.kafka.common.serialization.Serdes$StringSerde
|
||||
value:
|
||||
serde: org.apache.kafka.common.serialization.Serdes$StringSerde
|
||||
bindings:
|
||||
event-in:
|
||||
group: pay
|
||||
destination: fooddelivery
|
||||
contentType: application/json
|
||||
event-out:
|
||||
destination: fooddelivery
|
||||
contentType: application/json
|
||||
4
store/Dockerfile
Executable file
4
store/Dockerfile
Executable file
@@ -0,0 +1,4 @@
|
||||
FROM openjdk:8u212-jdk-alpine
|
||||
COPY target/*SNAPSHOT.jar app.jar
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["java","-Xmx400M","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar","--spring.profiles.active=docker"]
|
||||
103
store/cloudbuild.yaml
Executable file
103
store/cloudbuild.yaml
Executable file
@@ -0,0 +1,103 @@
|
||||
steps:
|
||||
### Test
|
||||
# - id: 'test'
|
||||
# name: 'gcr.io/cloud-builders/mvn'
|
||||
# args: [
|
||||
# 'test',
|
||||
# '-Dspring.profiles.active=test'
|
||||
# ]
|
||||
### Build
|
||||
- id: 'build'
|
||||
name: 'gcr.io/cloud-builders/mvn'
|
||||
args: [
|
||||
'clean',
|
||||
'package'
|
||||
# '-Dmaven.test.skip=true'
|
||||
]
|
||||
# waitFor: ['test']
|
||||
### docker Build
|
||||
- id: 'docker build'
|
||||
name: 'gcr.io/cloud-builders/docker'
|
||||
args:
|
||||
- 'build'
|
||||
- '--tag=gcr.io/$PROJECT_ID/$_PROJECT_NAME:latest'
|
||||
- '.'
|
||||
### Publish
|
||||
- id: 'publish'
|
||||
name: 'gcr.io/cloud-builders/docker'
|
||||
entrypoint: 'bash'
|
||||
args:
|
||||
- '-c'
|
||||
- |
|
||||
docker push gcr.io/$PROJECT_ID/$_PROJECT_NAME:latest
|
||||
### deploy
|
||||
- id: 'deploy'
|
||||
name: 'gcr.io/cloud-builders/gcloud'
|
||||
entrypoint: 'bash'
|
||||
args:
|
||||
- '-c'
|
||||
- |
|
||||
PROJECT=$$(gcloud config get-value core/project)
|
||||
gcloud container clusters get-credentials "$${CLOUDSDK_CONTAINER_CLUSTER}" \
|
||||
--project "$${PROJECT}" \
|
||||
--zone "$${CLOUDSDK_COMPUTE_ZONE}"
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: $_PROJECT_NAME
|
||||
labels:
|
||||
app: $_PROJECT_NAME
|
||||
spec:
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: $_PROJECT_NAME
|
||||
EOF
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: $_PROJECT_NAME
|
||||
labels:
|
||||
app: $_PROJECT_NAME
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: $_PROJECT_NAME
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: $_PROJECT_NAME
|
||||
spec:
|
||||
containers:
|
||||
- name: $_PROJECT_NAME
|
||||
image: gcr.io/$PROJECT_ID/$_PROJECT_NAME:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
timeoutSeconds: 2
|
||||
periodSeconds: 5
|
||||
failureThreshold: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /actuator/health
|
||||
port: 8080
|
||||
initialDelaySeconds: 120
|
||||
timeoutSeconds: 2
|
||||
periodSeconds: 5
|
||||
failureThreshold: 5
|
||||
EOF
|
||||
substitutions:
|
||||
_PROJECT_NAME: store
|
||||
options:
|
||||
env:
|
||||
# # location/name of GKE cluster (used by all kubectl commands)
|
||||
- CLOUDSDK_COMPUTE_ZONE=asia-northeast1-a
|
||||
- CLOUDSDK_CONTAINER_CLUSTER=cluster-1
|
||||
37
store/kubernetes/deployment.yml
Executable file
37
store/kubernetes/deployment.yml
Executable file
@@ -0,0 +1,37 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: store
|
||||
labels:
|
||||
app: store
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: store
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: store
|
||||
spec:
|
||||
containers:
|
||||
- name: store
|
||||
image: username/store:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: '/actuator/health'
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
timeoutSeconds: 2
|
||||
periodSeconds: 5
|
||||
failureThreshold: 10
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: '/actuator/health'
|
||||
port: 8080
|
||||
initialDelaySeconds: 120
|
||||
timeoutSeconds: 2
|
||||
periodSeconds: 5
|
||||
failureThreshold: 5
|
||||
12
store/kubernetes/service.yaml
Executable file
12
store/kubernetes/service.yaml
Executable file
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: store
|
||||
labels:
|
||||
app: store
|
||||
spec:
|
||||
ports:
|
||||
- port: 8080
|
||||
targetPort: 8080
|
||||
selector:
|
||||
app: store
|
||||
90
store/pom.xml
Executable file
90
store/pom.xml
Executable file
@@ -0,0 +1,90 @@
|
||||
<?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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.1.9.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>fooddelivery</groupId>
|
||||
<artifactId>store</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>store</name>
|
||||
<description>Demo project for Spring Boot</description>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
|
||||
<spring-cloud-stream.version>Germantown.SR1</spring-cloud-stream.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-rest</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- kafka streams -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-stream-kafka</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring-cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-dependencies</artifactId>
|
||||
<version>${spring-cloud-stream.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
78
store/src/main/java/fooddelivery/AbstractEvent.java
Executable file
78
store/src/main/java/fooddelivery/AbstractEvent.java
Executable file
@@ -0,0 +1,78 @@
|
||||
package fooddelivery;
|
||||
|
||||
import fooddelivery.config.kafka.KafkaProcessor;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class AbstractEvent {
|
||||
|
||||
String eventType;
|
||||
String timestamp;
|
||||
|
||||
public AbstractEvent(){
|
||||
this.setEventType(this.getClass().getSimpleName());
|
||||
SimpleDateFormat defaultSimpleDateFormat = new SimpleDateFormat("YYYYMMddHHmmss");
|
||||
this.timestamp = defaultSimpleDateFormat.format(new Date());
|
||||
}
|
||||
|
||||
public String toJson(){
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
String json = null;
|
||||
|
||||
try {
|
||||
json = objectMapper.writeValueAsString(this);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException("JSON format exception", e);
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
public void publish(){
|
||||
this.publish(this.toJson());
|
||||
}
|
||||
public void publish(String json){
|
||||
if( json != null ){
|
||||
|
||||
/**
|
||||
* spring streams 방식
|
||||
*/
|
||||
KafkaProcessor processor = Application.applicationContext.getBean(KafkaProcessor.class);
|
||||
MessageChannel outputChannel = processor.outboundTopic();
|
||||
|
||||
outputChannel.send(MessageBuilder
|
||||
.withPayload(json)
|
||||
.setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON)
|
||||
.build());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
public void setEventType(String eventType) {
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
public String getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(String timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public boolean isMe(){
|
||||
return getEventType().equals(getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
18
store/src/main/java/fooddelivery/Application.java
Executable file
18
store/src/main/java/fooddelivery/Application.java
Executable file
@@ -0,0 +1,18 @@
|
||||
package fooddelivery;
|
||||
import fooddelivery.config.kafka.KafkaProcessor;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.cloud.stream.annotation.EnableBinding;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableBinding(KafkaProcessor.class)
|
||||
@EnableFeignClients
|
||||
public class Application {
|
||||
protected static ApplicationContext applicationContext;
|
||||
public static void main(String[] args) {
|
||||
applicationContext = SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
||||
29
store/src/main/java/fooddelivery/PolicyHandler.java
Executable file
29
store/src/main/java/fooddelivery/PolicyHandler.java
Executable file
@@ -0,0 +1,29 @@
|
||||
package fooddelivery;
|
||||
|
||||
import fooddelivery.config.kafka.KafkaProcessor;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.stream.annotation.StreamListener;
|
||||
import org.springframework.messaging.handler.annotation.Payload;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PolicyHandler{
|
||||
|
||||
@StreamListener(KafkaProcessor.INPUT)
|
||||
public void whenever결제승인됨_주문정보받음(@Payload 결제승인됨 결제승인됨){
|
||||
|
||||
if(결제승인됨.isMe()){
|
||||
System.out.println("##### listener 주문정보받음 : " + 결제승인됨.toJson());
|
||||
}
|
||||
}
|
||||
@StreamListener(KafkaProcessor.INPUT)
|
||||
public void whenever결제취소됨_주문취소처리(@Payload 결제취소됨 결제취소됨){
|
||||
|
||||
if(결제취소됨.isMe()){
|
||||
System.out.println("##### listener 주문취소처리 : " + 결제취소됨.toJson());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
19
store/src/main/java/fooddelivery/config/kafka/KafkaProcessor.java
Executable file
19
store/src/main/java/fooddelivery/config/kafka/KafkaProcessor.java
Executable file
@@ -0,0 +1,19 @@
|
||||
package fooddelivery.config.kafka;
|
||||
|
||||
import org.springframework.cloud.stream.annotation.Input;
|
||||
import org.springframework.cloud.stream.annotation.Output;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.SubscribableChannel;
|
||||
|
||||
public interface KafkaProcessor {
|
||||
|
||||
String INPUT = "event-in";
|
||||
String OUTPUT = "event-out";
|
||||
|
||||
@Input(INPUT)
|
||||
SubscribableChannel inboundTopic();
|
||||
|
||||
@Output(OUTPUT)
|
||||
MessageChannel outboundTopic();
|
||||
|
||||
}
|
||||
43
store/src/main/java/fooddelivery/결제승인됨.java
Executable file
43
store/src/main/java/fooddelivery/결제승인됨.java
Executable file
@@ -0,0 +1,43 @@
|
||||
|
||||
package fooddelivery;
|
||||
|
||||
import javax.persistence.PrePersist;
|
||||
|
||||
public class 결제승인됨 extends AbstractEvent {
|
||||
|
||||
private Long id;
|
||||
private String orderId;
|
||||
private Double 금액;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getOrderId() {
|
||||
return orderId;
|
||||
}
|
||||
|
||||
public void setOrderId(String orderId) {
|
||||
this.orderId = orderId;
|
||||
}
|
||||
public Double get금액() {
|
||||
return 금액;
|
||||
}
|
||||
|
||||
public void set금액(Double 금액) {
|
||||
this.금액 = 금액;
|
||||
}
|
||||
|
||||
|
||||
@PrePersist
|
||||
public void delay(){
|
||||
try {
|
||||
Thread.currentThread().sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
15
store/src/main/java/fooddelivery/결제취소됨.java
Executable file
15
store/src/main/java/fooddelivery/결제취소됨.java
Executable file
@@ -0,0 +1,15 @@
|
||||
package fooddelivery;
|
||||
|
||||
|
||||
public class 결제취소됨 extends AbstractEvent {
|
||||
|
||||
private Long id;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
42
store/src/main/java/fooddelivery/배달시작됨.java
Executable file
42
store/src/main/java/fooddelivery/배달시작됨.java
Executable file
@@ -0,0 +1,42 @@
|
||||
package fooddelivery;
|
||||
|
||||
public class 배달시작됨 extends AbstractEvent {
|
||||
|
||||
private Long id;
|
||||
private String 요리종류;
|
||||
private String 배달지주소;
|
||||
private String orderId;
|
||||
|
||||
public 배달시작됨(){
|
||||
super();
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String get요리종류() {
|
||||
return 요리종류;
|
||||
}
|
||||
|
||||
public void set요리종류(String 요리종류) {
|
||||
this.요리종류 = 요리종류;
|
||||
}
|
||||
public String get배달지주소() {
|
||||
return 배달지주소;
|
||||
}
|
||||
|
||||
public void set배달지주소(String 배달지주소) {
|
||||
this.배달지주소 = 배달지주소;
|
||||
}
|
||||
public String getOrderId() {
|
||||
return orderId;
|
||||
}
|
||||
|
||||
public void setOrderId(String orderId) {
|
||||
this.orderId = orderId;
|
||||
}
|
||||
}
|
||||
45
store/src/main/java/fooddelivery/주문관리.java
Executable file
45
store/src/main/java/fooddelivery/주문관리.java
Executable file
@@ -0,0 +1,45 @@
|
||||
package fooddelivery;
|
||||
|
||||
import javax.persistence.*;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name="주문관리_table")
|
||||
public class 주문관리 {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy=GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@PostPersist
|
||||
public void onPostPersist(){
|
||||
배달시작됨 배달시작됨 = new 배달시작됨();
|
||||
BeanUtils.copyProperties(this, 배달시작됨);
|
||||
배달시작됨.publish();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@PrePersist
|
||||
public void onPrePersist(){
|
||||
쿠폰발행됨 쿠폰발행됨 = new 쿠폰발행됨();
|
||||
BeanUtils.copyProperties(this, 쿠폰발행됨);
|
||||
쿠폰발행됨.publish();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
15
store/src/main/java/fooddelivery/주문관리Controller.java
Executable file
15
store/src/main/java/fooddelivery/주문관리Controller.java
Executable file
@@ -0,0 +1,15 @@
|
||||
package fooddelivery;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
public class 주문관리Controller {
|
||||
|
||||
}
|
||||
8
store/src/main/java/fooddelivery/주문관리Repository.java
Executable file
8
store/src/main/java/fooddelivery/주문관리Repository.java
Executable file
@@ -0,0 +1,8 @@
|
||||
package fooddelivery;
|
||||
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
|
||||
public interface 주문관리Repository extends PagingAndSortingRepository<주문관리, Long>{
|
||||
|
||||
|
||||
}
|
||||
42
store/src/main/java/fooddelivery/쿠폰발행됨.java
Executable file
42
store/src/main/java/fooddelivery/쿠폰발행됨.java
Executable file
@@ -0,0 +1,42 @@
|
||||
package fooddelivery;
|
||||
|
||||
public class 쿠폰발행됨 extends AbstractEvent {
|
||||
|
||||
private Long id;
|
||||
private String 요리종류;
|
||||
private String 배달지주소;
|
||||
private String orderId;
|
||||
|
||||
public 쿠폰발행됨(){
|
||||
super();
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String get요리종류() {
|
||||
return 요리종류;
|
||||
}
|
||||
|
||||
public void set요리종류(String 요리종류) {
|
||||
this.요리종류 = 요리종류;
|
||||
}
|
||||
public String get배달지주소() {
|
||||
return 배달지주소;
|
||||
}
|
||||
|
||||
public void set배달지주소(String 배달지주소) {
|
||||
this.배달지주소 = 배달지주소;
|
||||
}
|
||||
public String getOrderId() {
|
||||
return orderId;
|
||||
}
|
||||
|
||||
public void setOrderId(String orderId) {
|
||||
this.orderId = orderId;
|
||||
}
|
||||
}
|
||||
64
store/src/main/resources/application.yml
Executable file
64
store/src/main/resources/application.yml
Executable file
@@ -0,0 +1,64 @@
|
||||
server:
|
||||
port: 8080
|
||||
---
|
||||
|
||||
spring:
|
||||
profiles: default
|
||||
jpa:
|
||||
properties:
|
||||
hibernate:
|
||||
show_sql: true
|
||||
format_sql: true
|
||||
cloud:
|
||||
stream:
|
||||
kafka:
|
||||
binder:
|
||||
brokers: localhost:9092
|
||||
streams:
|
||||
binder:
|
||||
configuration:
|
||||
default:
|
||||
key:
|
||||
serde: org.apache.kafka.common.serialization.Serdes$StringSerde
|
||||
value:
|
||||
serde: org.apache.kafka.common.serialization.Serdes$StringSerde
|
||||
bindings:
|
||||
event-in:
|
||||
group: store
|
||||
destination: fooddelivery
|
||||
contentType: application/json
|
||||
event-out:
|
||||
destination: fooddelivery
|
||||
contentType: application/json
|
||||
|
||||
logging:
|
||||
level:
|
||||
org.hibernate.type: trace
|
||||
org.springframework.cloud: debug
|
||||
server:
|
||||
port: 8083
|
||||
---
|
||||
|
||||
spring:
|
||||
profiles: docker
|
||||
cloud:
|
||||
stream:
|
||||
kafka:
|
||||
binder:
|
||||
brokers: my-kafka.kafka.svc.cluster.local:9092
|
||||
streams:
|
||||
binder:
|
||||
configuration:
|
||||
default:
|
||||
key:
|
||||
serde: org.apache.kafka.common.serialization.Serdes$StringSerde
|
||||
value:
|
||||
serde: org.apache.kafka.common.serialization.Serdes$StringSerde
|
||||
bindings:
|
||||
event-in:
|
||||
group: store
|
||||
destination: fooddelivery
|
||||
contentType: application/json
|
||||
event-out:
|
||||
destination: fooddelivery
|
||||
contentType: application/json
|
||||
Reference in New Issue
Block a user