With the rise of microservices and the billing model of cloud services, we are in need of analyzing the environments in which our applications run. We will analyze the most popular “Micro” Frameworks Java for the development of service layers.
Traditionally Java web applications have been deployed with their corresponding application server, sometimes a Tomcat, a JBoss (Wildfly), a Glassfish (Payara) or any other container. These containers provided the necessary functionality to access these applications from the network.
Unfortunately, various inconveniences are associated with these application servers, mainly which it is not always transparent to take our applications from one container to another, either because the way to configure them is different or because they generate dependency errors shared with our own applications. For some reason, the different web containers have been entering the field to force the applications that run in them to be tied to their implementation.
With the rise of the microservices world all these containers have found a new associated “problem”, when our functionality is small, which is expected in a microservice, the container becomes more of a memory and CPU load instead of a help. It does not seem a good idea a small service that performs a small function for example image processing is overloaded by an application container that consumes much more memory than the functionality itself.
Memory consumption in Standby:
Tomcat: Mem: 127Mb
Jboss Wildfly: Mem: 315Mb
Payara Micro: 371Mb
Due to these often unnecessary consumptions in the microservices scenario, self-contained solutions have been appearing, which allow applications to expose their services without container overload.
Without detracting from the application containers that clearly have a usage scenario, we are going to analyze some of these “micro” solutions specifically oriented to the world of microservices through a simple echo service:
- SparkJava
- Javalin
- Ninja
- Micronaut
- Dropwizard
- SpringBoot
- Rapidoid
1. SparkJava
Website: http://sparkjava.com/
Github repository: https://github.com/perwendel/spark
Documentation: 7/10
Boot Time: 0.3s
Requests/second: 13500
The Sparkjava framework is a lightweight web framework, it only gives us a small and very light layer of abstraction on a Jetty server, leaving the decision on the rest of libraries that our application needs to use under our responsibility. Despite not being a framework that offers us great functionalities, it assures us that we will hardly have a compatibility problem between the libraries we use and the libraries included in the framework.
On the other hand, being so light requires some manual processing of requests, resembling a servlet rather than a complete framework.
public class SparkServer {
private Gson gson=new Gson();
public static final void main(String[] args){
new SparkServer();
}
private SparkServer(){
port(8080);
post("/echo","application/json", this::echo);
}
private Object echo(Request request, Response response) {
Message input=gson.fromJson(request.body(), Message.class);
input.setValue("echo "+input.getValue());
return gson.toJson(input);
}
public void stop(){
Spark.stop();
}
}
In favor:
• Start very fast
• Compilation size too small
• Active community
Against:
• Lack of integrated functionalities
2. Javalin
Website: https://javalin.io/
Github Repository: https://github.com/tipsy/javalin
Documentation: 7/10
Boot Time: 0.3 s
Petitions/second: 15000
Javalin is the first cousin of SparkJava; in fact it is a fork of the same project on which functionalities such as session control, validation, and transparent support for serialization of json objects have been added, while at the same time it has reduced the quantity of original code of the project.
public class JavalinService {
private Javalin app;
public static final void main(String[] args){
new JavalinService();
}
private JavalinService(){
app = Javalin.create().start(8080);
app.post("/echo", this::echo);
}
private void echo(Context ctx) {
Message item = ctx.bodyAsClass(Message.class);
item.setValue("echo "+item.getValue());
ctx.json(item);
}
public void stop() {
app.stop();
}
}
In favor:
• Very fast start
• Compilation size too small
• High speed of request processing
Against:
• Lack of integrated functionalities
• Little community
3. Ninja
Website: https://www.ninjaframework.org
Github Repository: https://github.com/ninjaframework/ninja
Documentation: 4/10
Boot Time: 1s
Requests/second: 10000
Ninja is an integrated framework, that is, it does not only include the services layer but also views, jpa, or dependency injection. Unfortunately it is poorly documented and its user guide invites us to create a project from a maven archetype, which is always an alarm signal.
On the other hand, the structure of the generated project is not standard; generating resource files, configuration and views, outside the standard maven directory, which if we are accustomed to a certain order can be annoying.
public class Routes implements ApplicationRoutes {
@Override
public void init(Router router) { router.POST().route("/echo").with(ApplicationController::echo);
}
}
@Singleton
public class ApplicationController {
public static Result echo(Message item) {
item.setValue("echo "+item.getValue());
return Results.json().render(item);
}
}
In favor:
• SuperDev mode to make rapid deployments during development
Against:
• Slow processing of requests
• Non-standard project structure
• It offers a very closed ecosystem, with difficulties to migrate it
4. Micronaut
Website: https://micronaut.io/
Github Repository: https://github.com/micronaut-projects/micronaut-core
Documentation: 8/10
Boot time: 1.3s
Petitions/second: 13000
Micronaut is an integrated framework for microservices that mainly seeks the ease of implementing tests and the clear orientation to cloud services, supporting error and retry management.
On the other hand, we have encountered some difficulties when testing it, generating unclear and not excessively documented errors due to the processing of the annotations.
@Controller("/")
public class EchoController {
@Post(uri = "/echo", produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
public Message echo(Message message) {
message.setValue("echo "+message.getValue());
return message;
}
}
In favor:
• High performance in the processing of requests
• Easy setup
Against:
• It is a relatively heavy framework
5. Dropwizard
Website: https://www.dropwizard.io/en/latest/
Github Repository: https://github.com/dropwizard/dropwizard
Documentation: 7/10
Boot time: 1.5s
Petitions/second: 11000
Dropwizard is an integrated framework with Jetty/Jersey as the center of its service layer and other unmatched and modular utility libraries, such as JDBI, Guava or FreeMarker.
@Path("/")
public class MessageController {
@POST @Path("/echo") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Response echo(Message message) throws IOException {
message.setValue("echo "+message.getValue());
return Response.ok(message).build();
}
}
In favor:
• Very light in memory consumption
• Well documented framework
• The libraries that compose it are standard (Jersey, JDBI)
• Very active development
Against:
• It is not very easy to implement security, there is support for authentication but not for authorization
6. SpringBoot
Website: https://spring.io/projects/spring-boot
Github repository: https://github.com/spring-projects/spring-boot
Documentation: 10/10
Boot time: 2s
Petitions/second: 15000
SpringBoot is the most used framework in the business environment, it offers among other hundreds of modules that range from the presentation layer to database access through distributed processing. SpringBoot logically benefits from everything developed since the origins of Spring, that is, dependency injection, and the integration facilities with third-party products.
On the other hand, just as the Spring Framework required a lot of memory and CPU resources, the same happens to SpringBoot.
In favor:
• Very documented
• Widely adopted by the community
• Multiple libraries equally documented
• Includes all the advantages of the Spring framework
• Good support for security, both authentication and authorization
Against:
• Pretty large compiles
• Slow start
• High memory consumption
@RestController
@EnableAutoConfiguration
@ComponentScan
public class TextApplication {
public static void main(String[] args) {
SpringApplication.run(TextApplication.class);
}
@PostMapping(value = "/echo",consumes = MediaType.APPLICATION_JSON_VALUE,produces = MediaType.APPLICATION_JSON_VALUE)
public Message handle(Message message) {
message.setValue("output");
return message;
}
}
7. Rapidoid
Website: https://www.rapidoid.org/
Github Repository: https://github.com/rapidoid/rapidoid
Documentation: 5/10
Boot time: 0.9 s
Petitions/second: 17000
Rapidoid is almost unknown; it is a framework that offers both a rest layer and a template engine for the presentation layer. Its main advantage is the speed of processing requests, being the highest of all analyzed.
In favor:
• High processing speed of requests, with minimal impact on memory
• Minimum deployment size
• Minimum amount of source code
Against:
• Almost exclusive use of JSON
• Standby memory consumption
• Little documented
• Few features included
• Few movement in your repository
public class Rapidoid {
public static void main(String[] args){
On.post("/echo").json((Message message)->{message.setValue("echo "+message.getValue());return message;});
}
}
Summary:

Petitions/second, 50,000 requests, 200 concurrent



Conclusion
When choosing a framework to deploy as microservices it is necessary to take into account many factors, memory is a factor as important as the speed of process, since this normally affects profusely in the cost of servers. In general, it will be easier to adapt existing code to microservices based on more complete frameworks, such as SpringBoot or Dropwizard, while if we are designing a system from scratch, designing everything based on microservices, it will be more convenient for us to take a light framework as a basis, as Spark, (or if we feel very brave as Rapidoid) and add our dependencies on them.
All set?
It’s time to handle documents more efficiently