Spring Boot Apps With Spring Cloud Config

It is not uncommon for a Java application to have a number of properties that needs to be defined for it to to run smoothly at start. While these configurable parameters that are required by the app can be set in the code, placing those outside is a more logical and cleaner approach. Things like the JDBC URL of a database, perhaps REST API endpoints, or OAuth stuff for example. These however are normally only read when the Java application boots up.

Typically these application parameters are placed outside of the code not because it has to be done that way, but I’d rather prefer it like that since it certainly has benefits. It especially becomes all the more helpful when some properties need changing. Having the proverbial eggs in one basket, this time, makes it more convenient. These simple key-value pairs are commonly placed in a configuration file with the .properties file extension (e.g. application.properties), or a XML/YAML equivalent (e.g. application.yml), located in the resources folder of the Java application.

There are configuration parameters that are not expected to change in the course of an application’s runtime at all. Then there are some that might. In my experience it does not happen that often, but it still does. When it does so – and there are more than a handful of applications, with all the hoops a team has to go through to get it back to production just for minor but necessary property changes – maintenance can become ugly. Not to mention it takes longer than desired.

This can be avoided perhaps. I don’t know. Maybe pull somewhere from an external data catalogue that can then be cached and polled every X minutes? Via REST API requests? Or the tried and tested database? Whatever it may be, these options might be overkill. There is also that overhead for constantly querying properties that are not anticipated to change that frequently. Then again, is having something like a Spring Cloud Config not? After all, the point is to have it all in a centralized location, easy-ish to manage, and avoid a re-deploy in case updates are required. So what makes it different?

Well, aside from the trend of “everything to the cloud” nowadays, I am not really sure.

Spring Cloud Config

I’ve only just wet my feet on this Spring Cloud Config thingie. At first glance, it seems an additional layer of maintenance for all the moving parts that entails in order for this solution to function to its full potential. Here is what I’ve understood so far.

For one, setting up a bare minimum Spring Cloud Config Server ready is almost trivial. Sure, you have to read through a lot of documentation to be able to use all those wonderful features. Trial and errors to do. But getting it up and running is not really that hard. This is a win.

Create a standalone server as a Spring Boot app and annotate it with @EnableConfigServer, a few configuration lines, plus a simple git repository local or otherwise, and there we go. Deploy it, have your apps point to this server, after the necessary unavoidable integrations are made (that should be one-off).

This becomes even easier when the infrastructure to support this server are already there. Many enterprises already have that one way or another nowadays, I guess. The mass shift to the cloud has made it so. Red Hat OpenShift/Kubernetes? Yes. Repository providers like GitLab or BitBucket. Check. How about AWS? Of course.

Not surprisingly, the Server can do many more things. To secure endpoints. Encrypt properties in transit and at rest. Have a more complex repository setup. The list goes on…

It’s just annotations!

On the client side of things, integrating Spring Cloud Config is not very invasive code-wise. Include the Spring Cloud Config Client library into the application is step one. A few additional properties in the configuration file of the client app (Ironically!) so it will know where to find those other properties. An exponential retry can be had in case the config server is unavailable. Probably have more than one server defined for high availability, so it can iterate through the list until the app can connect to one.

Luckily, when @ConfigurationProperties is used by the app to get specific properties from the configuration file not much code changes will be necessary. Property changes will be picked up on the next refresh.

If the following code snippet is, however, scattered all over the codebase then the @RefreshScope annotation must be used on that class. Otherwise, the client app won’t be able to get the changes.

    @Value("${vars.role}")
    private String role;

When to refresh?!

I have to mention though that I got a bit of a surprise that picking up modifications to properties from the server is not automatic. The client application won’t know if there are changes or when to refresh at all. There is no polling being done out of the box. The server won’t readily tell its clients it’s time to refresh too. Not without another layer of technology to do that anyway.

Wait, it gets a bit more complicated?

The client app picks up the new changes via a “refresh”. So it falls on the client to trigger that refresh. The basic is to activate the /actuator/refresh endpoint client-side. Call that endpoint via an empty POST request. Then the client will contact the server to check for any changes, download them when there are, then updates the application context for these modified properties.

Sounds pretty quick and easy. Maybe not so much when you have to do all those POST requests to several pods running on your Kubernetes clusters by hand. Nor will picking which clients to refresh instead of a blanket refresh for all. Then you have to remember to trigger the refresh. That could be easily overlooked on any busy day (One team updates the repository, another does the work of refreshing what apps need to be refereshed).

That’s where other technologies come in. Like the Spring Cloud Bus. I’m not still clear how Push Notifications via a webhook (which many repository providers are capable of) works with or without Spring Cloud Bus. It looks like it is required. Then there is another method of having clients get the refresh event via a message broker such as Kafka. Still via Bus. Need to do some reading up and some tests on both of these approaches. But once either of these are configured, the only deliberate effort left to do is when revisions are to be made to any one applications’ properties in the repository.

Similar Posts: