1. Project setup#
What this step does. Starts a plain SpringBoot project, adds one Palmyra dependency, configures a database, and creates two empty tables. No Palmyra-specific code runs yet — that lands in steps 2 and 3.
build.gradle#
plugins {
id 'org.springframework.boot' version '3.3.4'
id 'io.spring.dependency-management' version '1.1.6'
id 'java'
id 'application'
}
java { toolchain { languageVersion = JavaLanguageVersion.of(21) } }
application { mainClass = 'com.example.empmgmt.AppMain' }
repositories {
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 'com.palmyralabs.palmyra:palmyra-spring:1.4.4'
compileOnly 'org.projectlombok:lombok:1.18.34'
annotationProcessor 'org.projectlombok:lombok:1.18.34'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client:3.4.0'
}SpringBoot entrypoint#
package com.example.empmgmt;
@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 }
datasource:
url: jdbc:mariadb://localhost:3306/empmgmt
username: empmgmt
password: empmgmt
driverClassName: org.mariadb.jdbc.Driver
server:
port: 8080
servlet: { context-path: /api }Database tables#
CREATE TABLE department (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(32) NOT NULL UNIQUE,
name VARCHAR(128) NOT NULL,
description VARCHAR(512)
);
CREATE TABLE employee (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
login_name VARCHAR(128) NOT NULL UNIQUE,
first_name VARCHAR(64) NOT NULL,
last_name VARCHAR(64) NOT NULL,
department_id BIGINT NOT NULL,
joining_date DATE NOT NULL,
status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
CONSTRAINT fk_employee_department FOREIGN KEY (department_id) REFERENCES department(id)
);Run ./gradlew bootRun. The app should boot on :8080 with context path /api. Nothing answers yet — we add models and handlers next.
Source layout#
src/main/java/com/example/empmgmt/
AppMain.java
entity/
DepartmentEntity.java
EmployeeEntity.java
model/
DepartmentModel.java
EmployeeModel.java
handler/
DepartmentHandler.java
EmployeeHandler.javaSame three-file split as the clinic reference (JPA entity, Palmyra model, handler). If you only want Palmyra to own persistence, the entity/ folder is optional — we keep it for clean separation.
Variations#
-
Different database? Swap the driver coordinate + JDBC URL. For PostgreSQL:
runtimeOnly 'org.postgresql:postgresql:42.7.3'datasource: url: jdbc:postgresql://localhost:5432/empmgmt driverClassName: org.postgresql.DriverPalmyra auto-detects the dialect from the connection — no extra configuration. The full list of supported databases is in Requirements.
-
No existing database? Palmyra plays fine with H2 in-memory for local development — change the URL to
jdbc:h2:mem:empmgmt;DB_CLOSE_DELAY=-1, drop in the H2 runtime dependency, and pointddl-autoatcreatefor the first run so the tables bootstrap themselves. -
No separate JPA entity? Skip the
entity/folder entirely and let the Palmyra model be the only Java representation of each table. The rest of the tutorial works unchanged; you give up JPA’s@ManyToOne/ cascades in return for a thinner codebase.