Beanstalk and Spring Boot profiles
Intro
As I mentioned previously, I've been working on a simple spring boot application and looking for some cheap hosting options. I've tried GCP but there was no chemistry between us. So, I tried with AWS.
Beanstalk
This is Amazon's equivalent to Google's App Engine; you have some code that you want to run without focusing too much on the infrastructure, and want some easy to use scaling options. As usual, it supports several runtimes/languages one of them is java. Sweet. Note that Beanstalk is only a wrapper around other amazon offering; it actually creates EC2 instances, provisions them, perform any necessary runtime preparation, ...etc.
Spring Profiles 101
Going back a bit, my application - like any sensible application - has several external properties, and some of them are secrets. So, I externalized them into properties. So now I have an application.properties file containing all of my properties (using spring boot default naming conventions). But what about keeping my properties secret? I have been using Github to host my code and didn't want to commit my secrets there. Also, some cloud providers have different requirements (Amazon's Beanstalk requires my application to listen on port 5000). Enter spring profiles.
Spring profiles in essence is me defining a flag (or several) passed at runtime that is used determine what configuration files to include or exclude. These flags are alphanumeric strings usually used to differentiate between the different environments the application can run in. Imagine building a single war containing the configurations for local, test and QA, and production environments. Each environment at runtime will pass the flag indicating which environment it is, and spring will pick up those flag and select the corresponding files to run the application.
You don't need to define these profiles; i.e. application-local.properties is the properties file that will be picked up only if the profile is local while application-cloud.properties will only be picked up if the profile is cloud. But how to define the active profile? Several ways exist. You can specify it programmatically (your code itself will set the correct active profile), using maven profiles to trigger spring profiles, using properties, by passing command line arguments or even environment variables.
The Story
So, I set the profiles as I wanted them (local and cloud), uploaded my jar to Beanstalk, added the corresponding env variable and ...... FAIL. Checking the logs, spring is not picking up the active profile, and it is using the default profile (aptly named default :)). No profile, no correct properties and my application won't even start correctly (yeah, I could've added some fault tolerance there but nah for now). Digging deeper time.
The Setup
In order to start quickly, I was using beanstalk WEB interface directly (not the CLI). I uploaded the jar and set the active profile under configuration > software > Environment properties. There were lots of mixed signals here; some docs refer to the property as SPRING_PROFILES_ACTIVE, while others insist on using spring.profiles.active. I tried both to no avail.
The Eureka Moment
After wasting the better half of a day, I remembered that I was using Java 11 (since I tried to upload to GCP first and that upgrade stuck). So, I created a new beanstalk environment using java 8, and repeated my attempt. It worked.
PS: the correct flag for java 8 is SPRING_PROFILES_ACTIVE.