Twilio SMS adapter for the Firefly Framework notifications abstraction — a reactive
SMSProviderthat delivers text messages through the Twilio REST API.
- Overview
- Features
- Requirements
- Installation
- Quick Start
- Configuration
- How It Works
- Documentation
- Contributing
- License
fireflyframework-notifications-twilio is a pluggable SMS provider adapter for the Firefly Framework notifications subsystem. It implements the SMSProvider outbound port defined by the notifications core (fireflyframework-notifications-core) using Twilio as the delivery backend.
The notifications subsystem follows a hexagonal (ports-and-adapters) design: the core module declares technology-agnostic ports such as SMSProvider, and infrastructure adapters supply concrete implementations. Application code depends only on the SMSProvider interface and stays decoupled from any specific vendor SDK. This adapter contributes one such implementation, TwilioSMSProvider, wired automatically through Spring Boot auto-configuration.
Adapter selection is property-driven: the adapter only activates when firefly.notifications.sms.provider is set to twilio (and the Twilio SDK is on the classpath). This makes the SMS backend swappable at deploy time without code changes — drop in a different adapter module and flip the property to switch providers.
The Twilio adapter is one of several notification adapters in the framework, alongside sibling modules such as fireflyframework-notifications-sendgrid and fireflyframework-notifications-resend (email) and fireflyframework-notifications-firebase (push). All of them plug into the same fireflyframework-notifications-core ports.
SMSProviderimplementation (TwilioSMSProvider) backed by the official Twilio Java SDK (com.twilio.sdk:twilio).- Fully reactive API —
sendSMSreturns a ReactorMono<SMSResponseDTO>; the blocking Twilio REST call is offloaded toSchedulers.boundedElastic()so it never blocks event-loop threads. - Property-driven activation — only engages when
firefly.notifications.sms.provider=twilio, leaving other SMS adapters inert and avoiding bean conflicts. - Spring Boot auto-configuration (
TwilioAutoConfiguration) initializes the Twilio client and registers the provider bean with zero boilerplate. @ConditionalOnMissingBeanbeans — bring your ownSMSProviderto override the default while keeping the auto-config.- Defensive request validation — null requests, blank recipient numbers, blank message bodies, and unconfigured sender numbers are turned into a structured
SMSResponseDTO.error(...)rather than thrown exceptions. - Structured responses — successful sends return the Twilio message SID via
SMSResponseDTO.success(sid); failures carry an error message andFAILEDstatus.
- Java 21+ (Java 25 recommended)
- Spring Boot 3.x
- Maven 3.9+
- A Twilio account with an Account SID, Auth Token, and a provisioned (or verified) sender phone number
fireflyframework-notifications-coreon the classpath (transitively included by this module)
Add the adapter to your application. The version is managed by the Firefly Framework BOM / parent, so you normally omit <version>:
<dependency>
<groupId>org.fireflyframework</groupId>
<artifactId>fireflyframework-notifications-twilio</artifactId>
<!-- version managed by the Firefly BOM / fireflyframework-parent -->
</dependency>This adapter transitively brings in fireflyframework-notifications-core, so you do not need to declare the core module separately.
1. Add the dependency (see Installation).
2. Select Twilio as the SMS provider and supply credentials in application.yml:
firefly:
notifications:
sms:
provider: twilio # activates this adapter
twilio:
account-sid: ${TWILIO_ACCOUNT_SID}
auth-token: ${TWILIO_AUTH_TOKEN}
phone-number: "+1234567890" # your Twilio sender number (E.164)3. Inject the SMSProvider port and send a message — your code stays vendor-agnostic:
import org.fireflyframework.notifications.interfaces.dtos.sms.v1.SMSRequestDTO;
import org.fireflyframework.notifications.interfaces.dtos.sms.v1.SMSResponseDTO;
import org.fireflyframework.notifications.interfaces.providers.sms.v1.SMSProvider;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
@Service
public class OtpService {
private final SMSProvider smsProvider;
public OtpService(SMSProvider smsProvider) {
this.smsProvider = smsProvider; // TwilioSMSProvider injected by auto-config
}
public Mono<SMSResponseDTO> sendOtp(String phoneNumber, String code) {
SMSRequestDTO request = SMSRequestDTO.builder()
.phoneNumber(phoneNumber)
.message("Your verification code is " + code)
.build();
return smsProvider.sendSMS(request)
.doOnNext(response -> {
if ("SENT".equals(response.getStatus())) {
// response.getMessageId() == Twilio message SID
}
});
}
}A successful send returns an SMSResponseDTO with status SENT and the Twilio message SID in messageId. Validation failures (null request, blank number, blank message, or missing sender number) return status FAILED with a populated errorMessage.
The adapter is configured through two property groups: the shared notifications selector and the Twilio-specific credentials (@ConfigurationProperties(prefix = "firefly.notifications.twilio")).
firefly:
notifications:
sms:
provider: twilio # required: must equal "twilio" to enable this adapter
twilio:
account-sid: # Twilio Account SID (starts with "AC...")
auth-token: # Twilio Auth Token
phone-number: # Twilio sender number in E.164 format, e.g. +14155552671| Property | Default | Description |
|---|---|---|
firefly.notifications.sms.provider |
(none) | Adapter selector. Must be twilio for this module's auto-configuration to activate. |
firefly.notifications.twilio.account-sid |
(none) | Twilio Account SID used to authenticate with the Twilio REST API. |
firefly.notifications.twilio.auth-token |
(none) | Twilio Auth Token paired with the Account SID. Keep this secret (env var / vault). |
firefly.notifications.twilio.phone-number |
(none) | The "from" number messages are sent from. Must be a Twilio-owned or verified number in E.164 format. If unset, sends fail with Sender phone number not configured. |
Tip: source
account-sidandauth-tokenfrom environment variables or a secrets manager rather than committing them toapplication.yml.
TwilioAutoConfiguration is registered via META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports and is guarded by:
@ConditionalOnProperty(name = "firefly.notifications.sms.provider", havingValue = "twilio")— opt-in selection.@ConditionalOnClass(com.twilio.Twilio.class)— only when the Twilio SDK is present.@EnableConfigurationProperties(TwilioProperties.class)— binds thefirefly.notifications.twilio.*keys.
When active, it initializes the static Twilio client with Twilio.init(accountSid, authToken) and registers a TwilioSMSProvider as the SMSProvider bean (both @ConditionalOnMissingBean, so you can override either). TwilioSMSProvider.sendSMS validates the request, builds a Twilio Message (recipient, sender, body), executes the REST call on Schedulers.boundedElastic(), and maps the result to an SMSResponseDTO.
- Notifications core (ports/SPI):
fireflyframework-notifications - Firefly Framework organization and module catalog: github.com/fireflyframework
- Twilio Java SDK reference: twilio.com/docs/libraries/java
Contributions are welcome. Please read the CONTRIBUTING.md guide for details on our code of conduct, development process, and how to submit pull requests.
Copyright 2024-2026 Firefly Software Foundation.
Licensed under the Apache License, Version 2.0. See LICENSE for details.