Skip to content

Commit aec5597

Browse files
committed
feat(sap-demo-java): add MySQL 8 Spring profile alongside Postgres
Split the datasource configuration into two Spring profiles so the Customer 360 service can run against either Postgres (default) or MySQL 8 with a runtime toggle — no rebuild, no code change, no @Profile annotations on business logic. - application.yml now keeps only the portable bits (connection pool, JPA, cache, Flyway base settings) and pins spring.profiles.active=${SPRING_PROFILES_ACTIVE:postgres} so env overrides win. Existing SPRING_DATASOURCE_URL / _USERNAME / _PASSWORD env overrides keep working for both profiles. - application-postgres.yml (new) — Postgres JDBC URL template, org.postgresql.Driver, PostgreSQLDialect, Flyway classpath:db/migration/postgres. Values match the previous application.yml exactly, so current users see no change. - application-mysql.yml (new) — MySQL JDBC URL template with useSSL=false, allowPublicKeyRetrieval=true and serverTimezone=UTC so TIMESTAMP columns round-trip against Hibernate's jdbc.time_zone=UTC; com.mysql.cj.jdbc.Driver, MySQLDialect, Flyway classpath:db/migration/mysql. - Flyway migrations split into db/migration/postgres (V1 moved verbatim — content unchanged) and db/migration/mysql (new dialect-equivalent DDL: BIGINT AUTO_INCREMENT, TIMESTAMP + CURRENT_TIMESTAMP, utf8mb4/InnoDB, parity indexes). - pom.xml adds mysql-connector-j and flyway-mysql at runtime scope, both managed by the Spring Boot 3.3.4 BOM (no explicit versions). Postgres dependencies are untouched. Signed-off-by: slayerjain <shubhamkjain@outlook.com>
1 parent fa83929 commit aec5597

6 files changed

Lines changed: 128 additions & 8 deletions

File tree

sap-demo-java/pom.xml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,11 @@
6666
<artifactId>caffeine</artifactId>
6767
</dependency>
6868

69-
<!-- Persistence: JPA + Postgres + Flyway migrations -->
69+
<!-- Persistence: JPA + (Postgres | MySQL) + Flyway migrations.
70+
Both drivers ship at runtime scope; the active Spring profile
71+
(postgres | mysql) picks the one Spring Boot wires into the
72+
DataSource. Keeping both on the classpath keeps the image
73+
portable across the two backends with no rebuild. -->
7074
<dependency>
7175
<groupId>org.springframework.boot</groupId>
7276
<artifactId>spring-boot-starter-data-jpa</artifactId>
@@ -76,6 +80,11 @@
7680
<artifactId>postgresql</artifactId>
7781
<scope>runtime</scope>
7882
</dependency>
83+
<dependency>
84+
<groupId>com.mysql</groupId>
85+
<artifactId>mysql-connector-j</artifactId>
86+
<scope>runtime</scope>
87+
</dependency>
7988
<dependency>
8089
<groupId>org.flywaydb</groupId>
8190
<artifactId>flyway-core</artifactId>
@@ -84,6 +93,10 @@
8493
<groupId>org.flywaydb</groupId>
8594
<artifactId>flyway-database-postgresql</artifactId>
8695
</dependency>
96+
<dependency>
97+
<groupId>org.flywaydb</groupId>
98+
<artifactId>flyway-mysql</artifactId>
99+
</dependency>
87100

