0

I have been evaluating the support of Spring Boot 3 for native compiling with native-image and so far I am very impressed. It has the potential to drastically reduce our cloud spend.

I note in the documentation, one of the major changes is the "closed world" assumption, meaning things like @ConditionalOn... are evaluated at build time rather than compile time.

To give a common example, I have an EmailSender interface and I have three implementations of this, for example LoggingEmailSender, SmtpEmailSender and SendGridEmailSender. Currently when running on the JVM the correct Bean for the environment will be created, LoggingEmailSender for local, SmtpEmailSender for test and SendGridEmailSender for production.

I am unsure what the best approach is to migrate this kind of conditional logic over to a Spring native way of doing things.

Currently the only option I can see would be to compile a binary per environment and use scopes at build and runtime to enable different implementations. This would result in a few different Docker images being created and deployed to their respective environments which breaks the previous conventions of promoting the same containers through various QA, Staging and then Production environments.

Is there a recommend strategy that I have overlooked or is this the best option available with the current level of maturity of native support?

  • Are you actually using `native-image` for development? Or is `LoggingEmailSender` always used without `native-image`? And when saying "testing", are you talking about some sort of staging environment? – dan1st Jan 18 '23 at 09:14
  • Not using native-image for development, would be far too slow. In our staging environment we use a service called Mailtrap that will catch all outbound mail to prevent anything being sent to "real" users. This uses SMTP. In production, we use SendGrid for sending our transactional emails, and this uses APIs. So currently we use @ConditionalOn at runtime to load the correct email implementation based on either SMTP credentials or SendGrid credentials in the environment. – william00179 Jan 19 '23 at 06:17
  • Well, you only need to compile two binaries - one for staging and one for production. – dan1st Jan 19 '23 at 09:07
  • Unfortunately its not quite that simple as there are a few other implementations that vary based on where its deployed, so would need to compile the various permutations. I think will need to wait for some support of runtime implementation selection to be supported. – william00179 Jan 25 '23 at 07:15
  • So you have more environments than just development/test/production? – dan1st Jan 25 '23 at 07:19

1 Answers1

0

As far as I know you can override properties for Spring Boot native applications too based on the run environment. And isn’t it possible you would rethink your bean creation a bit only. Drop the bean(s) conditional creation and have one create method for EmailSender only. In this method you should be able to create different implementations for this interface, it is interface right, based on property value you read too.

harism
  • 6,011
  • 1
  • 36
  • 31