This post is a continuation of Centralized and versioned configuration using Spring Cloud Config Server and Git where I covered the Spring Cloud Config server to prevent hard-coding properties that most-likely would be different for each deployment environment.
At the end of said post I outlined how updating a Git-backed property and sending a POST request to the client application’s
/refresh actuator endpoint caused the configuration property to be reloaded and the dependent Spring beans to be refreshed picking up the new value.
But what if it’s not just one or two microservices but maybe dozens or even hundreds that would need to reload those properties changes? Hitting
/refresh for each one doesn’t seem like an elegant solution. What if the numbers of instances keep growing?
In this post I’ll extend the Spring Cloud Config Server and the client service implemented in part 1 with Spring Cloud Bus and RabbitMQ support and a Bitbucket webhook to automatically notify subscribed client services of changes in the Git-backed configuration files.
1. MULTI-TENANT APPLICATIONS USING SPRING BOOT, JPA, HIBERNATE AND POSTGRES
Multitenancy is an approach in which an instance of an application is used by different customers and thus dropping software development and deployment costs when compared to a single-tenant solution where multiple parts would need to be touched in order to provision new clients or update existing tenants.
There are multiple well known strategies to implement this architecture, ranging from highly isolated (like single-tenant) to everything shared.
In this post I’ll review configuring and implementing a multitenancy solution with multiple databases and one API service using Spring Boot, JPA, Hibernate and Postgres.
Spring’s RestTemplate is one of the options to make client HTTP requests to endpoints, it facilitates communication with the HTTP servers, handles the connections and transforms the XML, JSON, … request / response payloads to / from POJOs via HttpMessageConverter.
By default RestTemplate doesn’t use a connection pool to send requests to a server, it uses a SimpleClientHttpRequestFactory that wraps a standard JDK’s HttpURLConnection taking care of opening and closing the connection.
But what if an application needs to send a large number of requests to a server? Wouldn’t it be a waste of efforts to open and close a connection for each request sent to the same host? Wouldn’t it make sense to use a connection pool the same way a JDBC connection pool is used to interact with a DB or a thread pool is used to execute tasks concurrently?
In this post I’ll cover configuring RestTemplate to use a connection pool using a pooled-implementation of the ClientHttpRequestFactory interface, run a load test using JMeter, troubleshoot requests timeout and reconfigure the connection pool.
1. CONFIGURING TOMCAT TO LISTEN ON MULTIPLE PORTS USING SPRING BOOT
Today I landed in a stackoverflow question about how to access the JavaMelody UI using a port other than the one used by the APIs. I went ahead I answered the question with some initial code I had for another blog post I’m working on but then decided to make it its own post.
While this could certainly be accomplished adding a couple of Spring Boot configuration properties: management.context-path and management.port to
application.yml for instance, and reuse the same path used for actuator endpoints (
/admin/health, …), there might be some cases where having the servlet container listening on a port other that the two mentioned earlier might make sense, maybe for monitoring, traffic analysis, firewall rules, etc..
In this post I’ll add support for configuring embedded Tomcat to listen on multiple ports and configure JavaMelody to exclusively use one of those ports to display its reports using Spring Boot.
The previous blog post covered Service Registration and Discovery as an infrastructure service used in a microservice architecture. In this post I’ll review another infrastructure microservice, the Configuration management service.
Configuration is used to prevent hard-coding values in the applications. But it’s also used to specify what is expected to be different between deployment environments (qa, staging, production, …) such as host names, mail and database credentials and other backing services. The latter type of configuration is identified as one of the elements in The Twelve-Factor App.
The benefits of this practice are that it promotes building only one artifact, only one binary to be executed in all the environments. You should never have to build a different executable for each environment, this will most-likely cause troubleshooting and debugging headaches.
As part of the Spring Cloud Series, this post describes the Spring Cloud Config’s server and client usage, the configuration storage options and its relation with the Discovery Server in a registration-first and configuration-first approaches.
1. MICROSERVICES REGISTRATION AND DISCOVERY USING SPRING CLOUD, EUREKA, RIBBON AND FEIGN
This blog post reviews an implementation pattern used in microservice architectural style: Service Registration and Discovery. The Discovery service and Configuration service, the latter discussed in this post, are most-likely the first infrastructure microservices needed when implementing such architecture.
Why is the Discovery service needed in a microservice architecture? Because if a running instance of service X needs to send requests to a running instance of service Y, it first needs to know the host and port service Y runs and listens on. One might think that service X may know this information via some static configuration file but this approach doesn’t sound very practical in an elastic-like distributed setup where services are dynamically (de)provisioned, triggered either manually or by some condition such as an auto-scaling policy or failure for instance.
Continuing with the Spring Cloud Series covered in this blog, this post discusses Spring Cloud Netflix’s Service Discovery component, a Spring-friendly and embedded Eureka server where services instances can register with and clients can discover such instances.
1. INTEGRATION TESTING USING SPRING BOOT, POSTGRES AND DOCKER
The integration testing goal is to verify that interaction between different parts of the system work well.
Consider this simple example:
Successful run of this integration test validates that:
- Class attribute actorDao is found in the dependency injection container.
- If there are multiple implementations of ActorDao interface, the dependency injection container is able to sort out which one to use.
- Credentials needed to communicate with the backend database are correct.
- Actor class attributes are correctly mapped to database column names.
- actor table has exactly 200 rows.
This trivial integration test is taking care of possible issues that unit testing wouldn’t be able to find. It comes at a cost though, a backend database needs to be up and running. If resources used by the integration test also includes a message broker or text-based search engine, instances of such services would need to be running and reachable. As can be seen, extra effort is needed to provision and maintain VMs / Servers / … for integration tests to interact with.
In this blog entry, a continuation of the Spring Cloud Series, I’ll show and explain how to implement integration testing using Spring Boot, Postgres and Docker to pull Docker images, start container(s), run the DAOs-related tests using one or multiple Docker containers and dispose them once the tests are completed.
1. DOCUMENTING MULTIPLE REST API VERSIONS USING SPRING BOOT, JERSEY AND SWAGGER
A few days ago I was completing the accompanying source code for Microservices using Spring Boot, Jersey, Swagger and Docker blog entry and found some problems while adding documentation support to multiple implementation versions of the “Hello” JAX-RS resource endpoints where the version information was passed in the URL or Accept Header.
Recapping the details, I stated my belief that Swagger’s BeanConfig singleton instantiation approach wasn’t going to work. The reason I believe so is because a BeanConfig instance dynamically creates only one Swagger definition file and it would require one definition file for each version. Yes, there are some “hacks” to get away with it, like removing the endpoints implementation where the version is passed in the Accept Header and then only one Swagger definition file will include the documentation for every endpoint implementation version. I don’t think this is the right answer though.
This post and its accompanying source code will tackle on this issue and demonstrate how to generate multiple Swagger definition files to feed Swagger UI to display JAX-RS APIs documentation for multiple implementation versions.
1. MICROSERVICES USING SPRING BOOT, JERSEY, SWAGGER AND DOCKER
Having used Spring for some years, I was impressed how easy it is to develop Spring-based apps using Spring Boot, an opinionated framework favoring convention over configuration and more impressed how easy it is to build and use common components of distributed systems using Spring Cloud which is built on top of Spring Boot.
Microservices has been a hot topic for a couple of years now, defined as a software architectural style to compose applications from a set of small and collaborating services each one implementing a specific purpose.
This and the other posts in this series are more of a hands-on experience once it has been decided to implement some solution using this pattern. This post won’t cover the trade-off using Microservices or Monolith First as discussed here and here or Don’t Start Monolith school of thoughts. Please follow these links or browse the REFERENCES section if you are also interested in these concepts or debates.
A few days ago I was setting my development environment up and it involved executing some Apache Ant tasks. I had installed latest Java 7, jdk1.7.0_80 to be exact and Ant 1.8.4, required by the project.
Attempted to compile it and got this output: