Java beyond Spring: A set of alternatives.

The quest

What will be covered in the series?

It is commonly known that by using Spring there are tons of modules you could add to you application. It is only a matter of browsing through the available dependencies of Spring Initializr.

Dependency injection

class MyDependencyInjector {   private UserDao userDao;
private UserService userService;

public MyDependencyInjector() {
this.userDao = new MongoDBUserDao();
this.userService = new UserService(this.userDao);
}
// getters
}
  • Simply have a bind without the to. That tells Guice to simply create an instance of UserService as it does not have an interface.
  • Have a bind with a to. This tells Guice to bind an interface to a specific implementation. In this case I wanted redis for production and an in-memory solution for development.
  • Sometimes, especially with third-party code, you need to construct the object yourself and then configure it, like you would do for a datasource or redis in my example. For that you use the @Provides annotation. As the word says, it tells Guice that whenever a Jedis instance is needed, it is that method that provides it.

Configuration properties

  • The configuration will depend for sure on the environment where the application is running. You will have the test db which is obviously different from the production db. So you need to have different configuration files per environment:
application-dev.propertiesdb.host=10.15.51.24application-prod.propertiesdb.host=20.25.71.240
  • One thing that we always want in software development is to avoid repeating things. When something needs to change you do not want become Indiana Jones finding the lost ark… you want change it in one place. Some configuration values need to be the same across all configuration files. So this means that if there are 3 different configuration files you will need to change the value in all 3 of them? You do not want that. You need to have a file to store configuration that is valid for all environments and then put the environment specific values in the right configuration file.
application-common.properties

app.port=8080
application-dev.propertiesdb.host=10.15.51.24application-prod.propertiesdb.host=20.25.71.240
  • For now I have focused on single value properties that can simply be read into a variable. But what if you wanted to read a group of properties that belong to the same concern? For example, the DB connection requires a host, user, password and db name at least. You could read all of them into simple Strings/Numbers, etc. Things will get tricky if you want to read something as a List, Map or an Object. Objects will be even trickier if you have one in the common configuration with one or more properties overridden in the environment specific file. You will need to merge them. We will come back to this later.
application-common.properties

db.user=user
db.pass=pass
application-dev.propertiesdb.host=10.15.51.24application-prod.propertiesdb.host=20.25.71.240

Configuration properties with Apache Commons Configuration 2

You can find the demo here.

  • Read one single configuration file.
  • Create a composite configuration made up from multiple files.
  • Upon configuration keys clash, it has different approaches to manage it: Union, Combine or override.
  • Supports properties, yaml and xml formats.

Database

Rest controller

Rest controllers with Spark

Rest controllers with Javalin

Http Client

Http Client with Retrofit

Http Client with OkHttp

And finally putting it all together…

Lastly, reaching the end of the quest. As last step I wrote an all-in-one application that makes use of most of the tools explained here. I chose Dagger, Retrofit and Javalin combined with Apache commons config and Jooq.

Conclusions

So, the quest has ended 😅. Here are some thoughts on the tools I have reviewed.

Dependency injection conclusions

Both Guice and Dagger offer quite a few options to create a dependency graph. I think both do a good job and they can for sure be a replacement for the Spring dependency injection mechanism.

Configuration properties conclusions

This is probably the most limited replacement tool of all present in this article. Yes, it does the job and it is easy to setup and use. But I think there is just too much to do by hand. Do not get me wrong, it can be done but it seems to me that if you want to have a complex set of configurations and replicate all or most of the Spring features… that would be a project on its own.

Database conclusions

As I stated in my previous article, Jooq is amazing and so easy to use. Just like everything, you need to learn how to use it, but once you are there it is a bliss. It can perfectly replace spring-data-jdbc and JPA.

Rest controller conclusions

Both Sparkjava and Javalin are good, quick and easy replacement for Spring-web. You can do the same things just as easy. Maybe the code may not look so elegant with the fancy annotations and all but it can get the job done just as good.

Http Client conclusions

In this case, I think the biggest advantage you get with both Retrofit and OkHttp is the chance of execution asynchronous calls. Spring rest-template is synchronous and if you want something async you will need to use spring reactive’s org.springframework.web.reactive.function.client.WebClient.

Final words

After going through this quest, I can say that it is amazing how many things Spring solves for you and how easy it is to use. I agree though that it has too many levels of abstraction, proxies, aspects and it may impact performance and specially boot time. But there things are just plug-and-play even when it comes to Maven configuration. Spring boot apps come bundled with many maven plugins that work out of the box like the compiler and packaging.

  • Setup and development speed: As stated, Spring solves a lot of things for you. You do not need to write complex code for configuration properties or learn how some dependency injection engine works, etc. Spring has modules for everything. Besides, given it is the tool choice of the vast majority, almost everyone knows the basics.
  • Documentation: Needless to say that the spring community is huge. Given it is the more widespread framework, you will find an answer to any issue a few click away.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Ignacio Cicero

Ignacio Cicero

I’m a back-end software engineer working in finance. I write about Java and tech that I decide to research.