Sharing routes and running multiple Java services in a single JVM with Undertow

Microservices has become an industry standard term and everyone is jumping aboard the hype train. There are definitely pros and cons in both building and maintaining microservices, however, they will not be discussed in this article, just remember you are not Google. We are going to show some options for sharing endpoints across services as well as run multiple services in a single JVM.

Services

Since we are talking about code reuse, let's grab our RouteHandler's from two previous examples to demonstrate. We will be using our lightweight REST server example as well as the simple content types example. To start we are going to run each of them as their own stand alone service on their own port.

Combining RoutingHandlers

A simple use case for shared routes would be ping / healthchecks / server status that all of your services might share. We don't have one prepared so use your imagination with our existing services. With RoutingHandler.addAll we can combine both RoutingHandler's into a single RoutingHandler and have a server listen to all of the routes on a single port. This allows us to combine common code across routing handlers or even run multiple micro services together under a single port (see next section for some reasons why you might want to do this). The biggest concern here would be conflicting routes across RoutingHandler's may overwrite other routes if they share the same verb / path.

One Server Listening on Multiple Ports

Testing microservices, especially ones that depend on other services to be up can be quite the pain. You either need to run N services in your IDE / command line or possibly set up something like docker so it is easy to reproduce. With each of these sometimes you need to remember which order to start each service in, yikes lots of fun. If all of our services are Java based and use the same dependencies we have another option. We already showed that the services could be combined into a single RoutingHandler. Maybe this doesn't meet your needs and each service is split by port and expects everything to work that way. Undertow has you covered, we can run multiple ports in a single undertow instance.

Note: If you have proper loose coupling both of the servers shouldn't be accessible from the same maven / gradle project so what do we do? Just make a new module that includes both server modules. This is not ideal and not necessarily recommended for prod since there could be some dependency issues. However if the dependencies line up across services (not such a bad thing to enforce especially on smaller teams / code bases) we can make such a shortcut. Whether you run this way in prod to reduce OPS work or only run this mode in development to save time is up to you. If you have a low traffic app running them together might make perfect sense. You would essentially have microservice ready code which can easily be split out into its own service when needed but for now it just shares the same CI pipeline, deploy script, and servers.