In the “Using Heroku to Quickly Build a Multi-Tenant SaaS Product” article, I documented the foundation for a new SaaS solution that I am building (initially for my sister-in-law) — utilizing the Heroku ecosystem. At the end of that article, I had planned to write about the core technologies (Spring Boot, Angular 9, ClearDB, Okta, GitLab and Heroku) in place, as we raced for the 1.0.0 release of the solution.
However, things have been moving fast around here, and I largely attribute the speed of development and end-user adoption to everything that Heroku brings to the table for this service. As I have noted before, using Heroku as the destination for my service and GitLab’s built-in CI/CD pipelines — updates that are merged from a feature branch into the
master branch of the client or service are automatically deployed into production (Heroku) without any further intervention.
Instead of starting the 1.0.1 release, the project is actually finishing up the 1.0.3 release. Below is an updated feature map:
Progress Via Screenshots
Since using Spring JPA to create the initial schema, which it did without any issues, I have been keeping the
fitness.sql up to date manually as model updates have been required. Using IntelliJ IDEA and built in database tooling (including yFiles), I was able to quickly create the following diagram of the current MySQL/ClearDB database structure:
As noted in the prior article, everything ties back to the ID of the tenant (or fitness trainer) – which is also enforced in the base JPA Specifications employed at the service level.
These changes, along with screens for Client configuration and Workout configuration, allowed the Session screen to be introduced:
The Sessions (which is an instance of a workout and at least one client) are presented in an optional calendar view to give the trainer a view which is easy to comprehend at a glance:
In the example above, there is only one event scheduled – since the screen shot is from my test account in the production instance of the SaaS solution.
There is also a training-mode version of the Session screen, which is mainly a read-only adaptation and consolidates data for quick reference.
The icons on this screen are still active, so that that trainer can not only check-in clients, but also provide session information (score and comments) too:
Along the Way … Twilio Was Discovered
One of items which was slated for the 1.0.4 release was referred to as Client Check-In. We soon realized the having a mechanism for the trainer to communicate with the clients was an important aspect, which needed to be handled next.
Below are the requirements that were employed for this feature:
- send reminders to clients ~24 hours before their scheduled session
- send a workout summary after their workout
- resend a reminder for a session
- allow trainer to send a broadcast text message (e,g, “I am going to be on vacation”)
- provide a link to allow client to confirm/cancel their session (planned for a future article)
Since the concept of a mobile client is beyond the current feature roadmap, I needed to find a solution that would work with most clients. Knowing that each client was communicating with my sister-in-law via a mobile device, I decided to use SMS (or text messages) to provide a lightweight client for the application.
It did not take long to settle on Twilio — especially since two colleagues (roberttables and blendedsoftware) who broadcast on Twitch had been participating in Twilio’s “TwilioQuest” awesome learning experience. In fact, I would not be surprised if both still have videos on their channels of them playing the “TwilioQuest” game.
Twilio provides the functionality I need with a robust API. I was able to quickly set up a trial account (which communicates only with mobile numbers that are added to the system), but that was enough for me to validate the functionality.
Preparing for Twilio
The first step is to create a new account in Twilio by visiting the following URL:
Which should direct first-time users to a screen similar to what is shown below:
Once everything is setup, the Twilio dashboard will appear as shown below:
The Account SSID and Auth Tokens are accessible via this screen.
I wanted to configure Twilio programmatically in mode project, so that using my production instance of Twilio was based upon environment variables passed in from Heroku. Below is a list of the attributes that I am managing in my API:
README.md for my API repository provides the documentation details for the environment-specific values:
cron based items determine the schedule of the session reminder and session summary jobs which are running in each environment (if enabled).
Within Spring Boot, a simple
TwilioConfigurationProperties class was created:
With these values set up, I can use the Run/Debug dialog in IntelliJ IDEA to pass in the expected values:
In Heroku, these values are set up in the environment:
Keep in mind, the Heroku values are different, because that is actually the production instance that I have running.
The Sms Service
Within the SmsService, the following public methods are available:
These methods are called either by a scheduled task or triggered from a request from the Angular client. The next section presents and example of how the Angular client interacts with the Spring Boot service in order to communicate with the Twilio service.
Example – Sending a Group Message
Sending a Group Message is initiated by the Angular client. An example is shown below:
The request is passed to the following controller in Spring Boot:
GroupSmsMessage object has the following properties:
The controller then calls the following method:
In the code above, after checking for elements which can yield a Fitness exception, the
Twilio.init() method is called. Thereafter, a
Message is created and the logic has been included to function in production and non-production environments. This basically ties to using the provided trial phone number when not running in production. Everything else is straight forward and pass the data received by the Angular client directly to the target distribution list.
The goal of this article was to outline some client communication needs for the SaaS solution I am building. Thereafter, I provided an example of how easy it is to create a Twilio instance and integrate the solution into my Spring Boot service and Angular client. Using Spring Boot and an Angular client, I was able to quickly and easily get SMS communication configured in use within a matter of hours. In my view, Twilio provides an awesome compliment to the services I am using with Heroku.
From a cost perspective, my sister-in-law has been using the SMS functionality for right at two months now and I just added more money into my production Twilio account two days ago. At this point, the total usage has been right at $10 a month – which is far less than I expected to use.
In the next article, I plan to discuss how Twilio was used to send the session reminder, providing a mechanism where clients can confirm or cancel their attendance to this session. I had initially planned to include everything in one article, but I felt it would be better to create an article dedicated to this functionality. In another future article, I plan to dive into how an end-user’s reply to the original (Twilio) SMS can be redirected to the actual trainer for that customer. Exciting articles planned, for sure!
Have a really great day!