1. Project setup#
The thinxar/clinic reference service uses plain Groovy Gradle with dependency versions hoisted into a sibling deps.gradle. This keeps version bumps to one file and avoids drift between the Palmyra core artifact and its extensions.
Prerequisites#
- Java 21+
- Gradle 8.x
- MariaDB / MySQL / PostgreSQL / Oracle / DB2
Layout#
service/
build.gradle
deps.gradle ← versions + dependency bundles
settings.gradle
src/main/java/... com.your.app.AppMain, controller/, entity/, model/, pojo/, handler/, ...
src/main/resources/application.yamldeps.gradle#
Centralise versions and pre-compose reusable dependency bundles:
def versions = [
spring_boot : '3.3.4',
palmyra : '1.4.4',
mariadb : '3.4.0',
lombok : '1.18.34'
]
def palmyra = [
spring : "com.palmyralabs.palmyra:palmyra-spring:${versions.palmyra}",
extn : [
pwdmgmt : "com.palmyralabs.palmyra.extn:palmyra-dbpwd-mgmt:${versions.palmyra}",
aclmgmt : "com.palmyralabs.palmyra.extn:palmyra-dbacl-mgmt:${versions.palmyra}"
]
]
ext {
versions = versions
palmyra = palmyra
}build.gradle#
plugins {
id 'org.springframework.boot' version '3.3.4'
id 'io.spring.dependency-management' version '1.1.6'
id 'java'
id 'application'
}
apply from: 'deps.gradle'
java { toolchain { languageVersion = JavaLanguageVersion.of(21) } }
application { mainClass = 'com.your.app.AppMain' }
repositories {
mavenLocal()
mavenCentral()
maven { url 'https://repo.palmyralabs.com/releases' }
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation palmyra.spring
implementation palmyra.extn.pwdmgmt
implementation palmyra.extn.aclmgmt
compileOnly "org.projectlombok:lombok:${versions.lombok}"
annotationProcessor "org.projectlombok:lombok:${versions.lombok}"
runtimeOnly "org.mariadb.jdbc:mariadb-java-client:${versions.mariadb}"
}settings.gradle#
rootProject.name = 'your-app'SpringBoot entrypoint#
Import PalmyraSpringConfiguration and enable JPA repositories / entity scanning alongside it. Palmyra and JPA coexist — JPA handles entities you own end-to-end; Palmyra publishes a thin CRUD API over the same schema.
package com.your.app;
@SpringBootApplication
@Import(PalmyraSpringConfiguration.class)
@EnableJpaRepositories
@EntityScan
public class AppMain {
public static void main(String[] args) {
SpringApplication.run(AppMain.class, args);
}
}application.yaml#
spring:
jpa:
show-sql: true
hibernate:
ddl-auto: validate # never 'update' in prod — migrations own the schema
datasource:
url: jdbc:mariadb://localhost:3306/clinic
username: dbuser
password: dbuser
driverClassName: org.mariadb.jdbc.Driver
server:
port: 8080
servlet:
context-path: /api # every handler mounts under /api/...Run ./gradlew bootRun. The app boots on :8080 with the /api context path; the next steps add the entities, models, and handlers that make it answer actual requests.