Pages

A more springy Hello World

I am going to modify my Spring Boot Hello World application to let it be a bit more springish. The first version was the bare minimum to check that the STS installation was working fine. The second one was a proper, even if minimal, Web Service. The third one added logging capabilities.

Ensured that all this basic stuff works properly, I can confidently move to something more interesting. Let's say hello using IoC (Inversion of Control) and DI (Dependency Injection).

I create a dedicate package for the logic related stuff for my hello project. Not surprisingly, I name it logic, and I put it under the hello package.
Actually, there's not much logic in this app, I just want to greet users. This suggests me to create an interface, Greeter, that exposes the a single greeting method.
The GreetingController changes accordingly. I remove the logic in it, delegating the work to the actual class that is going to implement the Greeter interface.
Notice how much more cleaner is this way of working. The controller doesn't know anymore about how a greeting is generated. It just knows that exists a Greeter interface, it holds a reference to it that is annotated as a Resource, a javax annotation, and through it, a greeting() method would be called to answer to the user request.

I create a couple of concrete classes implementing Greeter to give a sense to this architecture. There are about identical, in the real world things are usually more complicated. Here is the PlainGreeter, its brother MockGreeter is about the same.
Notice how the relation between the controller and the concrete Greeter is set. Before IoC it was commonly considered a controller task to define a dependency with the Greeter. In a way or another, an instance of the actual Greeter was created and used. Now IoC rules, so we perform an Inversion of Control. Is the Greeter that signal to be available for the controller, and the framework, Spring here, that take care of making it work.

I use annotation to implement the IoC relation, and you can see how in the code.
In the controller I have annotated its Greeter data member as Resource. This javax annotation tells Spring that Dependency Injection should be used here.
Each concrete class implementing the Greeter interface that could be a target for DI should be marked as Component, a springframework stereotype annotation.

Finally, we have to tell Spring which among the available Components should be injected in the controller Resource.

An handy way to do it is combining configuration and annotation. In the Spring configuration file I specify which profile is the active one
spring.profiles.active=prod
Then, I add a springframework context Profile annotation to each component, marking with the active profile only the one I want to be used. Be careful on it. Here is the exception that I get at startup if I mark both my components as "prod":
org.springframework.beans.factory.BeanCreationException:
 Error creating bean with name 'greetingController':
 Injection of resource dependencies failed; nested exception is 
org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
 No qualifying bean of type 'dd.manny.hello.logic.Greeter' available:
 expected single matching bean but found 2:
 mockGreeter,plainGreeter

This Spring Boot project is on github. You could be mainly interested in these files:

No comments:

Post a Comment