Skip to content

Commit c8f1398

Browse files
Andrés Contreras GuillénAndrés Contreras Guillén
authored andcommitted
docs: comprehensive, polished README
1 parent 6648a34 commit c8f1398

1 file changed

Lines changed: 143 additions & 25 deletions

File tree

README.md

Lines changed: 143 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
[![Java](https://img.shields.io/badge/Java-21%2B-orange.svg)](https://openjdk.org)
66
[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.x-green.svg)](https://spring.io/projects/spring-boot)
77

8-
> Notifications core library with email, SMS, and push notification service contracts and provider abstraction.
8+
> Reactive, provider-agnostic notifications core for Spring Boot — email, SMS and push ports with pluggable SendGrid, Resend, Twilio and Firebase adapters, FreeMarker templating, per-user channel preferences and built-in Micrometer metrics.
99
1010
---
1111

1212
## Table of Contents
1313

1414
- [Overview](#overview)
15+
- [Modules](#modules)
16+
- [Provider Adapters](#provider-adapters)
1517
- [Features](#features)
1618
- [Requirements](#requirements)
1719
- [Installation](#installation)
@@ -23,70 +25,186 @@
2325

2426
## Overview
2527

26-
Firefly Framework Notifications provides the core service layer and provider contracts for sending email, SMS, and push notifications. It defines provider interfaces (`EmailProvider`, `SMSProvider`, `PushProvider`) that concrete notification providers implement, along with application services that orchestrate notification delivery.
28+
Firefly Framework Notifications is the **core notifications abstraction** for the Firefly platform. It defines the application services and outbound ports for sending notifications across three channels — **email**, **SMS** and **push** — and lets you swap concrete delivery providers without touching business logic.
2729

28-
The module is structured as a multi-module project with a core sub-module containing the service implementations, DTOs, and provider interfaces. The notification services delegate to the appropriate provider implementation, which is supplied by separate provider modules (SendGrid, Resend, Twilio, Firebase).
30+
The module follows a strict **hexagonal (ports & adapters)** design. Your code depends only on the channel services (`EmailService`, `SMSService`, `PushService`) and the outbound port interfaces (`EmailProvider`, `SMSProvider`, `PushProvider`). The actual integration with a SaaS provider lives in a **separate adapter module** (SendGrid, Resend, Twilio, Firebase) that you add as a dependency and select with a single property. Because the ports are the only contract, you can switch from, say, SendGrid to Resend by changing a dependency and one config line — no code changes.
2931

30-
This architecture allows applications to switch notification providers without changing business logic, as all providers implement the same standardized interfaces.
32+
Everything is **reactive end to end**: services and ports return Project Reactor `Mono` types, so notification dispatch composes naturally into WebFlux pipelines and never blocks request threads. On top of the raw send path the core adds two cross-cutting concerns out of the box: a **FreeMarker template engine** for rendering templated emails by ID, and a **notification preference service** so deliveries can respect per-user, per-channel opt-outs. A Spring Boot auto-configuration wires shared **Micrometer** instrumentation (`NotificationMetrics`) that every adapter reuses to emit consistent send/latency/error metrics tagged by channel and provider.
33+
34+
This repository ships only the contracts, DTOs, services and observability — it has **no opinionated runtime provider of its own**. Pick one (or more) of the sibling adapter modules below to actually deliver messages.
35+
36+
### Modules
37+
38+
This is an aggregator (`pom` packaging) project. It currently contains a single submodule; the structure leaves room for additional core submodules without breaking coordinates.
39+
40+
| Module | Artifact | Purpose |
41+
| --- | --- | --- |
42+
| Notifications Core | `fireflyframework-notifications-core` | Channel services (email/SMS/push), outbound provider ports, request/response DTOs, FreeMarker template engine, in-memory notification preference service, and Micrometer observability auto-configuration. |
43+
44+
### Provider Adapters
45+
46+
Concrete delivery is supplied by these **separate adapter repositories**, each implementing the matching port from this core and activating via a `firefly.notifications.<channel>.provider` property:
47+
48+
| Adapter | Channel | Implements | Selecting property |
49+
| --- | --- | --- | --- |
50+
| [`fireflyframework-notifications-sendgrid`](https://github.com/fireflyframework/fireflyframework-notifications-sendgrid) | Email | `EmailProvider` | `firefly.notifications.email.provider=sendgrid` |
51+
| [`fireflyframework-notifications-resend`](https://github.com/fireflyframework/fireflyframework-notifications-resend) | Email | `EmailProvider` | `firefly.notifications.email.provider=resend` |
52+
| [`fireflyframework-notifications-twilio`](https://github.com/fireflyframework/fireflyframework-notifications-twilio) | SMS | `SMSProvider` | `firefly.notifications.sms.provider=twilio` |
53+
| [`fireflyframework-notifications-firebase`](https://github.com/fireflyframework/fireflyframework-notifications-firebase) | Push | `PushProvider` | `firefly.notifications.push.provider=firebase` |
3154

3255
## Features
3356

34-
- `EmailService` with template-based email sending and attachments
35-
- `SMSService` for SMS message delivery
36-
- `PushService` for push notification delivery
37-
- `EmailProvider` interface for pluggable email providers
38-
- `SMSProvider` interface for pluggable SMS providers
39-
- `PushProvider` interface for pluggable push notification providers
40-
- DTOs for email requests/responses with attachment support
41-
- DTOs for SMS requests/responses
42-
- DTOs for push notification requests/responses
43-
- Email status tracking enum
57+
- **Reactive channel services**`EmailService`, `SMSService` and `PushService`, each returning `Mono<...ResponseDTO>` for non-blocking dispatch.
58+
- **Hexagonal outbound ports**`EmailProvider`, `SMSProvider`, `PushProvider`. Add an adapter module and a config property to bind an implementation; no code changes to switch providers.
59+
- **Rich email model**`EmailRequestDTO` with `from`/`to`, CC/BCC lists, plain-text and HTML bodies, Bean Validation (`@Email`, `@NotBlank`), and `EmailAttachmentDTO` for byte-content attachments with MIME type.
60+
- **Templated email**`sendTemplateEmail(EmailTemplateRequestDTO)` renders a template by `templateId` with a variable map before delivery. Backed by the pluggable `NotificationTemplateEngine` SPI.
61+
- **FreeMarker template engine**`FreemarkerNotificationTemplateEngine` loads `.ftl` templates from a configurable classpath prefix (default `/notification-templates`) and an optional filesystem directory; rendering runs on a bounded-elastic scheduler.
62+
- **Per-user channel preferences**`NotificationPreferenceService` with a ready-to-use `InMemoryNotificationPreferenceService`; toggle email/SMS/push per user (with per-channel overrides) and check `isChannelEnabled(userId, channel)` before sending.
63+
- **Consistent response contracts**`EmailResponseDTO` (with `EmailStatusEnum` SENT/FAILED and `success(...)`/`error(...)` factories), `SMSResponseDTO`, and `PushNotificationResponse`, each carrying message ID, status and error message.
64+
- **Built-in observability**`NotificationObservabilityAutoConfiguration` registers a shared `NotificationMetrics` bean (when a `MeterRegistry` is present) emitting `firefly.notifications.sent`, `firefly.notifications.delivery.duration`, `firefly.notifications.errors` and `firefly.notifications.templates.rendered`, tagged by `channel`, `provider`, `status` and `template`.
65+
- **Reusable by every adapter** — adapters wrap their dispatch in `NotificationMetrics.timedDispatch(channel, provider, mono)` so all providers report metrics the same way.
4466

4567
## Requirements
4668

47-
- Java 21+
69+
- Java 21+ (Java 25 recommended)
4870
- Spring Boot 3.x
4971
- Maven 3.9+
72+
- At least one provider adapter (SendGrid, Resend, Twilio, or Firebase) plus its account/API credentials to actually deliver notifications
73+
- A `MeterRegistry` (e.g. Micrometer + Actuator) on the classpath if you want notification metrics
74+
- FreeMarker on the classpath only if you use templated email (it is an optional dependency)
5075

5176
## Installation
5277

78+
The notifications core is consumed transitively by every provider adapter, so in most applications you simply add the adapter you need (see [Provider Adapters](#provider-adapters)). To depend on the core contracts directly:
79+
5380
```xml
5481
<dependency>
5582
<groupId>org.fireflyframework</groupId>
56-
<artifactId>fireflyframework-notifications</artifactId>
57-
<version>26.02.07</version>
83+
<artifactId>fireflyframework-notifications-core</artifactId>
84+
<!-- Version is managed by the Firefly BOM / parent; omit it when inheriting fireflyframework-parent -->
5885
</dependency>
5986
```
6087

88+
The version is governed by the Firefly Framework parent/BOM. When your project inherits `fireflyframework-parent` (or imports the Firefly BOM), you can omit the `<version>` entirely.
89+
6190
## Quick Start
6291

92+
**1. Add a provider adapter** (here: SendGrid for email). The adapter brings `fireflyframework-notifications-core` in transitively.
93+
94+
```xml
95+
<dependency>
96+
<groupId>org.fireflyframework</groupId>
97+
<artifactId>fireflyframework-notifications-sendgrid</artifactId>
98+
</dependency>
99+
```
100+
101+
**2. Select and configure the provider** in `application.yml`:
102+
103+
```yaml
104+
firefly:
105+
notifications:
106+
email:
107+
provider: sendgrid # binds the SendGrid EmailProvider adapter
108+
sendgrid:
109+
api-key: ${SENDGRID_API_KEY}
110+
```
111+
112+
**3. Inject the channel service and send** — the `EmailProvider` adapter is auto-wired behind `EmailService`:
113+
63114
```java
64115
import org.fireflyframework.notifications.core.services.email.v1.EmailService;
65116
import org.fireflyframework.notifications.interfaces.dtos.email.v1.EmailRequestDTO;
117+
import org.fireflyframework.notifications.interfaces.dtos.email.v1.EmailResponseDTO;
118+
import org.springframework.stereotype.Service;
119+
import reactor.core.publisher.Mono;
66120
67121
@Service
68122
public class OrderNotificationService {
69123
70124
private final EmailService emailService;
71125
72-
public Mono<EmailResponseDTO> sendOrderConfirmation(Order order) {
126+
public OrderNotificationService(EmailService emailService) {
127+
this.emailService = emailService;
128+
}
129+
130+
public Mono<EmailResponseDTO> sendOrderConfirmation(String customerEmail, String orderId) {
73131
EmailRequestDTO request = EmailRequestDTO.builder()
74-
.to(order.getCustomerEmail())
75-
.subject("Order Confirmation - " + order.getId())
76-
.body("Your order has been confirmed.")
77-
.build();
78-
return emailService.send(request);
132+
.from("orders@example.com")
133+
.to(customerEmail)
134+
.subject("Order Confirmation - " + orderId)
135+
.html("<h1>Thanks!</h1><p>Your order " + orderId + " is confirmed.</p>")
136+
.build();
137+
return emailService.sendEmail(request);
79138
}
80139
}
81140
```
82141

142+
**Templated email** — provide a `NotificationTemplateEngine` bean (the FreeMarker engine renders `.ftl` files from `/notification-templates`) and call `sendTemplateEmail`:
143+
144+
```java
145+
@Bean
146+
NotificationTemplateEngine notificationTemplateEngine() {
147+
return new FreemarkerNotificationTemplateEngine(); // classpath:/notification-templates
148+
}
149+
150+
// ...
151+
EmailTemplateRequestDTO request = EmailTemplateRequestDTO.builder()
152+
.from("welcome@example.com")
153+
.to(user.getEmail())
154+
.subject("Welcome!")
155+
.templateId("welcome-email") // resolves welcome-email.ftl
156+
.templateVariables(Map.of("firstName", user.getFirstName()))
157+
.build();
158+
return emailService.sendTemplateEmail(request);
159+
```
160+
161+
**Respect user preferences** before dispatching:
162+
163+
```java
164+
return preferenceService.isChannelEnabled(userId, "email")
165+
.filter(Boolean::booleanValue)
166+
.flatMap(enabled -> emailService.sendEmail(request));
167+
```
168+
169+
SMS and push follow the same pattern via `SMSService.sendSMS(SMSRequestDTO)` and `PushService.sendPush(PushNotificationRequest)`, selecting the Twilio and Firebase adapters respectively.
170+
83171
## Configuration
84172

85-
Configuration is provided by the specific notification provider module (SendGrid, Resend, Twilio, Firebase).
173+
This core module exposes one auto-configuration toggle; the bulk of configuration (API keys, sender identities, provider selection) lives in the provider adapter you choose.
174+
175+
```yaml
176+
firefly:
177+
notifications:
178+
# Provider selection — supplied by the adapter modules you add (see table below).
179+
email:
180+
provider: sendgrid # or: resend
181+
sms:
182+
provider: twilio
183+
push:
184+
provider: firebase
185+
observability:
186+
metrics:
187+
enabled: true # default; set false to skip NotificationMetrics registration
188+
```
189+
190+
| Property | Default | Description |
191+
| --- | --- | --- |
192+
| `firefly.notifications.email.provider` | _(none)_ | Selects the email `EmailProvider` adapter — `sendgrid` or `resend`. Defined by the adapter module. |
193+
| `firefly.notifications.sms.provider` | _(none)_ | Selects the SMS `SMSProvider` adapter — `twilio`. Defined by the adapter module. |
194+
| `firefly.notifications.push.provider` | _(none)_ | Selects the push `PushProvider` adapter — `firebase`. Defined by the adapter module. |
195+
| `firefly.observability.metrics.enabled` | `true` | When `true` (and a `MeterRegistry` is present), registers the shared `NotificationMetrics` bean used by all adapters. |
196+
197+
Provider-specific keys (for example `firefly.notifications.sendgrid.*`, `firefly.notifications.twilio.*`, `firefly.notifications.firebase.*`) are documented in each adapter's README.
198+
199+
**Template engine** — `FreemarkerNotificationTemplateEngine` is not auto-registered; declare it as a bean. Its constructor accepts a classpath prefix (default `/notification-templates`) and an optional filesystem directory for template overrides. Without a `NotificationTemplateEngine` bean, `sendTemplateEmail` fails fast with an `UnsupportedOperationException`.
200+
201+
**Notification preferences** — `InMemoryNotificationPreferenceService` is suitable for development and single-instance deployments. For multi-instance/production usage, provide your own `NotificationPreferenceService` backed by R2DBC or a cache.
86202

87203
## Documentation
88204

89-
No additional documentation available for this project.
205+
- [`ARCHITECTURE.md`](ARCHITECTURE.md) — in-depth hexagonal architecture guide: ports & adapters, layer responsibilities, dependency flow, and how to add a new provider.
206+
- [Firefly Framework Module Catalog](https://github.com/fireflyframework) — the full set of framework modules and adapters.
207+
- Adapter READMes: [SendGrid](https://github.com/fireflyframework/fireflyframework-notifications-sendgrid) · [Resend](https://github.com/fireflyframework/fireflyframework-notifications-resend) · [Twilio](https://github.com/fireflyframework/fireflyframework-notifications-twilio) · [Firebase](https://github.com/fireflyframework/fireflyframework-notifications-firebase).
90208

91209
## Contributing
92210

0 commit comments

Comments
 (0)