88101
<!-- Observability: health, metrics, info -->
89102
<dependency>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# MySQL 8 profile.
2+
#
3+
# Activated when SPRING_PROFILES_ACTIVE=mysql. All connection-pool, JPA
4+
# and cache settings are shared with the Postgres profile in
5+
# application.yml; only the dialect-specific bits live here.
6+
#
7+
# Docker compose brings up a matching mysql:8.0 service under the
8+
# "mysql" compose profile:
9+
# docker compose --profile mysql up -d mysql customer360
10+
#
11+
# URL parameters explained:
12+
# useSSL=false — local demo; flip to true behind RISE/BTP
13+
# allowPublicKeyRetrieval — required for caching_sha2_password auth
14+
# over a first-contact (non-TLS) socket
15+
# serverTimezone=UTC — match Hibernate's jdbc.time_zone=UTC so
16+
# TIMESTAMP columns round-trip cleanly
17+
spring:
18+
datasource:
19+
url: ${SPRING_DATASOURCE_URL:jdbc:mysql://localhost:3306/customer360?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC}
20+
driver-class-name: com.mysql.cj.jdbc.Driver
21+
jpa:
22+
database-platform: org.hibernate.dialect.MySQLDialect
23+
flyway:
24+
locations: classpath:db/migration/mysql
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Postgres profile — the default.
2+
#
3+
# Activated when SPRING_PROFILES_ACTIVE is unset or "postgres". All
4+
# connection-pool, JPA and cache settings are in application.yml;
5+
# only the dialect-specific bits live here.
6+
#
7+
# The public sandbox/demo uses stock Postgres 16, which Keploy's OSS
8+
# core records and replays at the wire-protocol level. In a
9+
# RISE/BTP landscape this is typically a hyperscaler-hosted Postgres
10+
# (RDS, Azure DB, Cloud SQL) or SAP HANA Cloud — swap the URL via
11+
# SPRING_DATASOURCE_URL and the driver stays the same.
12+
spring:
13+
datasource:
14+
url: ${SPRING_DATASOURCE_URL:jdbc:postgresql://localhost:5432/customer360}
15+
driver-class-name: org.postgresql.Driver
16+
jpa:
17+
database-platform: org.hibernate.dialect.PostgreSQLDialect
18+
flyway:
19+
locations: classpath:db/migration/postgres

sap-demo-java/src/main/resources/application.yml

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,21 @@ spring:
66
serialization:
77
write-dates-as-timestamps: false
88

9-
# --- Postgres / JPA ----------------------------------------------------
10-
# The app persists tags, notes, and an audit log locally. In a RISE/BTP
11-
# landscape this would be a hyperscaler-hosted Postgres or SAP HANA Cloud;
12-
# for the demo we use stock Postgres, which Keploy's OSS core can record
13-
# and replay at the wire-protocol level.
9+
# ----------------------------------------------------------------------
10+
# Datasource backend is profile-selected.
11+
# Default is Postgres (application-postgres.yml); set
12+
# SPRING_PROFILES_ACTIVE=mysql
13+
# to swap to MySQL 8 (application-mysql.yml). Both profiles honour the
14+
# standard SPRING_DATASOURCE_URL / _USERNAME / _PASSWORD env overrides.
15+
# ----------------------------------------------------------------------
16+
profiles:
17+
active: ${SPRING_PROFILES_ACTIVE:postgres}
18+
19+
# --- Connection pool + JPA (shared across DB profiles) ----------------
20+
# Driver class, JDBC URL template, Hibernate dialect and Flyway location
21+
# come from the profile-specific YAML (application-postgres.yml or
22+
# application-mysql.yml). Everything below is portable.
1423
datasource:
15-
url: ${SPRING_DATASOURCE_URL:jdbc:postgresql://localhost:5432/customer360}
1624
username: ${SPRING_DATASOURCE_USERNAME:customer360}
1725
password: ${SPRING_DATASOURCE_PASSWORD:customer360}
1826
hikari:
@@ -32,7 +40,6 @@ spring:
3240
flyway:
3341
enabled: true
3442
baseline-on-migrate: true
35-
locations: classpath:db/migration
3643

3744
# --- Cache -----------------------------------------------------------
3845
# Caffeine-backed caches for SAP master data. Typical BTP-extension
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
-- Customer 360 local schema — MySQL 8 dialect.
2+
--
3+
-- Functional twin of db/migration/postgres/V1__init_schema.sql. The app is
4+
-- a BTP-style extension: it enriches SAP Business Partner master data with
5+
-- local-only concerns (tags, free-text notes, access audit log) that never
6+
-- touch SAP. This separation is the "clean core" pattern — local deltas
7+
-- live here; SAP stays canonical for master data.
8+
--
9+
-- Differences from the Postgres variant are dialect-only:
10+
-- * BIGSERIAL -> BIGINT AUTO_INCREMENT
11+
-- * TIMESTAMPTZ -> TIMESTAMP (stored UTC; see Hibernate
12+
-- jdbc.time_zone=UTC in application.yml)
13+
-- * TEXT -> TEXT (MySQL TEXT == up to 65 535 bytes,
14+
-- plenty for a note body; switch to
15+
-- MEDIUMTEXT if you expect longer)
16+
-- * NOW() -> CURRENT_TIMESTAMP
17+
-- * DESC index on happened_at expressed via a plain index — MySQL 8
18+
-- accepts the DESC qualifier on B-tree indexes, and it is retained for
19+
-- parity with the Postgres schema.
20+
--
21+
-- Tables:
22+
-- customer_tag — user-assigned labels on a BP ("vip", "delinquent", etc.)
23+
-- customer_note — free-text notes captured by CSRs during calls
24+
-- audit_event — every read/write, for compliance + usage analytics
25+
26+
CREATE TABLE customer_tag (
27+
id BIGINT NOT NULL AUTO_INCREMENT,
28+
customer_id VARCHAR(10) NOT NULL,
29+
tag VARCHAR(64) NOT NULL,
30+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
31+
created_by VARCHAR(64) NOT NULL DEFAULT 'system',
32+
PRIMARY KEY (id),
33+
CONSTRAINT uk_customer_tag UNIQUE (customer_id, tag)
34+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
35+
CREATE INDEX idx_customer_tag_customer_id ON customer_tag(customer_id);
36+
37+
CREATE TABLE customer_note (
38+
id BIGINT NOT NULL AUTO_INCREMENT,
39+
customer_id VARCHAR(10) NOT NULL,
40+
body TEXT NOT NULL,
41+
author VARCHAR(64) NOT NULL DEFAULT 'system',
42+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
43+
PRIMARY KEY (id)
44+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
45+
CREATE INDEX idx_customer_note_customer_id ON customer_note(customer_id);
46+
47+
CREATE TABLE audit_event (
48+
id BIGINT NOT NULL AUTO_INCREMENT,
49+
customer_id VARCHAR(10),
50+
operation VARCHAR(64) NOT NULL,
51+
correlation_id VARCHAR(128),
52+
latency_ms INTEGER,
53+
happened_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
54+
PRIMARY KEY (id)
55+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
56+
CREATE INDEX idx_audit_event_happened_at ON audit_event(happened_at DESC);
57+
CREATE INDEX idx_audit_event_customer_id ON audit_event(customer_id);

sap-demo-java/src/main/resources/db/migration/V1__init_schema.sql renamed to sap-demo-java/src/main/resources/db/migration/postgres/V1__init_schema.sql

File renamed without changes.

0 commit comments

Comments
 (0)