diff --git a/deploy/docker-compose/docker-compose.yml b/deploy/docker-compose/docker-compose.yml
index 9104d6aab..664335653 100644
--- a/deploy/docker-compose/docker-compose.yml
+++ b/deploy/docker-compose/docker-compose.yml
@@ -1,12 +1,12 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
-#
+#
# 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.
-#
+#
# 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
@@ -19,7 +19,7 @@ version: '2'
services:
ui:
ports:
- - 8888:8080
+ - 8888:8080
environment:
- JAVA_OPTS=-XX:MaxRAMPercentage=75.0 -Djava.security.egd=file:/dev/urandom
- SERVER_TOMCAT_ACCESSLOG_ENABLED=true
@@ -79,7 +79,7 @@ services:
hostname: carts-db
restart: always
mem_limit: 256m
-
+
orders:
hostname: orders
image: retail-store-sample-orders:${TAG:-latest}
@@ -87,28 +87,31 @@ services:
environment:
- JAVA_OPTS=-XX:MaxRAMPercentage=75.0 -Djava.security.egd=file:/dev/urandom
- SERVER_TOMCAT_ACCESSLOG_ENABLED=true
- - SPRING_PROFILES_ACTIVE=mysql,rabbitmq
- - SPRING_DATASOURCE_WRITER_URL=jdbc:mariadb://orders-db:3306/orders
- - SPRING_DATASOURCE_WRITER_USERNAME=orders_user
- - SPRING_DATASOURCE_WRITER_PASSWORD=${MYSQL_PASSWORD}
- - SPRING_DATASOURCE_READER_URL=jdbc:mariadb://orders-db:3306/orders
- - SPRING_DATASOURCE_READER_USERNAME=orders_user
- - SPRING_DATASOURCE_READER_PASSWORD=${MYSQL_PASSWORD}
+ - SPRING_PROFILES_ACTIVE=rabbitmq
+ - SPRING_DATASOURCE_URL=jdbc:postgresql://orders-db:5432/orders
+ - SPRING_DATASOURCE_USERNAME=orders_user
+ - SPRING_DATASOURCE_PASSWORD=${MYSQL_PASSWORD}
- SPRING_RABBITMQ_HOST=rabbitmq
mem_limit: 512m
cap_drop:
- ALL
orders-db:
- image: mariadb:10.9
+ image: postgres:16.1
hostname: orders-db
restart: always
+ security_opt:
+ - no-new-privileges:true
environment:
- - MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
- - MYSQL_ALLOW_EMPTY_PASSWORD=true
- - MYSQL_DATABASE=orders
- - MYSQL_USER=orders_user
- - MYSQL_PASSWORD=${MYSQL_PASSWORD}
+ - reschedule=on-node-failure
+ - POSTGRES_PASSWORD=${MYSQL_PASSWORD}
+ - POSTGRES_DB=orders
+ - POSTGRES_USER=orders_user
+ healthcheck:
+ test: [ "CMD-SHELL", "pg_isready -d orders -U orders_user" ]
+ interval: 10s
+ timeout: 5s
+ retries: 30
mem_limit: 128m
checkout:
@@ -145,4 +148,4 @@ services:
image: rabbitmq:3-management
ports:
- "5672:5672"
- - "15672:15672"
\ No newline at end of file
+ - "15672:15672"
diff --git a/deploy/kubernetes/charts/orders/templates/_helpers.tpl b/deploy/kubernetes/charts/orders/templates/_helpers.tpl
index 3a9ad8fdc..1c5c6c6ae 100644
--- a/deploy/kubernetes/charts/orders/templates/_helpers.tpl
+++ b/deploy/kubernetes/charts/orders/templates/_helpers.tpl
@@ -86,16 +86,16 @@ Create the name of the config map to use
{{- end }}
{{- end -}}
-{{- define "orders.mysql.fullname" -}}
-{{- include "orders.fullname" . }}-mysql
+{{- define "orders.postgresql.fullname" -}}
+{{- include "orders.fullname" . }}-postgresql
{{- end -}}
{{/*
-Common labels for mysql
+Common labels for postgresql
*/}}
-{{- define "orders.mysql.labels" -}}
+{{- define "orders.postgresql.labels" -}}
helm.sh/chart: {{ include "orders.chart" . }}
-{{ include "orders.mysql.selectorLabels" . }}
+{{ include "orders.postgresql.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
@@ -103,12 +103,12 @@ app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
-Selector labels for mysql
+Selector labels for postgresql
*/}}
-{{- define "orders.mysql.selectorLabels" -}}
+{{- define "orders.postgresql.selectorLabels" -}}
app.kubernetes.io/name: {{ include "orders.fullname" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
-app.kubernetes.io/component: mysql
+app.kubernetes.io/component: postgresql
{{- end }}
{{- define "getOrGeneratePass" }}
@@ -123,35 +123,19 @@ app.kubernetes.io/component: mysql
{{- end -}}
{{- end }}
-{{- define "orders.mysql.password" -}}
-{{- if not (empty .Values.mysql.secret.password) -}}
- {{- .Values.mysql.secret.password | b64enc -}}
+{{- define "orders.postgresql.password" -}}
+{{- if not (empty .Values.postgresql.secret.password) -}}
+ {{- .Values.postgresql.secret.password | b64enc -}}
{{- else -}}
- {{- include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" .Values.mysql.secret.name "Key" "password") -}}
+ {{- include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" .Values.postgresql.secret.name "Key" "password") -}}
{{- end -}}
{{- end -}}
-{{- define "orders.mysql.reader.password" -}}
-{{- if not (empty .Values.mysql.reader.secret.password) -}}
- {{- .Values.mysql.reader.secret.password | b64enc -}}
+{{- define "orders.postgresql.endpoint" -}}
+{{- if not (empty .Values.postgresql.endpoint.host) -}}
+jdbc:postgresql://{{- .Values.postgresql.endpoint.host -}}:{{- .Values.postgresql.endpoint.port -}}/{{ .Values.postgresql.database }}
{{- else -}}
- {{- include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" .Values.mysql.reader.secret.name "Key" "password") -}}
-{{- end -}}
-{{- end -}}
-
-{{- define "orders.mysql.endpoint" -}}
-{{- if not (empty .Values.mysql.endpoint) -}}
- {{- .Values.mysql.endpoint -}}
-{{- else -}}
-jdbc:mariadb://{{ include "orders.mysql.fullname" . }}:{{ .Values.mysql.service.port }}/{{ .Values.mysql.database }}
-{{- end -}}
-{{- end -}}
-
-{{- define "orders.mysql.reader.endpoint" -}}
-{{- if not (empty .Values.mysql.reader.endpoint) -}}
- {{- .Values.mysql.reader.endpoint -}}
-{{- else -}}
-{{- include "orders.mysql.endpoint" . -}}
+jdbc:postgresql://{{ include "orders.postgresql.fullname" . }}:{{ .Values.postgresql.service.port }}/{{ .Values.postgresql.database }}
{{- end -}}
{{- end -}}
diff --git a/deploy/kubernetes/charts/orders/templates/configmap.yml b/deploy/kubernetes/charts/orders/templates/configmap.yml
index 179f90799..ab3f8f0f6 100644
--- a/deploy/kubernetes/charts/orders/templates/configmap.yml
+++ b/deploy/kubernetes/charts/orders/templates/configmap.yml
@@ -4,8 +4,7 @@ kind: ConfigMap
metadata:
name: {{ include "orders.configMapName" . }}
data:
- SPRING_PROFILES_ACTIVE: mysql,rabbitmq
- SPRING_DATASOURCE_READER_URL: {{ include "orders.mysql.endpoint" . }}
- SPRING_DATASOURCE_WRITER_URL: {{ include "orders.mysql.reader.endpoint" . }}
+ SPRING_PROFILES_ACTIVE: rabbitmq
+ SPRING_DATASOURCE_URL: {{ include "orders.postgresql.endpoint" . }}
SPRING_RABBITMQ_ADDRESSES: {{ include "orders.rabbitmq.addresses" . }}
{{- end }}
diff --git a/deploy/kubernetes/charts/orders/templates/deployment.yaml b/deploy/kubernetes/charts/orders/templates/deployment.yaml
index 3eb5bb802..f28f23ff9 100644
--- a/deploy/kubernetes/charts/orders/templates/deployment.yaml
+++ b/deploy/kubernetes/charts/orders/templates/deployment.yaml
@@ -39,25 +39,15 @@ spec:
env:
- name: JAVA_OPTS
value: -XX:MaxRAMPercentage=75.0 -Djava.security.egd=file:/dev/urandom
- - name: SPRING_DATASOURCE_WRITER_USERNAME
+ - name: SPRING_DATASOURCE_USERNAME
valueFrom:
secretKeyRef:
- name: {{ .Values.mysql.secret.name }}
+ name: {{ .Values.postgresql.secret.name }}
key: username
- - name: SPRING_DATASOURCE_WRITER_PASSWORD
+ - name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
- name: {{ .Values.mysql.secret.name }}
- key: password
- - name: SPRING_DATASOURCE_READER_USERNAME
- valueFrom:
- secretKeyRef:
- name: {{ .Values.mysql.reader.secret.name }}
- key: username
- - name: SPRING_DATASOURCE_READER_PASSWORD
- valueFrom:
- secretKeyRef:
- name: {{ .Values.mysql.reader.secret.name }}
+ name: {{ .Values.postgresql.secret.name }}
key: password
envFrom:
- secretRef:
diff --git a/deploy/kubernetes/charts/orders/templates/mysql-reader-secret.yaml b/deploy/kubernetes/charts/orders/templates/mysql-reader-secret.yaml
deleted file mode 100644
index 17f2a1ff0..000000000
--- a/deploy/kubernetes/charts/orders/templates/mysql-reader-secret.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-{{- if .Values.mysql.reader.secret.create }}
-apiVersion: v1
-kind: Secret
-metadata:
- name: {{ .Values.mysql.reader.secret.name }}
-data:
- username: {{ .Values.mysql.reader.secret.username | b64enc | quote }}
- password: "{{ include "orders.mysql.reader.password" . }}"
-{{- end }}
\ No newline at end of file
diff --git a/deploy/kubernetes/charts/orders/templates/mysql-secret.yaml b/deploy/kubernetes/charts/orders/templates/mysql-secret.yaml
deleted file mode 100644
index 44faebc4d..000000000
--- a/deploy/kubernetes/charts/orders/templates/mysql-secret.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-{{- if .Values.mysql.secret.create }}
-apiVersion: v1
-kind: Secret
-metadata:
- name: {{ .Values.mysql.secret.name }}
-data:
- username: {{ .Values.mysql.secret.username | b64enc | quote }}
- password: "{{ include "orders.mysql.password" . }}"
-{{- end }}
\ No newline at end of file
diff --git a/deploy/kubernetes/charts/orders/templates/mysql-service.yaml b/deploy/kubernetes/charts/orders/templates/mysql-service.yaml
deleted file mode 100644
index 3bd08918f..000000000
--- a/deploy/kubernetes/charts/orders/templates/mysql-service.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-{{- if .Values.mysql.create }}
-apiVersion: v1
-kind: Service
-metadata:
- name: {{ include "orders.mysql.fullname" . }}
- labels:
- {{- include "orders.mysql.labels" . | nindent 4 }}
-spec:
- type: {{ .Values.mysql.service.type }}
- ports:
- - port: {{ .Values.mysql.service.port }}
- targetPort: mysql
- protocol: TCP
- name: mysql
- selector:
- {{- include "orders.mysql.selectorLabels" . | nindent 4 }}
-{{- end }}
\ No newline at end of file
diff --git a/deploy/kubernetes/charts/orders/templates/mysql-statefulset.yaml b/deploy/kubernetes/charts/orders/templates/mysql-statefulset.yaml
deleted file mode 100644
index eaf85423b..000000000
--- a/deploy/kubernetes/charts/orders/templates/mysql-statefulset.yaml
+++ /dev/null
@@ -1,97 +0,0 @@
-{{- if .Values.mysql.create }}
-apiVersion: apps/v1
-kind: StatefulSet
-metadata:
- name: {{ include "orders.mysql.fullname" . }}
- labels:
- {{- include "orders.mysql.labels" . | nindent 4 }}
-spec:
- replicas: 1
- serviceName: {{ include "orders.mysql.fullname" . }}
- selector:
- matchLabels:
- {{- include "orders.mysql.selectorLabels" . | nindent 6 }}
- template:
- metadata:
- {{- with .Values.mysql.podAnnotations }}
- annotations:
- {{- toYaml . | nindent 8 }}
- {{- end }}
- labels:
- {{- include "orders.mysql.selectorLabels" . | nindent 8 }}
- spec:
- {{- with .Values.imagePullSecrets }}
- imagePullSecrets:
- {{- toYaml . | nindent 8 }}
- {{- end }}
- containers:
- - name: mysql
- image: "{{ .Values.mysql.image.repository }}:{{ .Values.mysql.image.tag }}"
- imagePullPolicy: {{ .Values.mysql.image.pullPolicy }}
- env:
- - name: MYSQL_ROOT_PASSWORD
- value: my-secret-pw
- - name: MYSQL_DATABASE
- value: {{ .Values.mysql.database }}
- - name: MYSQL_USER
- valueFrom:
- secretKeyRef:
- name: {{ .Values.mysql.secret.name }}
- key: username
- - name: MYSQL_PASSWORD
- valueFrom:
- secretKeyRef:
- name: {{ .Values.mysql.secret.name }}
- key: password
- args:
- - "--ignore-db-dir=lost+found"
- volumeMounts:
- - name: data
- mountPath: /var/lib/mysql
- ports:
- - name: mysql
- containerPort: 3306
- protocol: TCP
- {{- with .Values.mysql.nodeSelector }}
- nodeSelector:
- {{- toYaml . | nindent 8 }}
- {{- end }}
- {{- with .Values.mysql.affinity }}
- affinity:
- {{- toYaml . | nindent 8 }}
- {{- end }}
- {{- with .Values.mysql.tolerations }}
- tolerations:
- {{- toYaml . | nindent 8 }}
- {{- end }}
-{{- if .Values.mysql.persistentVolume.enabled }}
- volumeClaimTemplates:
- - metadata:
- name: data
- {{- if .Values.mysql.persistentVolume.annotations }}
- annotations:
-{{ toYaml .Values.mysql.persistentVolume.annotations | indent 10 }}
- {{- end }}
- {{- if .Values.mysql.persistentVolume.labels }}
- labels:
-{{ toYaml .Values.mysql.persistentVolume.labels | indent 10 }}
- {{- end }}
- spec:
- accessModes:
-{{ toYaml .Values.mysql.persistentVolume.accessModes | indent 8 }}
- resources:
- requests:
- storage: "{{ .Values.mysql.persistentVolume.size }}"
- {{- if .Values.mysql.persistentVolume.storageClass }}
- {{- if (eq "-" .Values.mysql.persistentVolume.storageClass) }}
- storageClassName: ""
- {{- else }}
- storageClassName: "{{ .Values.mysql.persistentVolume.storageClass }}"
- {{- end }}
- {{- end }}
-{{- else }}
- volumes:
- - name: data
- emptyDir: {}
-{{- end }}
-{{- end }}
\ No newline at end of file
diff --git a/deploy/kubernetes/charts/orders/templates/postgresql-secret.yaml b/deploy/kubernetes/charts/orders/templates/postgresql-secret.yaml
new file mode 100644
index 000000000..e088e59c5
--- /dev/null
+++ b/deploy/kubernetes/charts/orders/templates/postgresql-secret.yaml
@@ -0,0 +1,9 @@
+{{- if .Values.postgresql.secret.create }}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ .Values.postgresql.secret.name }}
+data:
+ username: {{ .Values.postgresql.secret.username | b64enc | quote }}
+ password: "{{ include "orders.postgresql.password" . }}"
+{{- end }}
\ No newline at end of file
diff --git a/deploy/kubernetes/charts/orders/templates/postgresql-service.yaml b/deploy/kubernetes/charts/orders/templates/postgresql-service.yaml
new file mode 100644
index 000000000..fd9c780b1
--- /dev/null
+++ b/deploy/kubernetes/charts/orders/templates/postgresql-service.yaml
@@ -0,0 +1,17 @@
+{{- if .Values.postgresql.create }}
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "orders.postgresql.fullname" . }}
+ labels:
+ {{- include "orders.postgresql.labels" . | nindent 4 }}
+spec:
+ type: {{ .Values.postgresql.service.type }}
+ ports:
+ - port: {{ .Values.postgresql.service.port }}
+ targetPort: postgresql
+ protocol: TCP
+ name: postgresql
+ selector:
+ {{- include "orders.postgresql.selectorLabels" . | nindent 4 }}
+{{- end }}
\ No newline at end of file
diff --git a/deploy/kubernetes/charts/orders/templates/postgresql-statefulset.yaml b/deploy/kubernetes/charts/orders/templates/postgresql-statefulset.yaml
new file mode 100644
index 000000000..9f93a2f02
--- /dev/null
+++ b/deploy/kubernetes/charts/orders/templates/postgresql-statefulset.yaml
@@ -0,0 +1,95 @@
+{{- if .Values.postgresql.create }}
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: {{ include "orders.postgresql.fullname" . }}
+ labels:
+ {{- include "orders.postgresql.labels" . | nindent 4 }}
+spec:
+ replicas: 1
+ serviceName: {{ include "orders.postgresql.fullname" . }}
+ selector:
+ matchLabels:
+ {{- include "orders.postgresql.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ {{- with .Values.postgresql.podAnnotations }}
+ annotations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "orders.postgresql.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ containers:
+ - name: postgresql
+ image: "{{ .Values.postgresql.image.repository }}:{{ .Values.postgresql.image.tag }}"
+ imagePullPolicy: {{ .Values.postgresql.image.pullPolicy }}
+ env:
+ - name: POSTGRES_DB
+ value: {{ .Values.postgresql.database }}
+ - name: POSTGRES_USER
+ valueFrom:
+ secretKeyRef:
+ name: {{ .Values.postgresql.secret.name }}
+ key: username
+ - name: POSTGRES_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: {{ .Values.postgresql.secret.name }}
+ key: password
+ - name: PGDATA
+ value: /data/pgdata
+ volumeMounts:
+ - name: data
+ mountPath: /data
+ ports:
+ - name: postgresql
+ containerPort: 5432
+ protocol: TCP
+ {{- with .Values.postgresql.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.postgresql.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.postgresql.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+{{- if .Values.postgresql.persistentVolume.enabled }}
+ volumeClaimTemplates:
+ - metadata:
+ name: data
+ {{- if .Values.postgresql.persistentVolume.annotations }}
+ annotations:
+{{ toYaml .Values.postgresql.persistentVolume.annotations | indent 10 }}
+ {{- end }}
+ {{- if .Values.postgresql.persistentVolume.labels }}
+ labels:
+{{ toYaml .Values.postgresql.persistentVolume.labels | indent 10 }}
+ {{- end }}
+ spec:
+ accessModes:
+{{ toYaml .Values.postgresql.persistentVolume.accessModes | indent 8 }}
+ resources:
+ requests:
+ storage: "{{ .Values.postgresql.persistentVolume.size }}"
+ {{- if .Values.postgresql.persistentVolume.storageClass }}
+ {{- if (eq "-" .Values.postgresql.persistentVolume.storageClass) }}
+ storageClassName: ""
+ {{- else }}
+ storageClassName: "{{ .Values.postgresql.persistentVolume.storageClass }}"
+ {{- end }}
+ {{- end }}
+{{- else }}
+ volumes:
+ - name: data
+ emptyDir: {}
+{{- end }}
+{{- end }}
\ No newline at end of file
diff --git a/deploy/kubernetes/charts/orders/values.yaml b/deploy/kubernetes/charts/orders/values.yaml
index ea30cb748..5df511981 100644
--- a/deploy/kubernetes/charts/orders/values.yaml
+++ b/deploy/kubernetes/charts/orders/values.yaml
@@ -70,12 +70,14 @@ configMap:
create: true
name:
-mysql:
+postgresql:
create: true
database: orders
- endpoint: ""
+ endpoint:
+ host: ""
+ port: ""
secret:
create: true
@@ -92,13 +94,13 @@ mysql:
password: ""
image:
- repository: mysql
+ repository: postgres
pullPolicy: IfNotPresent
- tag: "5.7"
+ tag: "16.1"
service:
type: ClusterIP
- port: 3306
+ port: 5432
podAnnotations: {}
diff --git a/deploy/kubernetes/charts/templates/orders.yaml.gotmpl b/deploy/kubernetes/charts/templates/orders.yaml.gotmpl
index 163df87a2..6b36ab44a 100644
--- a/deploy/kubernetes/charts/templates/orders.yaml.gotmpl
+++ b/deploy/kubernetes/charts/templates/orders.yaml.gotmpl
@@ -5,7 +5,7 @@ image:
{{end}}
{{if env "RANDOM_PASSWORD" }}
-mysql:
+postgresql:
secret:
password: {{ env "RANDOM_PASSWORD" | default "" }}
{{end}}
\ No newline at end of file
diff --git a/deploy/terraform/eks/default/kubernetes.tf b/deploy/terraform/eks/default/kubernetes.tf
index 8818b1713..f733786c5 100644
--- a/deploy/terraform/eks/default/kubernetes.tf
+++ b/deploy/terraform/eks/default/kubernetes.tf
@@ -46,7 +46,7 @@ resource "time_sleep" "workloads" {
create_duration = "30s"
destroy_duration = "60s"
- depends_on = [
+ depends_on = [
null_resource.addons_blocker
]
}
@@ -64,12 +64,12 @@ resource "kubernetes_namespace_v1" "assets" {
}
resource "helm_release" "assets" {
- name = "assets"
- chart = "../../../kubernetes/charts/assets"
+ name = "assets"
+ chart = "../../../kubernetes/charts/assets"
- namespace = kubernetes_namespace_v1.assets.metadata[0].name
+ namespace = kubernetes_namespace_v1.assets.metadata[0].name
values = [
- templatefile("${path.module}/values/assets.yaml", {
+ templatefile("${path.module}/values/assets.yaml", {
opentelemetry_enabled = var.opentelemetry_enabled
})
]
@@ -88,13 +88,13 @@ resource "kubernetes_namespace_v1" "catalog" {
}
resource "helm_release" "catalog" {
- name = "catalog"
- chart = "../../../kubernetes/charts/catalog"
+ name = "catalog"
+ chart = "../../../kubernetes/charts/catalog"
- namespace = kubernetes_namespace_v1.catalog.metadata[0].name
+ namespace = kubernetes_namespace_v1.catalog.metadata[0].name
values = [
- templatefile("${path.module}/values/catalog.yaml", {
+ templatefile("${path.module}/values/catalog.yaml", {
opentelemetry_enabled = var.opentelemetry_enabled
database_endpoint = "${module.dependencies.catalog_db_endpoint}:${module.dependencies.catalog_db_port}"
database_username = module.dependencies.catalog_db_master_username
@@ -117,16 +117,16 @@ resource "kubernetes_namespace_v1" "carts" {
}
resource "helm_release" "carts" {
- name = "carts"
- chart = "../../../kubernetes/charts/carts"
+ name = "carts"
+ chart = "../../../kubernetes/charts/carts"
- namespace = kubernetes_namespace_v1.carts.metadata[0].name
+ namespace = kubernetes_namespace_v1.carts.metadata[0].name
values = [
- templatefile("${path.module}/values/carts.yaml", {
+ templatefile("${path.module}/values/carts.yaml", {
opentelemetry_enabled = var.opentelemetry_enabled
role_arn = module.iam_assumable_role_carts.iam_role_arn
- table_name = module.dependencies.carts_dynamodb_table_name
+ table_name = module.dependencies.carts_dynamodb_table_name
})
]
}
@@ -144,13 +144,13 @@ resource "kubernetes_namespace_v1" "checkout" {
}
resource "helm_release" "checkout" {
- name = "checkout"
- chart = "../../../kubernetes/charts/checkout"
+ name = "checkout"
+ chart = "../../../kubernetes/charts/checkout"
- namespace = kubernetes_namespace_v1.checkout.metadata[0].name
+ namespace = kubernetes_namespace_v1.checkout.metadata[0].name
values = [
- templatefile("${path.module}/values/checkout.yaml", {
+ templatefile("${path.module}/values/checkout.yaml", {
opentelemetry_enabled = var.opentelemetry_enabled
redis_address = module.dependencies.checkout_elasticache_primary_endpoint
redis_port = module.dependencies.checkout_elasticache_port
@@ -172,21 +172,23 @@ resource "kubernetes_namespace_v1" "orders" {
}
resource "helm_release" "orders" {
- name = "orders"
- chart = "../../../kubernetes/charts/orders"
+ name = "orders"
+ chart = "../../../kubernetes/charts/orders"
- namespace = kubernetes_namespace_v1.orders.metadata[0].name
+ namespace = kubernetes_namespace_v1.orders.metadata[0].name
values = [
- templatefile("${path.module}/values/orders.yaml", {
- opentelemetry_enabled = var.opentelemetry_enabled
- database_endpoint = "jdbc:mariadb://${module.dependencies.orders_db_endpoint}:${module.dependencies.orders_db_port}/${module.dependencies.orders_db_database_name}"
- database_username = module.dependencies.orders_db_master_username
- database_password = module.dependencies.orders_db_master_password
- rabbitmq_endpoint = module.dependencies.mq_broker_endpoint
- rabbitmq_username = module.dependencies.mq_user
- rabbitmq_password = module.dependencies.mq_password
- security_group_id = aws_security_group.orders.id
+ templatefile("${path.module}/values/orders.yaml", {
+ opentelemetry_enabled = var.opentelemetry_enabled
+ database_endpoint_host = module.dependencies.orders_db_endpoint
+ database_endpoint_port = module.dependencies.orders_db_port
+ database_name = module.dependencies.orders_db_database_name
+ database_username = module.dependencies.orders_db_master_username
+ database_password = module.dependencies.orders_db_master_password
+ rabbitmq_endpoint = module.dependencies.mq_broker_endpoint
+ rabbitmq_username = module.dependencies.mq_user
+ rabbitmq_password = module.dependencies.mq_password
+ security_group_id = aws_security_group.orders.id
})
]
}
@@ -204,10 +206,10 @@ resource "kubernetes_namespace_v1" "ui" {
}
resource "helm_release" "ui" {
- name = "ui"
- chart = "../../../kubernetes/charts/ui"
+ name = "ui"
+ chart = "../../../kubernetes/charts/ui"
- namespace = kubernetes_namespace_v1.ui.metadata[0].name
+ namespace = kubernetes_namespace_v1.ui.metadata[0].name
values = [
templatefile("${path.module}/values/ui.yaml", {
@@ -220,23 +222,23 @@ resource "helm_release" "ui" {
resource "time_sleep" "restart_pods" {
create_duration = "30s"
- depends_on = [
+ depends_on = [
helm_release.ui,
helm_release.opentelemetry
]
}
resource "null_resource" "restart_pods" {
- depends_on = [ time_sleep.restart_pods ]
+ depends_on = [time_sleep.restart_pods]
provisioner "local-exec" {
interpreter = ["/bin/bash", "-c"]
environment = {
KUBECONFIG = base64encode(local.kubeconfig)
}
-
+
command = <<-EOT
kubectl delete pod -A -l app.kuberneres.io/owner=retail-store-sample --kubeconfig <(echo $KUBECONFIG | base64 -d)
EOT
}
-}
\ No newline at end of file
+}
diff --git a/deploy/terraform/eks/default/values/orders.yaml b/deploy/terraform/eks/default/values/orders.yaml
index 103fc9fbc..185c4d93a 100644
--- a/deploy/terraform/eks/default/values/orders.yaml
+++ b/deploy/terraform/eks/default/values/orders.yaml
@@ -1,7 +1,11 @@
-mysql:
+postgresql:
create: false
- endpoint: ${database_endpoint}
+ database: ${database_name}
+
+ endpoint:
+ host: ${database_endpoint_host}
+ port: "${database_endpoint_port}"
secret:
username: ${database_username}
diff --git a/deploy/terraform/lib/apprunner/orders.tf b/deploy/terraform/lib/apprunner/orders.tf
index ccedda7f1..cff7e73dc 100644
--- a/deploy/terraform/lib/apprunner/orders.tf
+++ b/deploy/terraform/lib/apprunner/orders.tf
@@ -1,21 +1,18 @@
resource "aws_apprunner_service" "orders" {
service_name = "${var.environment_name}-orders"
-
+
source_configuration {
auto_deployments_enabled = false
image_repository {
image_configuration {
port = 8080
runtime_environment_secrets = {
- SPRING_DATASOURCE_WRITER_URL = "${aws_secretsmanager_secret.orders_db.arn}:host::"
- SPRING_DATASOURCE_WRITER_USERNAME = "${aws_secretsmanager_secret.orders_db.arn}:username::"
- SPRING_DATASOURCE_WRITER_PASSWORD = "${aws_secretsmanager_secret.orders_db.arn}:password::"
- SPRING_DATASOURCE_READER_URL = "${aws_secretsmanager_secret.orders_db.arn}:host::"
- SPRING_DATASOURCE_READER_USERNAME = "${aws_secretsmanager_secret.orders_db.arn}:username::"
- SPRING_DATASOURCE_READER_PASSWORD = "${aws_secretsmanager_secret.orders_db.arn}:password::"
- SPRING_RABBITMQ_ADDRESSES = "${aws_secretsmanager_secret.mq.arn}:host::"
- SPRING_RABBITMQ_USER = "${aws_secretsmanager_secret.mq.arn}:username::"
- SPRING_RABBITMQ_PASSWORD = "${aws_secretsmanager_secret.mq.arn}:password::"
+ SPRING_DATASOURCE_URL = "${aws_secretsmanager_secret.orders_db.arn}:host::"
+ SPRING_DATASOURCE_USERNAME = "${aws_secretsmanager_secret.orders_db.arn}:username::"
+ SPRING_DATASOURCE_PASSWORD = "${aws_secretsmanager_secret.orders_db.arn}:password::"
+ SPRING_RABBITMQ_ADDRESSES = "${aws_secretsmanager_secret.mq.arn}:host::"
+ SPRING_RABBITMQ_USER = "${aws_secretsmanager_secret.mq.arn}:username::"
+ SPRING_RABBITMQ_PASSWORD = "${aws_secretsmanager_secret.mq.arn}:password::"
}
}
image_identifier = module.container_images.result.orders
@@ -59,8 +56,8 @@ resource "aws_apprunner_vpc_ingress_connection" "orders" {
}
resource "random_string" "random_orders_secret" {
- length = 4
- special = false
+ length = 4
+ special = false
}
resource "aws_secretsmanager_secret" "orders_db" {
@@ -106,7 +103,7 @@ data "aws_iam_policy_document" "orders_db_secret" {
"secretsmanager:GetSecretValue",
"kms:Decrypt*"
]
- effect = "Allow"
+ effect = "Allow"
resources = [
aws_secretsmanager_secret.orders_db.arn,
aws_secretsmanager_secret.mq.arn,
@@ -135,4 +132,4 @@ resource "aws_security_group" "orders" {
}
tags = var.tags
-}
\ No newline at end of file
+}
diff --git a/deploy/terraform/lib/dependencies/orders_rds.tf b/deploy/terraform/lib/dependencies/orders_rds.tf
index 219cbcfb6..95385a76a 100644
--- a/deploy/terraform/lib/dependencies/orders_rds.tf
+++ b/deploy/terraform/lib/dependencies/orders_rds.tf
@@ -2,16 +2,16 @@ module "orders_rds" {
source = "terraform-aws-modules/rds-aurora/aws"
version = "7.7.1"
- name = "${var.environment_name}-orders"
- engine = "aurora-mysql"
- engine_version = "5.7"
- instance_class = "db.t3.small"
+ name = "${var.environment_name}-orders"
+ engine = "aurora-postgresql"
+ engine_version = "15.5"
+ instance_class = "db.t3.medium"
instances = {
one = {}
}
- vpc_id = var.vpc_id
+ vpc_id = var.vpc_id
subnets = var.subnet_ids
allowed_security_groups = concat(var.allowed_security_group_ids, [var.orders_security_group_id])
@@ -25,16 +25,16 @@ module "orders_rds" {
create_db_parameter_group = true
db_parameter_group_name = "${var.environment_name}-orders"
- db_parameter_group_family = "aurora-mysql5.7"
+ db_parameter_group_family = "aurora-postgresql15"
create_db_cluster_parameter_group = true
db_cluster_parameter_group_name = "${var.environment_name}-orders"
- db_cluster_parameter_group_family = "aurora-mysql5.7"
+ db_cluster_parameter_group_family = "aurora-postgresql15"
- tags = var.tags
+ tags = var.tags
}
resource "random_string" "orders_db_master" {
length = 10
special = false
-}
\ No newline at end of file
+}
diff --git a/src/catalog/docker-compose.yml b/src/catalog/docker-compose.yml
index f456e9b40..704e20080 100644
--- a/src/catalog/docker-compose.yml
+++ b/src/catalog/docker-compose.yml
@@ -10,7 +10,7 @@ services:
image: microservices-demo/catalog
hostname: catalog
depends_on:
- - catalog-db
+ - catalog-db
restart: always
cap_drop:
- all
diff --git a/src/orders/docker-compose.yml b/src/orders/docker-compose.yml
index 4f5c7250c..0bb8d6af1 100644
--- a/src/orders/docker-compose.yml
+++ b/src/orders/docker-compose.yml
@@ -22,19 +22,19 @@ services:
environment:
- reschedule=on-node-failure
- SERVER_TOMCAT_ACCESSLOG_ENABLED=true
- - SPRING_PROFILES_ACTIVE=mysql,activemq
- - SPRING_DATASOURCE_WRITER_URL=jdbc:mysql://orders-db:3306/orders
- - SPRING_DATASOURCE_WRITER_USERNAME=orders_user
- - SPRING_DATASOURCE_WRITER_PASSWORD=${MYSQL_PASSWORD}
- - SPRING_DATASOURCE_READER_URL=jdbc:mysql://orders-db:3306/orders
- - SPRING_DATASOURCE_READER_USERNAME=orders_user
- - SPRING_DATASOURCE_READER_PASSWORD=${MYSQL_PASSWORD}
- - SPRING_DATASOURCE_WRITER_MAXIMUMPOOLSIZE=20
+ - SPRING_PROFILES_ACTIVE=rabbitmq
+ - SPRING_DATASOURCE_URL=jdbc:postgresql://orders-db:5432/orders
+ - SPRING_DATASOURCE_USERNAME=orders_user
+ - SPRING_DATASOURCE_PASSWORD=${MYSQL_PASSWORD}
- SPRING_RABBITMQ_HOST=rabbitmq
ports:
- "8083:8080"
healthcheck:
- test: ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1"]
+ test:
+ [
+ "CMD-SHELL",
+ "curl -f http://localhost:8080/actuator/health || exit 1"
+ ]
interval: 10s
timeout: 10s
retries: 3
@@ -42,24 +42,22 @@ services:
# nosemgrep: yaml.docker-compose.security.writable-filesystem-service.writable-filesystem-service
orders-db:
- image: mysql:5.7
+ image: postgres:16.1
hostname: orders-db
restart: always
security_opt:
- no-new-privileges:true
environment:
- reschedule=on-node-failure
- - MYSQL_ROOT_PASSWORD=${MYSQL_PASSWORD}
- - MYSQL_ALLOW_EMPTY_PASSWORD=true
- - MYSQL_DATABASE=orders
- - MYSQL_USER=orders_user
- - MYSQL_PASSWORD=${MYSQL_PASSWORD}
+ - POSTGRES_PASSWORD=${MYSQL_PASSWORD}
+ - POSTGRES_DB=orders
+ - POSTGRES_USER=orders_user
ports:
- - "3306:3306"
+ - "5432:5432"
healthcheck:
- test: ["CMD-SHELL", "mysql -u root -p${MYSQL_PASSWORD} -e 'SELECT 1 cache'"]
- interval: 1s
- timeout: 3s
+ test: [ "CMD-SHELL", "pg_isready -d orders -U orders_user" ]
+ interval: 10s
+ timeout: 5s
retries: 30
# nosemgrep: yaml.docker-compose.security.writable-filesystem-service.writable-filesystem-service
@@ -72,4 +70,3 @@ services:
ports:
- "61616:61616"
- "8161:8161"
-
diff --git a/src/orders/pom.xml b/src/orders/pom.xml
index 53831d97d..a834eeea1 100644
--- a/src/orders/pom.xml
+++ b/src/orders/pom.xml
@@ -1,176 +1,189 @@
- 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 3.2.1
-
-
- com.amazon.sample
- orders
- 0.0.1-SNAPSHOT
- orders
- Orders component
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.1
+
+
+ com.amazon.sample
+ orders
+ 0.0.1-SNAPSHOT
+ orders
+ Orders component
-
- 17
- 1.5.5.Final
-
+
+ 17
+ 1.5.5.Final
+
-
-
- org.springframework.boot
- spring-boot-starter-actuator
-
-
- org.springframework.boot
- spring-boot-starter-logging
-
-
-
-
- org.springframework.boot
- spring-boot-properties-migrator
- runtime
-
-
- org.springframework.boot
- spring-boot-starter-validation
- runtime
-
-
- io.micrometer
- micrometer-registry-prometheus
-
-
- org.springframework.boot
- spring-boot-starter-data-jpa
-
-
- org.mariadb.jdbc
- mariadb-java-client
- 3.3.2
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
- org.springframework.boot
- spring-boot-starter-logging
-
-
-
-
- org.springframework.boot
- spring-boot-starter-log4j2
-
-
- org.springframework.boot
- spring-boot-starter-amqp
-
-
- org.springdoc
- springdoc-openapi-ui
- 1.7.0
-
-
- com.fasterxml.jackson.core
- jackson-databind
- 2.16.1
-
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
+
+ org.springframework.boot
+ spring-boot-properties-migrator
+ runtime
+
+
+ io.micrometer
+ micrometer-registry-prometheus
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jdbc
+
+
+ org.flywaydb
+ flyway-core
+
+
+ org.postgresql
+ postgresql
+
+
+ org.testcontainers
+ junit-jupiter
+ test
+
+
+ org.testcontainers
+ postgresql
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-log4j2
+
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+
+
+ org.springdoc
+ springdoc-openapi-ui
+ 1.7.0
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.16.1
+
-
- org.mapstruct
- mapstruct
- ${mapstruct.version}
-
-
- org.mapstruct
- mapstruct-processor
- ${mapstruct.version}
- provided
-
+
+ org.mapstruct
+ mapstruct
+ ${mapstruct.version}
+
+
+ org.mapstruct
+ mapstruct-processor
+ ${mapstruct.version}
+ provided
+
-
- com.h2database
- h2
- runtime
-
-
- org.projectlombok
- lombok
- true
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
- org.junit.vintage
- junit-vintage-engine
-
-
-
-
+
+ com.h2database
+ h2
+ runtime
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+
+
+
+
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
- start
- stop
-
-
-
-
-
- org.springdoc
- springdoc-openapi-maven-plugin
- 1.4
-
-
- integration-test
-
- generate
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
- 3.12.1
-
-
- ${java.version}
-
-
- org.mapstruct
- mapstruct-processor
- ${mapstruct.version}
-
-
- org.projectlombok
- lombok-mapstruct-binding
- 0.2.0
-
-
- org.projectlombok
- lombok
- ${lombok.version}
-
-
-
-
-
-
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ start
+ stop
+
+
+
+
+
+ org.springdoc
+ springdoc-openapi-maven-plugin
+ 1.4
+
+
+ integration-test
+
+ generate
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.12.1
+
+
+ ${java.version}
+
+
+ org.mapstruct
+ mapstruct-processor
+ ${mapstruct.version}
+
+
+ org.projectlombok
+ lombok-mapstruct-binding
+ 0.2.0
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+
+
+
+
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/OrdersApplication.java b/src/orders/src/main/java/com/amazon/sample/orders/OrdersApplication.java
index 8ee07e6a3..159c3cc40 100644
--- a/src/orders/src/main/java/com/amazon/sample/orders/OrdersApplication.java
+++ b/src/orders/src/main/java/com/amazon/sample/orders/OrdersApplication.java
@@ -27,5 +27,4 @@ public class OrdersApplication {
public static void main(String[] args) {
SpringApplication.run(OrdersApplication.class, args);
}
-
}
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/config/PersistenceConfig.java b/src/orders/src/main/java/com/amazon/sample/orders/config/PersistenceConfig.java
new file mode 100644
index 000000000..2f5453d1a
--- /dev/null
+++ b/src/orders/src/main/java/com/amazon/sample/orders/config/PersistenceConfig.java
@@ -0,0 +1,35 @@
+package com.amazon.sample.orders.config;
+
+import com.amazon.sample.orders.entities.OrderEntity;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.jdbc.core.convert.JdbcCustomConversions;
+import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
+import org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration;
+import org.springframework.data.relational.RelationalManagedTypes;
+import org.springframework.data.relational.core.mapping.NamingStrategy;
+import org.springframework.data.relational.core.mapping.event.BeforeConvertCallback;
+
+import java.util.Optional;
+import java.util.UUID;
+
+@Configuration
+public class PersistenceConfig extends AbstractJdbcConfiguration {
+ @Bean
+ BeforeConvertCallback beforeSaveCallback() {
+ return (entity) -> {
+ if (entity.getId() == null) {
+ entity.setId(UUID.randomUUID().toString());
+ }
+ return entity;
+ };
+ }
+
+ @Override
+ public JdbcMappingContext jdbcMappingContext(Optional namingStrategy,
+ JdbcCustomConversions customConversions, RelationalManagedTypes jdbcManagedTypes) {
+ JdbcMappingContext context = super.jdbcMappingContext(namingStrategy, customConversions, jdbcManagedTypes);
+ context.setForceQuote(false);
+ return context;
+ }
+}
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/config/persistence/ReaderConfig.java b/src/orders/src/main/java/com/amazon/sample/orders/config/persistence/ReaderConfig.java
deleted file mode 100644
index 0acde1140..000000000
--- a/src/orders/src/main/java/com/amazon/sample/orders/config/persistence/ReaderConfig.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: MIT-0
- *
- * 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.
- *
- * 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.
- */
-
-package com.amazon.sample.orders.config.persistence;
-
-import com.amazon.sample.orders.repositories.ReadOnlyRepository;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.boot.jdbc.DataSourceBuilder;
-import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
-import org.springframework.context.annotation.*;
-import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
-import org.springframework.orm.jpa.JpaTransactionManager;
-import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.annotation.EnableTransactionManagement;
-
-import jakarta.persistence.EntityManagerFactory;
-import javax.sql.DataSource;
-
-@Configuration
-@Profile("mysql")
-@EnableTransactionManagement
-@EnableJpaRepositories(
- entityManagerFactoryRef = "readerEntityManagerFactory",
- transactionManagerRef = "readerTransactionManager",
- includeFilters = @ComponentScan.Filter(ReadOnlyRepository.class),
- basePackages = {
- "com.amazon.sample.orders"
- }
-)
-public class ReaderConfig {
-
- @Bean(name = "readerDataSource")
- @ConfigurationProperties(prefix = "spring.datasource.reader")
- public DataSource customerDataSource() {
- return DataSourceBuilder.create().build();
- }
-
- @Bean(name = "readerEntityManagerFactory")
- public LocalContainerEntityManagerFactoryBean
- entityManagerFactory(
- EntityManagerFactoryBuilder builder,
- @Qualifier("readerDataSource") DataSource dataSource
- ) {
- return builder
- .dataSource(dataSource)
- .packages("com.amazon.sample.orders")
- .persistenceUnit("reader")
- .build();
- }
-
- @Bean(name = "readerTransactionManager")
- public PlatformTransactionManager customerTransactionManager(
- @Qualifier("readerEntityManagerFactory") EntityManagerFactory customerEntityManagerFactory
- ) {
- return new JpaTransactionManager(customerEntityManagerFactory);
- }
-}
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/config/persistence/WriterConfig.java b/src/orders/src/main/java/com/amazon/sample/orders/config/persistence/WriterConfig.java
deleted file mode 100644
index 09d100bae..000000000
--- a/src/orders/src/main/java/com/amazon/sample/orders/config/persistence/WriterConfig.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: MIT-0
- *
- * 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.
- *
- * 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.
- */
-
-package com.amazon.sample.orders.config.persistence;
-
-import com.amazon.sample.orders.repositories.ReadOnlyRepository;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.boot.jdbc.DataSourceBuilder;
-import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
-import org.springframework.context.annotation.*;
-import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
-import org.springframework.orm.jpa.JpaTransactionManager;
-import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.annotation.EnableTransactionManagement;
-
-import jakarta.persistence.EntityManagerFactory;
-import javax.sql.DataSource;
-
-@Configuration
-@Profile("mysql")
-@EnableTransactionManagement
-@EnableJpaRepositories(
- entityManagerFactoryRef = "writerEntityManagerFactory",
- transactionManagerRef = "writerTransactionManager",
- excludeFilters = @ComponentScan.Filter(ReadOnlyRepository.class),
- basePackages = {
- "com.amazon.sample.orders"
- }
-)
-public class WriterConfig {
-
- @Primary
- @Bean(name = "writerDataSource")
- @ConfigurationProperties(prefix = "spring.datasource.writer")
- public DataSource customerDataSource() {
- return DataSourceBuilder.create().build();
- }
-
- @Primary
- @Bean(name = "writerEntityManagerFactory")
- public LocalContainerEntityManagerFactoryBean
- entityManagerFactory(
- EntityManagerFactoryBuilder builder,
- @Qualifier("writerDataSource") DataSource dataSource
- ) {
- return builder
- .dataSource(dataSource)
- .packages("com.amazon.sample.orders")
- .persistenceUnit("writer")
- .build();
- }
-
- @Primary
- @Bean(name = "writerTransactionManager")
- public PlatformTransactionManager writerTransactionManager(
- @Qualifier("writerEntityManagerFactory") EntityManagerFactory writerEntityManagerFactory
- ) {
- return new JpaTransactionManager(writerEntityManagerFactory);
- }
-}
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/entities/OrderEntity.java b/src/orders/src/main/java/com/amazon/sample/orders/entities/OrderEntity.java
index 668d8d31e..04c652eab 100644
--- a/src/orders/src/main/java/com/amazon/sample/orders/entities/OrderEntity.java
+++ b/src/orders/src/main/java/com/amazon/sample/orders/entities/OrderEntity.java
@@ -18,30 +18,88 @@
package com.amazon.sample.orders.entities;
-import lombok.Data;
-import org.hibernate.annotations.GenericGenerator;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.relational.core.mapping.MappedCollection;
+import org.springframework.data.relational.core.mapping.Table;
-import jakarta.persistence.*;
import java.util.ArrayList;
import java.util.List;
-@Entity
-@Table(name="CUSTOMER_ORDER")
-@Data
+@Table
public class OrderEntity {
-
@Id
- @GeneratedValue(generator = "uuid")
- @GenericGenerator(name = "uuid", strategy = "uuid2")
private String id;
private String firstName;
private String lastName;
private String email;
- @OneToMany(
- mappedBy = "order",
- orphanRemoval = true,
- fetch = FetchType.EAGER
- )
+ @MappedCollection(keyColumn = "product_id")
private List items = new ArrayList<>();
+
+ public OrderEntity() {
+
+ }
+
+ public OrderEntity(String firstName, String lastName, String email) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.email = email;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public List getItems() {
+ return items;
+ }
+
+ public void setItems(List items) {
+ this.items = items;
+ }
+
+ public OrderEntity addItem(OrderItemEntity item) {
+ this.items.add(item);
+
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "OrderEntity{" +
+ "id='" + id + '\'' +
+ ", firstName='" + firstName + '\'' +
+ ", lastName='" + lastName + '\'' +
+ ", email='" + email + '\'' +
+ ", items=" + items +
+ '}';
+ }
}
\ No newline at end of file
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/entities/OrderItemEntity.java b/src/orders/src/main/java/com/amazon/sample/orders/entities/OrderItemEntity.java
index 329c6f366..dc921c7c2 100644
--- a/src/orders/src/main/java/com/amazon/sample/orders/entities/OrderItemEntity.java
+++ b/src/orders/src/main/java/com/amazon/sample/orders/entities/OrderItemEntity.java
@@ -18,42 +18,69 @@
package com.amazon.sample.orders.entities;
-import lombok.Data;
+import org.springframework.data.relational.core.mapping.Table;
-import jakarta.persistence.*;
-import java.io.Serializable;
-
-@Entity
-@Table(name="CUSTOMER_ORDER_ITEM")
-@Data
+@Table
public class OrderItemEntity {
- @Embeddable
- @Data
- public static class Key implements Serializable {
- private String orderId;
- private String productId;
- }
-
- @EmbeddedId
- @AttributeOverrides({
- @AttributeOverride(name="productId",
- column=@Column(length=64))
- })
- private Key id;
- @Transient
private String productId;
private int quantity;
- private int price;
+ private int unitCost;
private String name;
private int totalCost;
- @ManyToOne(fetch = FetchType.LAZY)
- @MapsId("orderId")
+ public String getProductId() {
+ return productId;
+ }
+
+ public void setProductId(String productId) {
+ this.productId = productId;
+ }
+
+ public int getQuantity() {
+ return quantity;
+ }
+
+ public void setQuantity(int quantity) {
+ this.quantity = quantity;
+ }
+
+ public int getUnitCost() {
+ return unitCost;
+ }
- private OrderEntity order;
+ public void setUnitCost(int unitCost) {
+ this.unitCost = unitCost;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getTotalCost() {
+ return totalCost;
+ }
+
+ public void setTotalCost(int totalCost) {
+ this.totalCost = totalCost;
+ }
+
+ @Override
+ public String toString() {
+ return "OrderItemEntity{" +
+ ", productId='" + productId + '\'' +
+ ", quantity=" + quantity +
+ ", unitCost=" + unitCost +
+ ", name='" + name + '\'' +
+ ", totalCost=" + totalCost +
+ '}';
+ }
}
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/messaging/OrdersEventHandler.java b/src/orders/src/main/java/com/amazon/sample/orders/messaging/OrdersEventHandler.java
index 35e2a6fd5..a7feed46c 100644
--- a/src/orders/src/main/java/com/amazon/sample/orders/messaging/OrdersEventHandler.java
+++ b/src/orders/src/main/java/com/amazon/sample/orders/messaging/OrdersEventHandler.java
@@ -47,7 +47,7 @@ public void postCreatedEvent(OrderEntity entity) {
order.setFirstName(entity.getFirstName());
order.setLastName(entity.getLastName());
order.setEmail(entity.getEmail());
- order.setOrderItems(entity.getItems());
+ order.setOrderItems(entity.getItems().stream().toList());
OrderCreatedEvent event = new OrderCreatedEvent();
event.setOrder(order);
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/metrics/OrdersMetrics.java b/src/orders/src/main/java/com/amazon/sample/orders/metrics/OrdersMetrics.java
index 4b4f6af54..a8b18c2b8 100644
--- a/src/orders/src/main/java/com/amazon/sample/orders/metrics/OrdersMetrics.java
+++ b/src/orders/src/main/java/com/amazon/sample/orders/metrics/OrdersMetrics.java
@@ -21,7 +21,6 @@
import com.amazon.sample.events.orders.OrderCreatedEvent;
import com.amazon.sample.orders.entities.OrderItemEntity;
import io.micrometer.core.instrument.Counter;
-import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/repositories/OrderReadRepository.java b/src/orders/src/main/java/com/amazon/sample/orders/repositories/OrderReadRepository.java
deleted file mode 100644
index 80654179e..000000000
--- a/src/orders/src/main/java/com/amazon/sample/orders/repositories/OrderReadRepository.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: MIT-0
- *
- * 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.
- *
- * 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.
- */
-
-package com.amazon.sample.orders.repositories;
-
-import com.amazon.sample.orders.entities.OrderEntity;
-import org.springframework.data.repository.CrudRepository;
-
-@ReadOnlyRepository
-public interface OrderReadRepository extends CrudRepository {
-
-}
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/repositories/OrderRepository.java b/src/orders/src/main/java/com/amazon/sample/orders/repositories/OrderRepository.java
index b40bd6278..d53eb2245 100644
--- a/src/orders/src/main/java/com/amazon/sample/orders/repositories/OrderRepository.java
+++ b/src/orders/src/main/java/com/amazon/sample/orders/repositories/OrderRepository.java
@@ -20,7 +20,9 @@
import com.amazon.sample.orders.entities.OrderEntity;
import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+@Repository
public interface OrderRepository extends CrudRepository {
}
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/repositories/ReadOnlyRepository.java b/src/orders/src/main/java/com/amazon/sample/orders/repositories/ReadOnlyRepository.java
deleted file mode 100644
index 0589ece65..000000000
--- a/src/orders/src/main/java/com/amazon/sample/orders/repositories/ReadOnlyRepository.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: MIT-0
- *
- * 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.
- *
- * 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.
- */
-
-package com.amazon.sample.orders.repositories;
-
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE})
-@Documented
-public @interface ReadOnlyRepository {
-}
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/services/OrderService.java b/src/orders/src/main/java/com/amazon/sample/orders/services/OrderService.java
index 13d0b8d2d..6b32acb87 100644
--- a/src/orders/src/main/java/com/amazon/sample/orders/services/OrderService.java
+++ b/src/orders/src/main/java/com/amazon/sample/orders/services/OrderService.java
@@ -19,52 +19,42 @@
package com.amazon.sample.orders.services;
import com.amazon.sample.orders.entities.OrderEntity;
-import com.amazon.sample.orders.entities.OrderItemEntity;
import com.amazon.sample.orders.messaging.OrdersEventHandler;
-import com.amazon.sample.orders.repositories.OrderReadRepository;
import com.amazon.sample.orders.repositories.OrderRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.relational.core.mapping.event.AbstractRelationalEventListener;
+import org.springframework.data.relational.core.mapping.event.AfterSaveEvent;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
-import jakarta.transaction.Transactional;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
@Service
@Slf4j
-public class OrderService {
+public class OrderService extends AbstractRelationalEventListener {
@Autowired
private OrderRepository repository;
- @Autowired
- private OrderReadRepository readRepository;
-
@Autowired
private OrdersEventHandler eventHandler;
@Transactional
public OrderEntity create(OrderEntity order) {
- for(OrderItemEntity item : order.getItems()) {
- item.setOrder(order);
-
- OrderItemEntity.Key key = new OrderItemEntity.Key();
- //key.setProductId(item.getProductId());
-
- item.setId(key);
- }
-
OrderEntity entity = repository.save(order);
- eventHandler.postCreatedEvent(entity);
-
return entity;
}
public List list() {
- return StreamSupport.stream(this.readRepository.findAll().spliterator(), false)
- .collect(Collectors.toList());
+ return StreamSupport.stream(this.repository.findAll().spliterator(), false)
+ .collect(Collectors.toList());
+ }
+
+ protected void onAfterSave(AfterSaveEvent orderCreated) {
+ this.eventHandler.postCreatedEvent(orderCreated.getEntity());
}
}
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/web/OrderController.java b/src/orders/src/main/java/com/amazon/sample/orders/web/OrderController.java
index c3959c7aa..cedcc1194 100644
--- a/src/orders/src/main/java/com/amazon/sample/orders/web/OrderController.java
+++ b/src/orders/src/main/java/com/amazon/sample/orders/web/OrderController.java
@@ -18,6 +18,7 @@
package com.amazon.sample.orders.web;
+import com.amazon.sample.orders.entities.OrderEntity;
import com.amazon.sample.orders.services.OrderService;
import com.amazon.sample.orders.web.payload.*;
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/web/payload/Order.java b/src/orders/src/main/java/com/amazon/sample/orders/web/payload/Order.java
index 50e4d9c81..9a13925f2 100644
--- a/src/orders/src/main/java/com/amazon/sample/orders/web/payload/Order.java
+++ b/src/orders/src/main/java/com/amazon/sample/orders/web/payload/Order.java
@@ -21,6 +21,7 @@
import lombok.Data;
import java.util.List;
+import java.util.Set;
@Data
public class Order {
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/web/payload/OrderItemMapper.java b/src/orders/src/main/java/com/amazon/sample/orders/web/payload/OrderItemMapper.java
new file mode 100644
index 000000000..a9fa1c836
--- /dev/null
+++ b/src/orders/src/main/java/com/amazon/sample/orders/web/payload/OrderItemMapper.java
@@ -0,0 +1,12 @@
+package com.amazon.sample.orders.web.payload;
+
+import com.amazon.sample.orders.entities.OrderItemEntity;
+import org.mapstruct.Mapper;
+
+@Mapper(componentModel = "spring")
+public interface OrderItemMapper {
+
+ OrderItem toOrderItem(OrderItemEntity entity);
+
+ OrderItemEntity toOrderItemEntity(OrderItem item);
+}
diff --git a/src/orders/src/main/java/com/amazon/sample/orders/web/payload/OrderMapper.java b/src/orders/src/main/java/com/amazon/sample/orders/web/payload/OrderMapper.java
index d0e9c876c..e796f6bb3 100644
--- a/src/orders/src/main/java/com/amazon/sample/orders/web/payload/OrderMapper.java
+++ b/src/orders/src/main/java/com/amazon/sample/orders/web/payload/OrderMapper.java
@@ -22,15 +22,11 @@
import com.amazon.sample.orders.entities.OrderItemEntity;
import org.mapstruct.Mapper;
-@Mapper(componentModel = "spring")
+@Mapper(componentModel = "spring", uses = OrderItemMapper.class)
public interface OrderMapper {
- Order toOrder(OrderEntity entity);
-
- OrderItem toOrderItem(OrderItemEntity entity);
ExistingOrder toExistingOrder(OrderEntity entity);
OrderEntity toOrderEntity(Order order);
-
- OrderItemEntity toOrderItemEntity(OrderItem item);
}
+
diff --git a/src/orders/src/main/resources/application-mysql.yml b/src/orders/src/main/resources/application-mysql.yml
deleted file mode 100644
index 7a5208999..000000000
--- a/src/orders/src/main/resources/application-mysql.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-spring:
- jpa:
- generate-ddl: true
- show-sql: false
- hibernate:
- ddl-auto: update
-
- datasource:
- writer:
- jdbc-url: ${spring.datasource.writer.url}
- username:
- password:
- driverClassName: org.mariadb.jdbc.Driver
-
- reader:
- jdbc-url: ${spring.datasource.reader.url}
- username:
- password:
- driverClassName: org.mariadb.jdbc.Driver
\ No newline at end of file
diff --git a/src/orders/src/main/resources/application.yml b/src/orders/src/main/resources/application.yml
index b59a3fef9..98b6b50a1 100644
--- a/src/orders/src/main/resources/application.yml
+++ b/src/orders/src/main/resources/application.yml
@@ -5,4 +5,6 @@ management:
include: '*'
server:
- port: ${port:8080}
\ No newline at end of file
+ port: ${port:8080}
+
+spring.flyway.baseline-on-migrate: true
\ No newline at end of file
diff --git a/src/orders/src/main/resources/db/migration/V1__Initial.sql b/src/orders/src/main/resources/db/migration/V1__Initial.sql
new file mode 100644
index 000000000..8b6f020da
--- /dev/null
+++ b/src/orders/src/main/resources/db/migration/V1__Initial.sql
@@ -0,0 +1,16 @@
+create table IF NOT EXISTS order_entity (
+ id varchar(255) not null,
+ first_name varchar(255) not null,
+ last_name varchar(255),
+ email varchar(255),
+ primary key (id)
+);
+
+create table IF NOT EXISTS order_item_entity (
+ product_id varchar(255) not null,
+ name varchar(255) not null,
+ quantity int,
+ unit_cost int,
+ total_cost int,
+ order_entity varchar(255) not null
+);
\ No newline at end of file
diff --git a/src/orders/src/test/java/com/amazon/sample/orders/metrics/OrdersMetricsTest.java b/src/orders/src/test/java/com/amazon/sample/orders/metrics/OrdersMetricsTests.java
similarity index 90%
rename from src/orders/src/test/java/com/amazon/sample/orders/metrics/OrdersMetricsTest.java
rename to src/orders/src/test/java/com/amazon/sample/orders/metrics/OrdersMetricsTests.java
index bf5d245f7..ea499d18d 100644
--- a/src/orders/src/test/java/com/amazon/sample/orders/metrics/OrdersMetricsTest.java
+++ b/src/orders/src/test/java/com/amazon/sample/orders/metrics/OrdersMetricsTests.java
@@ -26,22 +26,18 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.event.TransactionalEventListener;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
import static org.assertj.core.api.BDDAssertions.then;
-
-public class OrdersMetricsTest {
+public class OrdersMetricsTests {
private MeterRegistry meterRegistry;
private final String PRODUCT_1 = "Product1";
private final String PRODUCT_2 = "Product2";
+
@BeforeEach
void setUp() {
meterRegistry = new SimpleMeterRegistry();
@@ -69,14 +65,14 @@ void testCreateCounterAndIncrement() {
OrderItemEntity item = new OrderItemEntity();
item.setName("Pocket Watch");
item.setQuantity(5);
- item.setPrice(100);
+ item.setUnitCost(100);
item.setTotalCost(500);
item.setProductId(PRODUCT_1);
orderItems.add(item);
item = new OrderItemEntity();
item.setName("Wood Watch");
item.setQuantity(2);
- item.setPrice(50);
+ item.setUnitCost(50);
item.setTotalCost(100);
item.setProductId(PRODUCT_2);
orderItems.add(item);
@@ -85,15 +81,15 @@ void testCreateCounterAndIncrement() {
event.setOrder(order);
ordersMetrics.onOrderCreated(event);
- var counter = meterRegistry.get("watch.orders").tags("productId","*").counter();
+ var counter = meterRegistry.get("watch.orders").tags("productId", "*").counter();
then(counter).isNotNull();
then(counter.count()).isEqualTo(1);
- var woodWatchCounter = meterRegistry.get("watch.orders").tags("productId",PRODUCT_2).counter();
+ var woodWatchCounter = meterRegistry.get("watch.orders").tags("productId", PRODUCT_2).counter();
then(woodWatchCounter).isNotNull();
then(woodWatchCounter.count()).isEqualTo(2);
- var pocketWatchCounter = meterRegistry.get("watch.orders").tags("productId",PRODUCT_1).counter();
+ var pocketWatchCounter = meterRegistry.get("watch.orders").tags("productId", PRODUCT_1).counter();
then(pocketWatchCounter).isNotNull();
then(pocketWatchCounter.count()).isEqualTo(5);
diff --git a/src/orders/src/test/java/com/amazon/sample/orders/services/OrderServicePostgresTests.java b/src/orders/src/test/java/com/amazon/sample/orders/services/OrderServicePostgresTests.java
new file mode 100644
index 000000000..246e69317
--- /dev/null
+++ b/src/orders/src/test/java/com/amazon/sample/orders/services/OrderServicePostgresTests.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: MIT-0
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+package com.amazon.sample.orders.services;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.hasSize;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.server.LocalServerPort;
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
+import org.testcontainers.containers.PostgreSQLContainer;
+
+import com.amazon.sample.orders.entities.OrderEntity;
+import com.amazon.sample.orders.repositories.OrderRepository;
+
+import io.restassured.RestAssured;
+import io.restassured.http.ContentType;
+
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class OrderServicePostgresTests {
+
+ @LocalServerPort
+ private Integer port;
+
+ static PostgreSQLContainer> postgres = new PostgreSQLContainer<>(
+ "postgres:16.1");
+
+ @BeforeAll
+ static void beforeAll() {
+ postgres.start();
+ }
+
+ @AfterAll
+ static void afterAll() {
+ postgres.stop();
+ }
+
+ @DynamicPropertySource
+ static void configureProperties(DynamicPropertyRegistry registry) {
+ registry.add("spring.datasource.url", postgres::getJdbcUrl);
+ registry.add("spring.datasource.username", postgres::getUsername);
+ registry.add("spring.datasource.password", postgres::getPassword);
+ }
+
+ @Autowired
+ OrderRepository orderRepository;
+
+ @BeforeEach
+ void setUp() {
+ RestAssured.baseURI = "http://localhost:" + port;
+ orderRepository.deleteAll();
+ }
+
+ @Test
+ void shouldGetEmptyOrders() {
+ given()
+ .contentType(ContentType.JSON)
+ .when()
+ .get("/orders")
+ .then()
+ .statusCode(200)
+ .body(".", hasSize(0));
+ }
+
+ @Test
+ void shouldGetAllOrders() {
+ List orders = List.of(
+ new OrderEntity("first", "last", "email@example.com"),
+ new OrderEntity("first", "last", "email@example.com"));
+ orderRepository.saveAll(orders);
+
+ given()
+ .contentType(ContentType.JSON)
+ .when()
+ .get("/orders")
+ .then()
+ .statusCode(200)
+ .body(".", hasSize(2));
+ }
+}
\ No newline at end of file