A robust, multi-channel notification service built with Spring Boot that enables sending notifications across multiple platforms including Email, SMS, and WhatsApp.
The Notification Service is a microservice designed to handle notification delivery across multiple channels. It provides a unified API for sending notifications through different providers while managing notification logs, templates, and configurations with intelligent provider selection and fallback mechanisms.
Project Group ID: com.axd
Version: 0.0.1-SNAPSHOT
Java Version: 21
Spring Boot Version: 3.5.7
API Base Path: /notification-service
-
Multi-Channel Support:
- Email (AWS SES, Postmark)
- SMS (Twilio, AWS SNS)
- WhatsApp (Twilio)
-
Key Capabilities:
- Template-based notification system with dynamic content rendering
- Request deduplication using
requestIdto prevent duplicate sends - Notification history and detailed logging
- Provider selection with configurable rankings and fallback mechanisms
- Configuration management with Redis caching for high performance
- User notification tracking and status retrieval
- Support for both template-based and direct content notifications
-
Technology Stack:
- Spring Boot 3.5.7
- Spring Data JPA with Hibernate
- MySQL Database
- AWS SDK (SES, SNS)
- Twilio SDK
- Lombok for Code Generation
- SpringDoc OpenAPI/Swagger Documentation
Before you begin, ensure you have the following installed:
- Java 21
- Maven 3.6+
- MySQL 8.0+
git clone https://github.com/yourusername/notification-service.git
cd notification-servicemvn clean installmvn spring-boot:runThe application will start on http://localhost:8080/notification-service
All endpoints are prefixed with /notification-service/notifications
Endpoint: POST /notifications/send
Request Body:
{
"requestId": "unique-request-id-12345",
"userId": 1,
"type": "TEMPLATE_BASED",
"channel": "EMAIL",
"data": {
"templateId": "welcome_email",
"userName": "John Doe",
"activationLink": "https://example.com/activate",
"recipientEmail": "john@example.com"
}
}Alternative - Direct Content:
{
"requestId": "unique-request-id-67890",
"userId": 2,
"type": "DIRECT_CONTENT",
"channel": "SMS",
"data": {
"phoneNumber": "+1234567890",
"message": "Your verification code is: 123456"
}
}Response:
{
"success": true,
"data": {
"notificationId": "550e8400-e29b-41d4-a716-446655440000",
"status": "SUCCESS"
}
}Endpoint: GET /notifications/user/{userId}
Response:
{
"success": true,
"data": {
"userId": 1,
"notifications": [
{
"id": 1,
"notificationId": "550e8400-e29b-41d4-a716-446655440000",
"channel": "EMAIL",
"provider": "AWS_SES",
"state": "SUCCESS",
"createdAt": "2026-03-03T10:30:00"
}
]
}
}Endpoint: GET /notifications/status/{notificationId}
Response:
{
"success": true,
"data": {
"status": "SUCCESS"
}
}- AWS SES - High deliverability, enterprise-grade
- Postmark - Developer-friendly email service
- Twilio SMS - Global SMS delivery
- AWS SNS - AWS-integrated SMS service
- Twilio WhatsApp - Rich media messaging, interactive templates
notification-service/
βββ src/
β βββ main/
β β βββ java/com/axd/notificationService/
β β β βββ channel/
β β β β βββ implementations/
β β β β β βββ EmailChannelService.java
β β β β β βββ SmsChannelService.java
β β β β β βββ WhatsAppChannelService.java
β β β β βββ NotificationChannelService.java
β β β βββ config/
β β β β βββ AwsSesConfig.java
β β β β βββ AwsSnsConfig.java
β β β β βββ TwilioConfig.java
β β β β βββ RedisConfig.java
β β β β βββ KafkaConfig.java
β β β β βββ WebClientConfig.java
β β β βββ controller/
β β β β βββ NotificationController.java
β β β βββ enums/
β β β β βββ NotificationChannel.java # EMAIL, SMS, WHATSAPP
β β β β βββ NotificationProvider.java # AWS_SES, TWILIO_SMS, etc.
β β β β βββ NotificationType.java # TEMPLATE_BASED, DIRECT_CONTENT
β β β β βββ NotificationRequestStatus.java
β β β β βββ LogContextKey.java
β β β βββ exceptions/
β β β β βββ AbstractException.java
β β β β βββ ValidationException.java
β β β β βββ ResourceNotFoundException.java
β β β β βββ handler/GlobalExceptionsHandler.java
β β β βββ factory/
β β β β βββ ChannelFactory.java
β β β β βββ ProviderFactory.java
β β β βββ model/
β β β β βββ entity/
β β β β β βββ BaseEntity.java
β β β β β βββ User.java
β β β β β βββ NotificationLog.java
β β β β β βββ NotificationTemplate.java
β β β β β βββ ConfigEntity.java
β β β β βββ dto/
β β β β β βββ request/NotificationRequest.java
β β β β β βββ response/
β β β β β β βββ GenericResponse.java
β β β β β β βββ NotificationResponse.java
β β β β β β βββ NotificationStatus.java
β β β β β β βββ UserNotification.java
β β β β β βββ EmailDto.java
β β β β β βββ SmsDto.java
β β β β β βββ WhatsappDto.java
β β β β βββ ProviderConfig.java
β β β βββ provider/
β β β β βββ NotificationProviderService.java
β β β β βββ emailProvider/AwsEmailProviderService.java
β β β β βββ smsProvider/
β β β β β βββ AwsSmsProviderService.java
β β β β β βββ TwilioSmsProviderService.java
β β β β βββ whatsAppProvider/TwilioWhatsAppProviderService.java
β β β βββ repository/
β β β β βββ UserRepository.java
β β β β βββ NotificationLogRepository.java
β β β β βββ NotificationTemplateRepository.java
β β β β βββ ConfigRepository.java
β β β βββ service/
β β β β βββ NotificationService.java
β β β β βββ NotificationLogService.java
β β β β βββ ConfigCacheService.java
β β β β βββ ProviderSelectionService.java
β β β βββ util/
β β β β βββ TemplateRenderer.java
β β β β βββ CommonUtils.java
β β β βββ constants/
β β β β βββ AppConstants.java
β β β β βββ ControllerConstants.java
β β β βββ NotificationServiceApplication.java
β β βββ resources/
β β βββ application.properties
β βββ test/
β βββ java/com/axd/notificationService/
βββ pom.xml
βββ README.md
βββ HELP.md
- Core service orchestrating notification delivery
- Handles request deduplication using
requestId - Routes requests to appropriate channels via
ChannelFactory - Manages notification status and user notifications retrieval
- Abstract contract for all channel implementations
- Implemented by
EmailChannelService,SmsChannelService,WhatsAppChannelService - Each implementation selects appropriate providers using
ProviderSelectionService
- ChannelFactory: Maps
NotificationChannelenum to channel service implementations - ProviderFactory: Dynamically selects providers based on configuration and availability
- Selects providers for a channel based on cached configuration
- Filters enabled providers and sorts by rank
- Implements fallback mechanism - if primary provider fails, tries next in rank
- Manages configuration caching with Redis
- Eliminates repeated database queries for provider configurations
- Supports cache invalidation and refresh
- Logs all notification attempts and their outcomes
- Tracks status, provider used, and delivery results
- Enables notification history and debugging
@Entity
public class User {
private Long id;
private String name;
}@Entity
public class NotificationLog extends BaseEntity {
private Long id;
private String requestId; // Used for deduplication
private String notificationId;
private Long userId;
private String eventId;
private String type; // TEMPLATE_BASED, DIRECT_CONTENT
private String channel; // EMAIL, SMS, WHATSAPP
private String provider; // AWS_SES, TWILIO_SMS, etc.
private String providerNotificationId;
private String state; // SUCCESS, FAILURE, PENDING
}@Entity
public class NotificationTemplate extends BaseEntity {
private Long id;
private String type; // Template type (e.g., ORDER_PLACED)
private String channel; // EMAIL, SMS
private String subject; // For email templates
private String bodyTemplate; // Template with placeholders
}@Entity
public class ConfigEntity extends BaseEntity {
private Long id;
@Column(name = "`group`")
private String group; // Configuration group (EMAIL, SMS, etc.)
@Column(name = "`key`")
private String key; // Configuration key
private String value; // Configuration value
}@MappedSuperclass
public class BaseEntity {
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}Configuration is stored in the database and cached in Redis for performance:
// Example: Providers for EMAIL channel stored as JSON
{
"group": "CHANNEL_PROVIDERS",
"key": "EMAIL",
"value": {
"providers": [
{
"name": "AWS_SES",
"enabled": true,
"rank": 1
},
{
"name": "POSTMARK",
"enabled": true,
"rank": 2
}
]
}
}1. Receive Notification Request (POST /notifications/send)
β
2. Validate Request & Check Required Fields
β
3. Check Deduplication (Query by requestId)
βββ If exists, return existing notification ID
β
4. Determine Channel from Request
β
5. Get Channel Implementation via ChannelFactory
β
6. Channel Service:
ββ Get Providers via ProviderSelectionService
ββ Try providers in rank order
ββ If provider succeeds β return result
ββ If provider fails β try next provider (fallback)
β
7. Log Notification (if not failure)
β
8. Return Response with notificationId & status
- Uses pre-configured templates with placeholders
- Requires
templateIdin request data - Template variables substituted at runtime
- Example: Welcome email with dynamic user name
- Sends content directly without templates
- Message/body provided in request
- No template lookup required
- Example: OTP or verification code
The application uses SLF4J with Logback for comprehensive logging:
- Request-level logging: Track requests through the system
- Provider-level logging: Monitor each provider's performance
- Error logging: Capture and log exceptions with stack traces
- Contextual information: Log through
LogContextKeyenumeration
Run the test suite:
mvn testTest class: NotificationServiceApplicationTests.java
Create a Dockerfile in the project root:
FROM openjdk:21-slim
WORKDIR /app
COPY target/notification-service-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-jar","app.jar"]Build and run:
docker build -t notification-service:latest .
docker run -p 8080:8080 \
-e SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/notification_db \
-e SPRING_DATASOURCE_USERNAME=root \
-e SPRING_DATASOURCE_PASSWORD=root \
notification-service:latestversion: '3.8'
services:
notification-service:
build: .
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/notification_db
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: root
SPRING_DATA_REDIS_HOST: redis
SPRING_DATA_REDIS_PORT: 6379
AWS_SES_ACCESS_KEY: ${AWS_ACCESS_KEY}
AWS_SES_SECRET_KEY: ${AWS_SECRET_KEY}
TWILIO_ACCOUNT_SID: ${TWILIO_ACCOUNT_SID}
TWILIO_AUTH_TOKEN: ${TWILIO_AUTH_TOKEN}
depends_on:
- mysql
- redis
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: notification_db
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:7.0-alpine
ports:
- "6379:6379"
volumes:
mysql_data:Interactive API documentation is available via Swagger UI:
http://localhost:8080/notification-service/swagger-ui.html
OpenAPI specification:
http://localhost:8080/notification-service/v3/api-docs