The GeoTrak (tm) platform is composed of a suite of application services focused on the tracking and visualization of reported geographic position data. It is largely intended to demonstrate the ability of a Quarkus microservice to effectively scale to meet the demand of hundreds to thousands of position reports being sent in from many different IoT sources.
The core components of the platform are:
- Trakker: the Quarkus microservice used for capturing reported position data. It accepts GraphQL mutations and pushes received events to a Kafka event stream.
- GeoTrak Server: a Spring Boot service which listens to the Kafka event stream written to by Trakker, consumes the reported events, and serves them to client(s) via GraphQL Subscription(s). These events are delivered asynchronously by the Reactive Streams Publisher & Spring WebFlux APIs.
- TrakkerJakker: a Spring Boot application which executes parameterized simulations of IoT calls. Uses randomizers to determine number of calls per execution, and to offset geographic positions for each subsequent call. Uses the Java ApolloClient library to execute GraphQL calls against the Trakker service.
I have always had an interest in geographic information systems and map-based data visualization, though I have had precious few opportunities to exercise this interest professionally. When I read the requirements for this Hackathon, I decided it would be the perfect chance to create something in this vein. I chose the IoT theme because of the potential to generate large amounts of geographic data that could be visualized using a mapping API like Leaflet, which I have used before. The concept was to build a Quarkus service that could stand up to massive demand from multiple connected devices reporting their geographic positions simultaneously. Deployed to a container management system such as OpenShift/Kubernetes, EKS or Docker Enterprise, the ability to rapidly scale out to many instances of the service would be invaluable for meeting this kind of demand. To this end, the Quarkus component I developed (trakker) has been compiled to a native executable on a container image that can be deployed into any of the above referenced platforms. I've pushed the image to my Docker hub account at eahollin/trakker. The source code is available on github at https://github.com/eahollin/trakker. The additional components of the GeoTrak (tm) platform, identified in the Summary, have been containerized as well for ease of deployment.
What it does
The GeoTrak (tm) platform supports large-volume tracking and visualization of geographic position data. Its domain model includes a GeoEntity, which is a producer of GeoTrak events. The GeoEntities have a unique ID and a Name, and the GeoTrak objects include a randomly generated UUID, the GeoID of the entity producing the event, and floats representing Latitude, Longitude and Altitude. GeoTrak (tm) currently only maps in 2D. The UI provides an interactive Map that displays the position data in realtime as it is produced. A User can execute various custom simulations which produce bulk position events that are immediately visualized on the Map. The User can also export the captured and rendered data in GeoJSON format for distribution to other systems.
How I built it
The centerpiece of the GeoTrak (tm) platform is the Quarkus-based microservice, trakker. I started with the basic Quarkus starter project, including some of the libraries I knew I would need, including graphql and kafka support. Initially, I tried to make trakker do too much, thinking I would implement full GraphQL-based crud of GeoTrak events. This quickly became overkill as I realized all the trakker service really needed to do was accept inbound events as quickly and efficiently as possible. In the end, I implemented a single GraphQL mutation for adding new GeoTrak events. The Quarkus service receives these events and pushes them to an outbound Kafka topic, which is configured using the Smallrye Kafka libraries. The resulting code is very tight and streamlined and blazing fast. One might even say, "supersonic".
The other components of the platform were necessary for supporting the Quarkus service. I needed a way of receiving the Kafka events and distributing them to consumers, which is the primary function of geotrak-server. Since I can't effectively produce GeoTrak events from many physical sources, I required a way of simulating this behavior, which was the impetus for creating trakker-jakker. Initially, this was going to just be a standalone Spring boot application with no web interface at all. Once I started working on the UI (geotrak), however, it became obvious that the ability to remotely invoke trakker-jakker via a REST call would be tremendously useful as it would allow for exercising the features of trakker from a single user experience. The JakkerPanel component of the React UI was one of the last pieces I built, so that I could effectively instruct trakker-jakker to run its processes directly from the UI.
Challenges I ran into
Initially, I intended to use an open-source project called react-leaflet for rendering and interacting with the Leaflet mapping capability. Unfortunately, I discovered early on that this was quite unwieldy in terms of managing state across the various components and getting the underlying Leaflet libraries to actually do what I needed them to do. In the end, and after reading some relevant forum posts from other folks experiencing the same problems, I resorted to a more brute-force approach of leveraging React capabilities for reference objects and callbacks, but within the callback methods, invoking various Leaflet API calls directly on the associated object(s). This allowed me to do alot more than I would have if I had continued to struggle with react-leaflet.
I was also a bit late to the party, only becoming aware of the Hackathon and beginning work on GeoTrak (tm) on July 6, almost 3 weeks after it had begun. Despite the tight time window, I believe I made significant progress, but I was unable to complete some of the more advanced features I would have liked to include. The framework I've built, however, should make future extensions much easier to incorporate.
Accomplishments that I'm proud of
Although the Quarkus service was the onus for the application, and shines as the most vital and efficient component, I am particularly proud of my work on the UI. Frontend development has never been my strong suit, so finding and effectively working with React component libraries and putting together a complete functional UI was very satisfying.
What I learned
I got a much better feel for creating native images with Quarkus. While I have had limited success during labs and demos in the past, this was the first time I was able to create an original service that can be reliably compiled into a native executable using a Docker container, then embedded in a container image for deployment to a live container management system like Kubernetes.
What's next for GeoTrak (tm)
A separate service is planned for management of GeoEntity objects (the simulated objects generating the position events), but this facility is currently being provided by the GeoTrak Server component.
I also plan to create more complex simulation algorithms that can be executed by the TrakkerJakker component. The current algorithm is very simplistic. My original scenario idea centered around many GeoEntities moving in a large group simultaneously, e.g. a "herd". I would also like to create a scenario where GeoEntities periodically cause the creation of a new GeoEntity at their present location, which then begins its own Trakker reporting in a separate thread. I would like to see the exponential growth that would occur in such a simulation. Most of these ideas require multi-Thread management and built-in timer delays to effectively simulate. I just didn't have time to implement some of the more ambitious features.