To demonstrate how easy it is to parse AIS messages (what is an AIS message?) with my open source library AISmessages, this post shows how to create a Spring Boot based microservice which can receive NMEA strings via HTTP and respond with the decoded AIS messages in JSON format.
So – for an HTTP request with a JSON array of NMEA strings like this:
… we would like a response like this:
Initializing a new Spring Boot project
A quick way to build such a service is to use Spring MVC. So, first we need to initialize a new Spring Boot project. An easy way to do this is to visit https://start.spring.io and fill in the form like this:
Generate and download the resulting project. Then move it to a suitable directory on your machine and unzip it like this:
As a smoke test we will first build new freshly, unmodified project - this is done with Gradle like this:
With the boiler plate project just built, we should see that it runs:
All seems well. The Spring MVC web application is running - but not doing much useful yet.
Adding custom code
Adding AISmessages as a dependency
The first thing we will do, is to add AISmessages as a dependency. This is done by adding this line into build.gradle:
Adding Spring MVC Controller
Next we will add the Spring MVC controller which handle incoming HTTP requests. This controller should be able to receive a JSON array of NMEA strings and output a JSON array of AIS messages.
So, in folder src/main/java/dk/tbsalling/ais/decoder/ we add file AisdecoderController.java like this:
This class is discovered by Spring through classpath scanning at startup, and handles incoming HTTP POST requests headed for URI /decode - such as http://localhost:8080/decode. The current implementation is mostly boiler plate and does nothing useful.
What we want it to do, is to call a service class which can convert the received NMEA strings into AIS messages. Like this:
Adding AIS decode service
Then we need need the AisdecoderService. This is the most custom part of the code and where the real work happens. It should receive a list of n NMEA messages, convert and return these as a list of m AIS messages.
We start by adding to src/main/java/dk/tbsalling/ais/decoder/ the class AisdecoderService.java:
So - how do we implement the decode method? The key here is class NMEAMessageHandler from AISmessages. NMEAMessageHandler is a class which can keep consuming NMEA messages and perform a callback whenever the received messages result in the successful decoding of a complete AIS message. Sometimes NMEA messages and AIS messages correspond 1:1 - other times it takes 2 NMEA messages to decode 1 AIS message.
So - we will extend AisdecoderService like this:
Now the decode()-method initializes a NMEAMessageHandler. This handler is handed this (the decoder itself) to that it can make callbacks whenever an AIS message is fully constructed. To be used for callbacks, the AisdecoderService needs to implement the Consumer<AISMessage> interface.
Next, we need to start feeding the NMEA messages to the NMEAMessageHandler. One way to do that is this loop which iterates over all the NMEA strings and passes each one to the NMEAMessageHandler:
Everytime the NMEA message handler can put the NMEA pieces together a complete AIS message, a callback is made to the AisdecoderService#accept(AISMessage msg) method. This method needs to store i AIS messages in a list, so that they can be returned by the decoder later:
Finally, in the decode() method, we must deal with the situation, where there are no more NMEA messages. This calls for a flush of the NMEAMessageHandler and return of the collected AIS messages:
The complete code resulting from the above can be viewed on Github: https://github.com/tbsalling/aisdecoder/tree/ready/spring-boot-webservice
Run it yourself
The code can then be cloned, compiled, run and invoked like this: