Building a Microservice in Perl (Part 2): Up and Running
In part 1, we designed our API using OpenAPI/Swagger. Now it's time to write some tests and wire it up using Mojolicious::Plugin::OpenAPI.
Join the DZone community and get the full member experience.Join For Free
If you haven't already, you'll need to install Perl. Using Linux or macOS? You've already got Perl installed on your system. On Windows? I recommend you install Strawberry Perl as it lets you develop Perl applications using the same tools that our Unix-based brethren use.
Once you have Perl installed, it's a simple matter of using either the
cpanm tools to install Mojolicious and Mojolicious::Plugin::OpenAPI. The latter will install some dependencies as well. Here's a transcript of installing
cpanm and the two modules:
(The versions listed above may differ as this article gets progressively out of date.)
Next, make a folder somewhere to place our new microservice project. We'll call it
~/Projects/blog here, but any place will do as long as you know how to get to it from your text editor and your command line.
After that, go into that directory and use the newly-installed
mojo command to build the basics of our project:
This command builds the scaffolding for our new project. We won't be using all of it, but it does provide some useful starting points.
(Why did we put
Local:: in the beginning of the name? Because nothing you place there will conflict with other modules you install from CPAN.)
Next, put the OpenAPI document we developed in part 1 somewhere in the project. We'll choose
openapi/dictionary_openapi.yml. Create a folder called
openapi in the project, and then open your text editor and paste the following document into a file called
Calling the Plugin
Right now all our application does is serve a demonstration page; you can test it by running the following command:
...and then going to that URL on the last line.
After you've verified that it works, hold down the Control key and type the letter C in your terminal to stop the script. Edit the
lib/Local/Dictionary/Microservice.pm file in your text editor. Replace it with this:
Now when you run the script as a daemon, the URL it reports responds with the JSON version of our OpenAPI document. Progress!
$self->plugin() call towards the end of our class above. That's the secret sauce that loads our OpenAPI document and tells Mojolicious to create responses from it.
Writing Our First Tests
Next, we'll write a couple test scripts. (Why are we writing tests before actually coding our microservice? Because we're practicing test-driven development, in which we write our tests first, see that they fail, and then write the code to make them succeed.) Here's a modified
t/basic.t script that should succeed right off the bat:
Run it with
Now for a test that will fail at first. Put this in
Note in the second line of output that Mojolicious tried to route to a controller class at
Local::Dictionary::Microservice::Controller::Word with an action of
save. That's what our OpenAPI document told it to do with its
x-mojo-to: word#save line.
Adding Methods to Make the Tests Pass
Now we'll write the controller class at
save method above retrieves the
definition parameters from the URL path and POST data, respectively, and then saves them into a hash that is
tied to a Berkeley DB file stored in
definitions.db. It then renders an empty response back to the client.
Now run the test:
Woohoo, our method works! Let's add some tests to the same
t/word.t script, underneath the first one:
Here we're testing that we get back the definition we saved, that we can delete the definition, and that when we try to retrieve it again we get a
404 Not Found error.
The test script will fail again, but we can fix that by adding the
remove methods to our controller class in
Run the test script one last time:
(As an exercise, write the
/health route defined in our OpenAPI document. It calls a
heartbeat method in a controller class named
- You may not want to store your definitions in a DB file in your project; consider making it a configurable option. Or use one of the many modules on CPAN to choose a completely different backend.
- Add methods to list some or all definitions, using hypertext as the engine of application state (HATEOAS) to render links where appropriate.
- Support multiple definitions of the same word, or expand the API to respond with synonyms and antonyms. (Just make sure to increment the version in the OpenAPI document and add some way for clients to specify the version to indicate you're making a breaking change!)
Did you have any trouble following along? Got stuck on the installation steps or somewhere else? Please leave a comment below and I'll try to help.
Published at DZone with permission of Mark Gardner, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.