Video summary
Build an Event Ticket Platform with Spring Boot - Full Build - Intermediate Project
Main summary
Key takeaways
Technology / Product Being Built
A full-stack event ticket platform using:
- Spring Boot (REST API backend, Spring Security resource server)
- React SPA (front-end; single-page app consuming the REST API)
- PostgreSQL (main relational database)
- Keycloak (authentication/authorization via OAuth2 + OpenID Connect; JWT)
- Docker Compose (runs PostgreSQL + Adminer, and Keycloak locally)
- MapStruct + Lombok (DTO/entity mapping and boilerplate reduction)
- QR code generation using a QR library (generate QR image, store as base64)
Core workflow
- Event organizers create events with multiple ticket types.
- Attendees browse/search published events, view details, and purchase tickets (mock payment).
- Purchased tickets include a unique QR code.
- Event staff scan QR codes (or manually enter ticket IDs) to validate tickets at entry, preventing duplicates.
Video Structure / Key Modules and What They Implement
1) Domain analysis + requirements
- Defines domain concepts: Event, Ticket, QR Code
- Converts a project brief into user stories and acceptance criteria for:
- Create event (organizer)
- Purchase ticket (attendee)
- Manage ticket sales (organizer analytics/limits/overselling prevention)
- Validate ticket (staff scanning on mobile; instant feedback; prevent duplicate use)
2) UX/UI planning (personas, journeys, wireframes)
-
Creates user personas and journeys for:
- Organizers (corporate manager, planning pro, part-time organizer)
- Attendees (busy parent, young/digital native, corporate networking attendee)
- Staff (coordinator, entry-level staff)
-
Figma UI wireframes:
- Organizer pages: create/manage events, ticket sales, ticket types, reporting placeholder
- Attendee pages: search events, event details, purchase ticket page (mock), tickets dashboard + QR display
- Staff page: mobile-first QR scanner + manual entry + instant validation result
3) Domain modeling (class diagram → REST API blueprint)
-
Builds a domain/class model including relationships:
- Event → ticket types → tickets → QR codes
- Ticket → ticket validations (multiple validations tracked for history)
-
Evolves into a richer class diagram with:
- cardinality
- data types (UUIDs, enums, LocalDateTime)
- required vs optional fields
-
This informs REST resource design.
4) REST API design (per user role)
Endpoints are planned from UI flows:
Organizer (“events” CRUD)
POST /api/v1/events(create event)GET /api/v1/events(list events for organizer; paginated)GET /api/v1/events/{eventId}(event details for organizer)PUT /api/v1/events/{eventId}(full update)DELETE /api/v1/events/{eventId}(delete)
Ticket sales / ticket type management
- Tickets under event (list/retrieve; cancellation via status update)
- Ticket types under event (list/retrieve; patch name/availability)
- Validation concept: restrict deletes if tickets exist
Attendee (“published events” + purchase)
Public list/search
GET /api/v1/published-events(paginated)- optional query parameter for search
Public details
GET /api/v1/published-events/{eventId}
Ticket purchase (mock payment)
POST /api/v1/published-events/{publishedEventId}/ticket-types/{ticketTypeId}/tickets(mock)
Attendee dashboard
GET /api/v1/tickets(list user’s tickets; paginated)GET /api/v1/tickets/{ticketId}(get ticket details)GET /api/v1/tickets/{ticketId}/qr-codes(returns QR image bytes)
Staff validation
POST /api/v1/events/{eventId}/ticket-validations(QR scan or manual entry)- Planned: validation history listing (optional in this segment)
5) Architecture setup
- SPA front-end (React) ↔ Spring Boot REST backend
- PostgreSQL as relational DB
- Keycloak as auth/authorization server
Notes:
- React communicates via REST API
- Keycloak used for JWT validation (resource server)
- Authorization enforced in Spring Security by roles (organizer/attendee/staff)
Implementation Highlights (What Gets Coded)
Spring Boot project setup
- Spring Initializer choices:
- Java 21
- Maven
- Dependencies: Spring Web, Spring Security, OAuth2 Resource Server, Spring Data JPA, PostgreSQL driver, Lombok, H2 for tests
Docker Compose infrastructure
- PostgreSQL + Adminer for viewing data
- Keycloak container with persisted config (volume) for realms/clients/users
Keycloak setup
- Realm:
event-ticket-platform - Client for SPA (OpenID Connect, public access; redirect/callback configured)
- Users + roles created:
- Organizer role + user
- Attendee role + user
- Staff role + user
Entity modeling (JPA)
Implemented entities:
UserEventTicketTypeTicketTicketValidationQRcode
Key ORM decisions:
- Single
Userentity; user “type” handled via Keycloak roles - UUID primary keys (except keycloak user ID derived from JWT subject)
- Audit fields via
@CreatedDate/@LastModifiedDateand global JPA auditing enablement - Fixes included:
- Renaming DB column names from reserved keywords like
start/endtoevent start/event end
- Renaming DB column names from reserved keywords like
DTOs, validation, and MapStruct
- Dedicated request/response DTOs per endpoint (decoupling entities from API contracts)
- Validation with:
@NotBlank,@NotNull,@PositiveOrZero, etc.- nested validation via
@Valid
- Global error handling:
ConstraintViolationExceptionMethodArgumentNotValidException- custom exceptions (e.g.,
UserNotFoundException, laterTicketNotFoundException, etc.)
- MapStruct mappers convert entity ↔ DTO for request/response paths.
Feature-by-Feature: What Worked + Notable Bugs/Fixes
Create event (organizer)
-
Implemented:
- DTOs for create request/response
- service layer creates
Event+ nestedTicketTypes via cascading - global exception handler returns consistent error format (HTTP codes +
{ "error": "..." })
-
Bug/fix:
- Initial failures due to:
- reserved SQL keywords (
start,end) - controller annotation mismatch (
@RequestParamvs@PathVariable)
- reserved SQL keywords (
- Initial failures due to:
List events for organizer (dashboard)
- Paginated listing:
GET /api/v1/events?page=&size=...
- DTO summary response includes:
- event ID/name/start/end/venue/sales window/status + ticket type summaries
Get event details for organizer (edit form)
GET /api/v1/events/{eventId}- Returns full event details including ticket types; used to populate edit UI.
Update event (full update)
PUT /api/v1/events/{eventId}- Full replacement model:
- updates fields
- reconciles ticket types:
- remove ticket types not present in request (orphan removal)
- update existing ones by ID
- create new ones when ticket type ID is null
- Bug/fix note:
- Ensures method is
transactionalto avoid inconsistent partial updates.
- Ensures method is
Delete event
DELETE /api/v1/events/{eventId}- UI button triggers confirmation modal
- Returns
204 No Contenton success
Public published events listing + search
- Endpoint made public using Spring Security matchers:
GET /api/v1/published-events
- Search:
GET /api/v1/published-events?Q=term- Uses PostgreSQL text search across
nameandvenue - Filters by
EventStatus = published
Get published event details (attendee view)
GET /api/v1/published-events/{eventId}- Public details DTO subset (no organizer/audit details)
- Returns ticket type list used on ticket purchase page.
Purchase Ticket + QR Code Generation
QR code generation
- Added QR code persistence fields:
- stores QR image as B64 in a
textcolumn
- stores QR image as B64 in a
- Generates:
- a manual UUID for QR code ID (baked into QR value)
- QR image = PNG → bytes → base64 string
- Uses a QR library (ZXing mentioned)
- Saves
QRcodeentity linked toTicket.
Ticket purchase
- New ticket creation flow (no third-party payments; mock payment):
- validates user + ticket type existence
- checks available inventory and prevents overselling
- implements concurrency control:
- pessimistic lock on
TicketTypefetch (PESSIMISTIC_WRITE)
- pessimistic lock on
- creates:
- a
Ticket(status purchased) - a
QRcodefor that ticket
- a
- Bug/fix:
- Fixed
NullPointerExceptionwhereQR code repositorywasnulldue to missing dependency wiring/final injection.
- Fixed
Purchase endpoint
POST /api/v1/.../ticket-types/{ticketTypeId}/tickets- Returns
204 No Content(no ticket payload in response)
Role-based Security
JWT role extraction
- Custom
Converterparses JWT claim:realm_access.roles
- Converts
RO_*roles (Keycloak convention) into Spring SecurityGrantedAuthoritys.
Endpoint authorization rules
- Spring Security configured to restrict:
- Organizer endpoints (event controller) to
ROLE_organizer
- Organizer endpoints (event controller) to
- Staff-only access added for ticket validation endpoint:
ROLE_staff
Tickets Dashboard + QR Retrieval
List tickets
GET /api/v1/tickets- Paginated listing for the logged-in user.
Get ticket details
GET /api/v1/tickets/{ticketId}- Returns flattened ticket + ticket type + event details for display.
Get ticket QR image
GET /api/v1/tickets/{ticketId}/qr-codes- Returns raw image bytes with correct
Content-TypeandContent-Length.
Ticket Validation (Staff Scanning + Manual Entry)
Validation service
Implemented TicketValidation creation for two input modes:
- QR code scan:
- uses
QRcodelookup byidandstatus=active
- uses
- Manual entry:
- uses ticket ID directly
Validation logic:
- Prevents duplicate redemption:
- if any prior validation on the ticket is valid, the next becomes invalid.
Validation endpoint
- POST endpoint under event route:
POST /api/v1/events/{eventId}/ticket-validations
- Input DTO contains:
idandvalidationMethod(QR scan vs manual)
UI testing
-
Demonstrated:
- scanning QR twice yields valid then invalid
- manual entry yields valid then invalid
-
Bug discovered/fixed:
- validation method incorrectly hardcoded as
QR code scanin one branch; corrected so manual validations record correct method.
- validation method incorrectly hardcoded as
Notable “Analysis/Tutorial” Takeaways
- Strong emphasis on deriving backend API from:
- domain model + user stories + UI flows
- Clear separation:
- entities vs DTOs per endpoint
- request DTOs vs response DTOs
- Correct handling of:
- validation errors and consistent API error response schema
- transactional boundaries for write operations
- reserved SQL keywords and ORM column naming
- Local development stack:
- Dockerized Postgres and Keycloak
- Adminer for schema debugging
- Security:
- JWT role extraction from Keycloak
- role-based endpoint access using Spring Security request matchers
Main Speakers / Sources (from the Subtitles)
- Primary speaker/instructor: “I’ll show you the process that I use…” (unnamed in the subtitles)
- Sources referenced in the video text:
- Devto.com (premium UI lessons)
- DevTiscord server (downloadable resources/source code/materials)
- Keycloak documentation / libraries (e.g., MapStruct/Lombok/ZXing mentioned during implementation)