Bootiful Vaccine Scavenger: A Tale of the Pragmatic Spring Framework

Link

https://springone.io/2021/sessions/bootiful-vaccine-scavenger

Author(s)

Greg Meyer as Director, Distinguished Engineer, Cerner Corp.

Length

25:30

Date

23-09-2021

Language

English 🇺🇸

Track

Beginner-Friendly Spring

Rating

⭐⭐⭐⭐⭐

  • ✅ A very impressive tale o a real application built on top of well-suited technologies able to ship into production quickly.

  • ✅ Introduction of Spring Cloud projects and alternatives.

  • ⛔ Incorrect usage of Stream API with a side-effect.

  • ⛔ Lack of time for deployment.


Taking an existing open-source Python project and then enhancing it and rapidly converting it into a production-grade application with the use of Spring:

  • Vaccine spotter is an application that allows you to pick up a location by a ZIP code and shows all the appointments available at local retail pharmacies with external REST API.

  • Vaccine watch is a Python bot application to query out to a specific region for un/available appointments and publishes those results out to social media networks like Twitter or Slack.

JWatch application

Architecture

The whole application is divided into a Consumer and Supplier on top of the common Spring Boot Configuration.

  • Supplier contains web clients to continuously call appointment APIs (Vaccine Spotter API and Proprietary Clinic API). The transformed business objects are handed up the stack o determine whether a particular appointment has already been published to our social media networks and then the state of that is stored inside Redis. A RabbitMQ queue is fed by appointments.

  • Consumer consumes RabbitMQ queue to push notifications to Twitter, Slack, and Email.

  • Spring Boot configuration profiles and conditional beans are used to enable/disable functionality inside the application so we could deploy separate instances of the application.

  • RabbitMQ is used, although it is a single application to break down the concern and make the application deployable.

Implementation

The main JVWatchAppliatinon class is annotated with @SpringBootApplication, @EnableReactiveFeignClients, @EnableRedisRepositories, and @EnableConfigurationProperties.

RestTemplaete class has effectively been deprecated in favor of configurable WebClient implementing reactive programming paradigm. Another way is using a reactive non-blocking Feign client through @ReactiveFeignCient annotation or Retrofit HTTP client as a part of the Spring Cloud Square project (incubator project as of the time of writing).

Feign client URL can be either hard coded, parameterized as a hardcoded URL, or a service name that interacts with some service discovery frameworks like Eureka.

Spring Cloud Streams framework can abstract us from knowing of implementation details of the underlying messaging system - the redesigned framework aligned with the Spring Cloud Functions framework which itself aligns with Java 8.

RabbitMQ (can be replaced with Kafka) is configured through spring.cloud.stream.* properties, spring.cloud.stream.function, spring.cloud.stream.bindings:

spring.cloud.stream.poller.fixed-delay=${jvwatch.checkTask.period}
spring.cloud.stream.function.definition=vaccineClinigDataSupplier;vaccineClinicDataSink
spring.cloud.stream.bindings.vaccineClinicDataSupplier-out-0.destinatnion=jvwatch-clinic-data
spring.cloud.stream.bindings.vaccineClinicDataSink-in-0.destinatnion=jvwatch-clinic-data
spring.cloud.stream.bindings.vaccineClinicDataSink-in-0.group=jvwatch-clinic-data-sink-group
spring.cloud.stream.bindings.vaccineClinicDataSink-in-0.consumer.concurrency=1
spring.cloud.stream.bindings.vaccineClinicDataSink-in-0.consumer.maxAttempts=4
spring.cloud.stream.bindings.vaccineClinicDataSink-in-0.consumer.backOffInitialInterval=15000
spring.cloud.stream.bindings.vaccineClinicDataSink-in-0.consumer.backOffMaxInterval=60000

There are defined beans @PollableBean Supplier<Flux<ClinicData>> vaccineClinicDataSupplier() and @Bean Consumer<ClinicData> vaccineClinicDataSink() where @PollableBean means that the supplier function gets executed on a configurable interval and its returned object then gets mapped into a messaging object that’s bound to a destination like a topic ora queue in the underlying messaging system.

Spring Boot configuration allows configuration files with properties prefixes such as:

@Configuration
@Configuration(prefix="jvwatch.notifications.twitter.oauth")
@Data
public class TwitterConfigProperties {

    // Code
}