| | |

Microservices at Bench: Microapps

By Stefan Bleibinhaus on
Microservices at Bench: Microapps

Introduction

Most of the services in our microservice oriented architecture at Bench are purely used within the back-end. They communicate via Camel messages and REST calls and do not offer a user interface on their own. They are the small little workers in the background dedicated to their job. Their functionality is indirectly exposed via our web front-end.

Since a big part of our business is doing what a traditional bookkeeping firm does but better, we look at everything from customer intake to preparing documents for tax accountants as one workflow that we should improve on. As a result, we often identify problems that are unrelated to our primary bookkeeping software that can make our employee’s lives much easier. In those cases, microapps allow us to quickly iterate on ideas and requirements that come straight from any of our departments.

An example is the sales-service; a microservice with a user interface that allows our sales team to coordinate incoming leads in a more efficient and scalable way. At Bench, we call these microservices ‘microapps’, and in this post we’ll cover the technical choices we made to implement them.

 

Spray on the Back-End

The bench-service.g8 template gives us a great starting point to develop the back-end of the new microapp using Scala, Spray, and Akka. Now all we need to do is add the necessary logic and REST API like in any other microservice.

Another option would have been to go with Play instead of Spray. If we used Play we would have the advantage of a full-fledged Scala framework for web applications.

However, using Play would  also mean that the front-end and back-end code are bound more tightly together, and the technical choices for the front-end are limited to those which work well with Play. A consequence of the dependencies between front-end and back-end code is that it is harder to split up the project if the app becomes bigger, or you want to scale the back-end by having more instances of the service. The dependencies also mean more effort working in parallel on the project (e.g. one back-end and one front-end developer). Having Scala code in the front-end also means that a front-end developer not familiar with it has a harder time making changes to it.

Using Spray is advantageous because our back-end developers are familiar with the framework as we are using it as the base for most of our Scala microservices. Our shared libraries (e.g. for security) also define the most commonly used Spray routes and directives which can be easily integrated in any of our Spray projects.

 

Front-End with AngularJS

For the front-end we create a folder named ui-source on the top level of the project. Within the folder we apply a Yeoman script to generate the template of the front-end. For the sales-service we have been using this AngularJs generator with the Coffeescript option.

The advantage of that approach is that the code for the front-end can be completely independent developed from the back-end using all the familiar front-end tools like Grunt and Bower.

By setting the distribution folder of Grunt to ../ui/dist as shown in the code snippet below, we do not need to commit the built distribution files. It also allows us to serve the front-end files from Spray without the risk of exposing raw unprocessed source files.

var appConfig = {
   app: require('./bower.json').appPath || 'app',
   dist: '../ui/dist'
 };

After adding the built front-end files to the resources classpath of the Spray application in build.sbt with the line

unmanagedResourceDirectories in Compile += baseDirectory.value / "ui"

we can easily serve the front-end via a Spray endpoint:

class UiRoutes(implicit ec: ExecutionContext, log: LoggingContext, system: ActorSystem) extends ApiRoute {

  val route: Route =
    pathPrefix("web") {
      getFromResourceDirectory("dist") ~
        redirect(Uri("/web/index.html"), StatusCodes.Found)
    }
}

 

Deployment

Thanks to the previous steps and our already established process for microservices at Bench, the deployment is now rather simple. We just need to make sure  that the most recent front-end code is part of the assembled jar file.

We are using Jenkins to build and upload our artifacts to Amazon’s S3 which will then be deployed within Elastic Beanstalk. Our Jenkins uses the assembly task of Sbt to create the jar file and as we added the ui folder to Sbt’s resources classpath all we need to do is make Jenkins build the front-end before running Sbt assembly. The commands we use to achieve that are:

cd ui-source
npm install
bower install
grunt build-production --force

 

Conclusion

This is just one example of how we do a microapp. Scala with Spray is a great choice because it allows us to reuse our common libraries, but they can be in any language; we even have a few running in node. Due to our microservices architecture, microapps can easily be integrated to our overall architecture.

Our approach is tailored to our specific needs, so it might not work for everyone. However, if you do happen to need a quick JVM based app that can be easily scaled in production, give our template a try, and feel free to leave us a note on Github or through email if you have any comments or feedback.