Skip to content

Implement boring, extensible email notification orchestration pattern - #3

Open
imagineux wants to merge 1 commit into
mainfrom
codex/design-java-spring-boot-email-notification-service-xtje7e
Open

Implement boring, extensible email notification orchestration pattern#3
imagineux wants to merge 1 commit into
mainfrom
codex/design-java-spring-boot-email-notification-service-xtje7e

Conversation

@imagineux

Copy link
Copy Markdown
Owner

Motivation

  • Centralize the notification flow so callers have a single, low-cognitive-load entry point: EmailNotificationOrchestrator.notify(type, payload).
  • Make adding a new notification a small, local change (YAML entry + template + tiny model builder + optional payload) without editing the orchestration flow.
  • Keep this service publisher-only so it produces an EmailPublicationRequest and does not perform delivery.
  • Use typed, centralized configuration to avoid scattered settings and runtime surprises via @ConfigurationProperties.

Description

  • Added EmailNotificationOrchestrator that looks up NotificationDefinition, delegates model construction to NotificationModelBuilderRegistry, renders via TemplateRenderer, and publishes an EmailPublicationRequest through EmailPublicationPublisher.
  • Introduced typed config objects: NotificationProperties, NotificationDefinition, and NotificationCatalog for centralized lookup by NotificationType.
  • Added a rendering abstraction TemplateRenderer plus a ThymeleafTemplateRenderer implementation, and a publishing abstraction EmailPublicationPublisher with payload EmailPublicationRequest (no Kafka implementation included by design).
  • Implemented the model-builder strategy NotificationModelBuilder<T> with an explicit registry and two examples (HOLD_LIST_CREATED and HOLD_LIST_REMOVED) including payload records, small builders, application.yml entries, Thymeleaf templates, a sample domain service (HoldListDomainService), and focused unit tests.

Testing

  • Included unit tests: EmailNotificationOrchestratorTest and NotificationModelBuilderRegistryTest under src/test/java that verify publish behavior, disabled-skip behavior, builder delegation, and payload-mismatch errors.
  • Ran mvn test in this environment, but the run failed due to dependency resolution being blocked (Maven Central returned HTTP 403 while resolving the Spring Boot parent POM), so tests did not execute here.
  • The tests are small and mocked where appropriate and should pass in a normal environment once dependencies can be fetched (the failure is environmental, not due to test logic).

Codex Task

@bolt-new-by-stackblitz

Copy link
Copy Markdown

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cc448a9616

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

recipients:
- ops@example.com
- support@example.com
templatePath: templates/notifications/hold-list-created

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove templates/ prefix from templatePath values

ThymeleafTemplateRenderer.render passes definition.templatePath() directly to TemplateEngine.process(...), and with Spring Boot’s default Thymeleaf resolver that path is already prefixed with classpath:/templates/. Setting templatePath to templates/notifications/hold-list-created makes resolution look for classpath:/templates/templates/notifications/hold-list-created.html, so rendering enabled notifications will fail at runtime (TemplateInputException). Use template names relative to the templates root (for example notifications/hold-list-created) for both entries.

Useful? React with 👍 / 👎.

NotificationCatalog catalog,
NotificationModelBuilderRegistry builderRegistry,
TemplateRenderer templateRenderer,
EmailPublicationPublisher publisher

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Provide a concrete EmailPublicationPublisher bean

EmailNotificationOrchestrator is a @Service with a required constructor dependency on EmailPublicationPublisher, but this commit only adds the interface and no @Component/@Bean implementation in src/main. As a result, booting NotificationApplication in this repo will fail during context initialization with an unsatisfied dependency before any notification flow can run.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant