About the project
The SPiD team, that I am currently working for, was established in STP in September last year. Since the beginning, our goal is to build a payment platform, that integrates various payment types. We have just had first production release in June this year, and the scope of that release included some basic functionalities.
The main objective now is to provide a functionality of Peer-to-Peer payments. This also requires some surrounding features like depositing money into the system using credit card, transferring it between the users, or withdrawing it to the real bank account. When the system is stable and gets broader audience we plan to extend it with new features and payment types. In order to fulfill our goal we also need to provide a custom user’s wallet solution – that is something similar to Google Wallet.
Our decision was to be cloud based and use Amazon Web Services like EC2, SQS queues, S3 and their other goodies. One of our main concerns about building that platform was to make it as flexible and agile with developing new services and functionalities as possible. When we concluded all our objectives, it occurred that the most appropriate, and probably the only right solution for us was to take the microservices approach.
Our system is built of several different modules. Most of them use REST to communicate with each other. As it is for now, we have 3 types of components:
- Order/Payment module – the main entry point of the system, something like a governor for other services. That will be the only public component that is meant to be used by end users of the platform. It handles all requests from the users and perform proper operations on other internal components.
- PPAs – which in our terminology means Payment Provider Adapter. Each of these components is responsible for communication with the provider of particular payment type. These providers are called PSPs (Payment Service Provider) in our dictionary and most of them are 3rd parties, but we also built one called SpidCash – which is responsible for handling users’ wallets. Every PPA uses a different communication protocol to reach its vendor. As presented on the design picture – Telepay PPA, supporting withdrawal of money to the real bank accounts, utilizes SFTP, Klarna PPA, which handles invoice transactions, uses XML RPC, Payex PPA, that serves credit card transactions, is based upon SOAP and finally our internal wallet solution – SpidCash – uses REST.
- Callback server – this is the third type of our services – its only responsibility is to expose an endpoint for callback communication from PSPs, and pass that information to a particular PPA, using SQS queues. PPA will handle that message and, if needed, pass it down in the flow to other components.
As presented in the picture below, some of our modules are based on Spring Boot (referred to as SB) and some on Dropwizard (referred to as DW). Initially the platform skeleton was based only on Dropwizard, but since it is a microservice world, we decided to try Spring Boot for new services, and hence we can compare how we feel about working with both of them.
This project was founded first. In overall I would say DW is just a little bit of glue code between popular libraries that were commonly used in web apps development for a while, and nothing more than that. It does not come with any enterprise heavy stuff, that could probably slow it down. It is incredibly fast and easy to learn. It glues Jetty – for HTTP, Jackson – for JSON, Jersey – for REST, optionally Hibernate or JDBI – for persistence support, Metrics and others like Guava or Logback.
It is nicely aligned with the microservices way of thinking. Its authors had this brilliant idea with revolutionary way of building and running web applications. DW allows you to build one jar, that contains all needed dependencies, so that means you do not have to deploy it inside any specific application container or server – it is runnable from a basic console with use of java –jar.
Spring Boot (SB)
When DW was born, Spring Framework was already somewhere out there. It was very popular and had a well grounded position in Java web dev world. Due to the complexity of Spring Framework, DW was much easier to use with microservices. To be honest, when I was learning Spring few years ago, it was quite difficult, and it took me some time to feel comfortable with it. There were tons of XMLs and other configuration that had to be done in order to run your application. They needed something to lower the threshold of entrance, which was very low in Dropwizard.
Maybe one day, one of the Spring team sat down, looked at what DW offered and got really amazed. They were so amazed that they told their colleagues “Hey, we should definitely go that way, because that is how people want to do things right now”.
And they did. They adopted many of DW ideas – for example the concept of self-runnable jar with all dependencies or healthchecks support. They called it Spring Boot, and I would say it was rather an evolutionary step in Spring Framework history. They didn’t clone Dropwizard – they adopted these nice ideas to their existing platform, so that when using SB you would’t loose any of Spring Framework power and abilities it had before.
I was thinking a bit about some metaphor for these two frameworks, and the best one that I came up with is based on Marvel characters.
I can identify Dropwizard as Spiderman – it is just a regular guy from our neighbourhood that has perfect combat skills, and simply glues some things together.
Spring Boot on the other hand, can be considered as the Iron Man – a billionaire with the latest high-tech stuff packed inside one well suited armor, that may look heavy, but somehow doesn’t cause any agility and quickness issues.
Let’s return back to the project and present areas which are important to us, that will be used as comparison areas of Spring Boot and Dropwizard:
- REST support – our components use REST for internal communication. We also expose RESTful API to our clients.
- DI support – it may be controversial right now, because of the trend to get rid of such features, but inside our team we agreed that we like it, and we can get great benefit out of it.
- Persistence Support – we don’t want to create SQLs, and extract result sets manually because we store high amount of various type of data. That’s why we need an ORM.
- Transaction support – we have some volatile areas in our platform that need to be handled inside transactions and it is good when we don’t have to create them manually.
- Configuration management – since we are cloud-based and have multiple running environments we need good way to manage module configuration.
- Dependency management – one of our main objective is to compile our modules with maven-enforcer plugin, and we invest our time in order to have a clean classpath and to omit dependency hell.
- Metrics – we want to have an insight into our application and gather some stats, so any kind of support for it is very appreciated.
- Good Community Support – it is quite obvious that sooner or later you will need somebody to give you a hand with doing something, and that is very important to have live community around frameworks that you use.
As mentioned above, we use REST for communication between our microservices. To achieve this, we decided to use the Jersey 2 library, because it is fully compatible with JAX-RS. One of our principles is that – whenever possible – we should code towards specification, rather than be tightly coupled with one of libraries.
Starting from Dropwizard – when we entered a project, there was already a basic skeleton created with the latest version of DW at the time – version 0.7.1. However, the problem was that this version was tightly coupled with the legacy version of Jersey – 1.18, which was not compatible with JAX-RS. We tried manually to make it use Jersey 2, but we did not succeed and we gave up. There was also a note from DW authors that they planned to integrate Jersey 2 in the next release of their framework, so we decided to wait. Finally, their kept their word, because in March 2015 we migrated to the newest DW 0.8.0 at the time and it came with Jersey 2 on board, so it solved our problems.
On the other hand, Spring Boot by default comes with its own solution for exposing REST endpoints, which is Spring Web MVC. We did not want to use it, because it also is not compatible with JAX-RS. We tried to integrate Jersey 2 inside a project based on Spring Boot and not only it was possible, but also quite easy. What is more, starting from 1.2.0 version Spring Boot has integrated support for Jersey 2 (sample configuration can be found here), so it is even easier right now.
To conclude this area, I would say that if you asked me few months ago about this topic, my answer probably would be that Spring Boot is more flexible and gives you a freedom of choice, but now the situation changed, and these two frameworks are quite similar and even looking from that point of view.
Another important feature of such frameworks is the possibility to use it with some Dependency Injection solution. Even though we strived to keep our microservices small and simple, we found using DI very helpful. From the start I want to mark that comparing Dropwizard and Spring Boot from DI support perspective may be a bit unfair, since DW authors probably did not intend to use it this way – there is no single word about it in official project docs. Hence, there is no official package with integration of any existing DI solution, but there are some built by community. The most popular one is dropwizard-guice, and it is an integration with Google Guice, that is also supported by community right now.
We do not like to use beta or snapshot version of any libraries, but at the time we started the implementation of microservices based on DW, the only version of Guice that was possible to use with Java 8 was Guice 4.0-beta5.
To be honest that solution was far from perfect. There were many bugs in that integration – for example these connected with two modes of Guice: DEV and PROD, that differed on how they initialized components (DEV it lazily, during first call to particular component, PROD inited everything at startup). Since we wanted to use some of the application properties at startup in our code, we needed to stick with the DEV setting, otherwise we would not be able to do this. That is not something that you want to have on production. It also created some problems for us when talking about testing with DropwizardAppRule and ResourceTest classes. When tests that are using them were ran one after another, one of them failed, but when ran independently they worked, so we were forced to create some workaround.
At the end of April a new dropwizard-guice was released and it finally integrates with stable Guice 4.0, but unfortunately we haven’t tried it yet, so there is a chance that some of our issues are fixed by it.
Generally, all DI integrations for DW are community based, so they have different release cycle than pure DW and such situation often cause new bugs to pop up. The important matter is what I mentioned in the beginning of this section – DW was probably never supposed to be used with DI frameworks, and it is a very possible misuse of the framework from our side.
Spring Boot stands on a totally different side of the road. It provides its own, mature and stable DI solution that has been popular within Spring based apps for a couple of years. Its main advantage is that it works just as you expect, and does no nasty surprises to you. In my mind it is one of the most important things about features like DI – that they just work as they are intended to. We have not had any problems with it so far, so using it caused huge productivity gain for us.
Summing up this area – the verdict is quite clear – SB gives us just what we need and is much more suitable for us.
As stated in REST support section, we try to use specification wherever it is possible. Talking about persistence, we wanted to base it on JPA 2.1 specification. Unfortunately, it is not possible using Dropwizard, because it is very tightly coupled with Hibernate (dropiwzard-hibernate is official package from framework authors). Hibernate is compatible with JPA 2.1, but with dropwizard-hibernate you cannot inject EntityManager for example, and you have to use Hibernate’s Session and SessionFactory. Contrary to community DI support, this integration is very stable and works fine. However, it requires quite a lot of manual configuration, which in my opinion is quite verbose. It means that for example you have to list entities and converters by hand in order to make them working. It also provides a very basic DAO abstraction, which in majority of cases is sufficient.
Spring Boot gives much more in that area. To start with one thing, it uses Spring Data module that is build on JPA 2.1 specification, so it is possible for us to use callback methods like prePersist, preUpdate, etc. Moreover, it has very easy automated configuration when compared to DW. That is achieved by providing nice solutions that speed up everyday development, like entity scanning. Another brilliant concept is Repository interface (from Spring Data module) that makes creation of CRUDs and simple DAOs as simple as you can imagine. And finally, less important but also worth noting is the fact that it is possible to use SB with different ORMs than Hibernate, which is very difficult to achieve with DW.
Payment platforms need to be trustworthy and consistent. Error situations always happen, and you need to be aware of them. For instance, in microservices world you need to handle situations like connection timeouts or services being down. We have some volatile areas that consist of multiple service calls, that change the state of payments, wallets, etc, so they need to be atomic. We use transaction mechanism to achieve this, because we want to be able to rollback all the changes, if any error occurs.
Both frameworks provide a way to use declarative transactions. Dropwizard comes with @UnitOfWork annotation which can be applied only to methods in REST resource classes. That means that whole request processing is bounded inside of transaction, and if any exception is thrown, all changes are rolled back. In most of the cases it is not what we want. If we want to decide what takes part in the transaction, and to manage that in DW based projects, we have to start transactions manually. There is also one very important information about DW 0.8.0. When we migrated to that version, we got to know that it comes with a serious bug – that does not rollback a transaction after failure. That is something totally unacceptable for us. DW authors knew about it, and they patched it in the sources available on github, but they decided to wait for over a month with releasing it to public repository. That forced us to build a patched version of that artifact and host it on our own. Finally they fixed it and released Dropwizard 0.8.1.
When it comes to Spring Boot and that matter, I have to admit that it offers much more. Its @Transactional annotation can be applied on any method or class, not only on endpoints, so it gives much more flexibility. What is more, it also supports transaction isolation levels, what makes it very powerful and suitable for advanced use cases. Finally, it is a very well tested and stable solution, and it is barely possible that one of its versions will have a bug similar to one that DW 0.8.0 comes with.
Wrapping up this area, it is much more comfortable for us to work with SB when it comes to transactions, because it has a more advanced and mature solution for that.
Every application that runs on multiple environments needs to be configurable somehow. With microservices architecture things get more complicated than in monolith application with a single property file. Since we deployed and ran every microservice separately and had multiple configuration files, we quickly realised that the maintenance of this amount of config files is painful. That is why we decided to have one config file for each component, and have settings for all environments in there.
Dropwizard and Spring Boot are both compatible with configuration file in YAML format, and SB also supports simple .properties file format. DW has no built-in functionality to support multiple environment configs in one file, but we found out that integrating Constretto library would do the thing for us. Spring Boot has its own solution for that, and it is called Spring Profiles. It also provides an easy way to access your properties, because you can simply inject them to your bean by @Value annotation. Besides, similarly to DW framework, they can be retrieved from Environment object. There is one issue that I mentioned in DI area – when using Guice inside DW based microservice, we have to stick with DEV mode to get our properties at startup.
Summing up, the configuration management is by default supported better in Spring Boot, but Dropwizard, supplied with Constretto, also meets our requirements.
Dependency management is very important for us, because we put much effort into keeping our classpath clean. We decided to use maven-enforcer to fail build at compilation stage, in case it discovers duplicated jars.
Unfortunately, that area is probably one of the weakest points of Dropwizard, because its authors did not put much attention into this. The project itself has only few managed dependencies. Dropwizard framework is divided into few core modules, and even though they are compiled with maven-enforcer, we encountered some issues with dependency convergence. Some of DW modules are incompatible with each other, some have issues inside. For example dropwizard-logging from DW 0.8.0 module comes with 2 versions of slf4j-api artifact. Same issues concern community modules, which also do not align their dependencies with official packages and if you use them, you have to struggle a bit to make your project compiling with the enforcer.
Spring Boot authors present totally different mindset about that case. They provide very nice dependency management pom, which can be either imported, or set as parent in your application’s pom. Spring framework is build of multiple packages, has higher granularity of them comparing to DW. So, at first you may feel a bit dizzy which of them you have to pick to achieve your goal, but Spring team came with this idea of “starter” modules that ease the use and configuration of other Spring modules, or 3rd parties in order to supply everything that you need for a particular objective. For example there are starter poms for Spring Data JPA, which provides repository interfaces and other goodies for persistence, also starter modules for Big Data, NOSQLs, security, and nearly everything you can use to build your web app. One last fact to mark about Spring Framework is that all its modules are compiled with maven-enforcer, so that is simple and smooth to include these packages into our pom.
The overall impression – looking from dependency management point of view the absolute winner is Spring Boot, because it does not require any effort from us to have a clean classpath, and it is structured better than Dropwizard.
We value the meaning of application metrics. For now we have not put much effort into specific gauges inside of the platform, but we want to get stats about some parts of it so we did initial work to have them.
Since Dropwizard was initially developed by Coda Hale, it is more than obvious it adopts his own solution – codahale-metrics – inside of Dropwizard. It was great decision, because this library can be nicely integrated inside of web application. They are easy in use and are very powerful at the same time. It comes with the most popular gauges defined, but still you can define any type of custom measurement. What is more, Dropwizard also provides good support for health checks that are a must-have feature for microservices and cloud based environment.
Spring Boot provides only basic metrics and stats – for example some system metrics, and support for health checks. It does not provide its own solution for advanced metrics like Dropwizard. In official Spring Boot documentation, in the metrics section, we can find that they suggest using Dropwizard metrics package for any advanced measurements, so they pay honours to DW authors for their work in that matter.
In the metrics area, we give huge credit to Dropwizard’s solution. Using its metrics you can have well measurable application without putting much effort into it.
When it comes to community support, I did some research about both of these frameworks in the web.
Surprisingly, it turns out that on StackOverflow there are 4 times more topics about Spring Boot, than about Dropwizard (accurate numbers are: 6,326 about SB, and 1,482 about DW – data collected at 24th June 2015).
That is not what one can expect, because Spring Boot is younger than Dropwizard (SB was created about 2 years after DW). The number of contributors on Github is quite similar – 183 vs 163 for Dropwizard, but in both cases 90% of them are rarely active. Release cycles also favours Spring Boot, they are much more frequent than Dropwizard (last interval was about 9 months between 0.7.1 and 0.8.0). The ecosystem is also more sophisticated around Spring Boot – it provides aforementioned starter modules, that allow integration with lots of other official Spring goodies. What Dropwizard offers here is a few official integration packages (like hibernate one), and a lot of community projects.
There were moments that we were stuck with something when working with both of these frameworks, and then we tried to contact the authors. Sooner or later, we got their responses, but it seems that Spring Boot has some coders also delegated for contacting users and they are much more responsive. Generally speaking, Spring Framework is sponsored by Pivotal, so there is much more activity around it. Dropwizard is no longer developed by Coda Hale, he decided to entrust further development to community, and that has some impact on the quality of the support.
Over half of a year of work with these two solutions gave us some thought on them. Both of them are achieving their goal of building microservice components, and also are very devops-friendly, but they are built upon slightly different ideas and mindsets.
We feel that we are more productive using Spring Boot than Dropwizard. You may say that we abuse microservices idea with features like DI or ORM, but I think that if they work for you, that is the right path to go. Since we are building payment platform, in some places we need to use this “enterprisy” things to make our lives easier. Even though it seems Spring Boot is more suitable for us in most of the areas, we don’t throw Dropwizard away and we still use it in some of our components. In my opinion for smaller services, with a simple domain, Dropwizard is a way to go. Most of our components are rather small, but some of them have quite a complex logic that is easier to implement using Spring Boot. What is more, it seems that the maintenance of components based on SB is less painful. We also value its popularity, when it comes to community support. A lot of modules that are used by Spring Boot under the hood have much longer history than the project itself and they are considered as stable and mature. There is one thing that should be noted, though – all these features provided by Spring Boot, come with a price of a longer startup time. Vanilla Dropwizard distribution starts a lot faster than Spring Boot but it does not concern us, because in our project we utilize blue-green deployment technique, which eliminates downtime.
All in all, you should always consider what do you want to do and choose the tools that will make your work easier and more pleasant to go through. Whether you go with Dropwizard or Spring Boot, if you put some thought to this decision beforehand, it is more likely that you will benefit from framework’s characteristics, rather than curse its authors.