Doing microservices with micro-infra-spring

We’ve been working at 4financeit for last couple of months on some open source solutions for microservices. I will be publishing some articles related to microservices and our tools and this is the first of (hopefully) many that I will write in the upcoming weeks (months?) on Too much coding blog.

This article will be an introduction to the micro-infra-spring library showing how you can quickly set up a microservice using our tools.

Introduction 

Before you start it is crucial to remember that it’s not enough to just use our tools to have a microservice. You can check out my slides about microservices and issues that we have dealt with while adopting them at 4financeit.

4financeit microservices 12.2014 at Lodz JUG from Marcin Grzejszczak

Here you can find my video where I talk about microservice at 4finance (it’s from 19.09.2014 so it’s pretty outdated)


Also it’s worth checking out the articles of Martin Fowler about microservices, Todd Hoff’s – Microservices not a free lunch! or The Strengths and Weaknesses of Microservices by Abel Avram’s.

Is monolith bad?

No it isn’t! The most important thing to remember when starting with microservices is that it will complicate your life in terms of operations, metrics, deployment and testing. Of course it does bring plenty of benefits but if you are unsure of what to pick – monolith or microservices then my advice to use is to go the monolith way.

All the benefits of microservices like code autonomy, doing one thing well, getting ridd of pacakge dependencies can be also achieved in the monolithic code thus try to write your applications with such approaches and your life will get simpler for sure. How to achieve that? That’s complicated but here are a couple of hints that I can give you:

  • try to do DDD. No, you don’t have DDD when your entities have methods. Try to use concepts of aggregate roots
  • try not to make dependencies on packages from different roots. If you have two different bounded context like com.blogspot.toomuchcoding.client and com.blogspot.toomuchcoding.loan – go via tight cohesion and low coupling – emit events, call REST endpoint, send JMS messages or talk via strictly defined API. Do not reuse internals of those packages – take a look at the next point that deals with encapsulation
  • take your highscool notes and read about encapsulation again. Most of us make the mistake of thinking that if we make a field private and add an accessor to it then we have encapsulation. That’s not true! I really like the example of Slawek Sobotka (article in polish) who shows an example of common approach to encapsulation:

    human.getStomach().getBowls().getContent().add(new Sausage())

    instead of

    human.eat(new Sausauge())

  • add to your IDE class generation template that you want your new classes to be package scoped by default – what should be publicly available are interfaces and really limited number of classes
  • start doing what’s crucial in terms of tracking microservice requests and measuring business and technical data in your own application! Gather metrics, set up correlation ids for your messages, add service discovery if you have multiple monoliths.

I’m a hipster – I want microservices!

Let’s assume that you know what you are doing, you evaluated all pros and cons and you want to go down the microservice way. You have a devops culture there in your company and people are eager to start working on multiple codebases. How to start? Pick our tools and you won’t regret it 😉

Clone a repo and get to work

We have set up a working template on Github with UI – boot-microservice-gui and without it – boot-microservice. If you clone our repo and start working with it you get a service that:
  • uses micro-infra-spring library
  • is written in Groovy
  • uses Spring Boot
  • is built with Gradle (set up for 4finance – but that’s really easy to change)
  • is JDK8 compliant
  • contains an example of a business scenario
what you just have to do is:
  • check out the slides above to see our approach to microservices
  • remove the packages com/ofg/twitter from src/main and src/test
  • alter microservice.json to support your requirements
  • write your code!
Why should you use our repo?
  • you don’t have to set up anything – we’ve already done it for you
  • the time required to start developing a feature is close to zero

Aren’t we duplicating Spring Cloud?

In fact we’re not. We’re using it in our libraries ourselves (right now for property storage in Git repository). We have some different approaches to service discovery for instance but in general we are extending Spring Cloud’s features by:

Conclusions

If you want to go down the microservice way you have to be well aware of the issues related to that approach. If you know what you’re doing you can use our libraries and our microservice templates to have a fast start into feature development. 

What’s next

On my blog at toomuchcoding.blogspot.com I’ll write about different features of the micro-infra-spring library with more emphasis on configuration on specific features that are not that well known but equally cool as the rest 😉 Also I’ll write some articles on how we approached splitting the monolith but you’ll have to wait for that some time 😉

This post is part of the Java Advent Calendar and is licensed under the Creative Commons 3.0 Attribution license. If you like it, please spread the word by sharing, tweeting, FB, G+ and so on!

Spring’s @Primary annotation in action

Spring is a framework that never stops to amaze me. It’s because of the fact that it offers plenty of different solutions that allow us, developers, to complete our tasks without writing millions of lines of code. Instead we are able to do the same in a much more readable, standardized manner. In this post I will try to describe one of its features that most likely is well known to all of you but in my opinion its importance is undervalued. The feature that I’ll be talking about is the @Primary annotation.

The problem

On a couple of projects that I was working on we have came accross a common business problem – we had a point of entry to a more complex logic – some container, that would gather the results of several other processors into a single output (something like map-filter-reduce functions from the functional programming). To some extent it resembled the Composite pattern. Putting it all together our approach was as follows:

  1. We had a container that had an autowired list of processors implementing a common interface
  2. Our container implemented the same interface as the elements of the autowired list
  3. We wanted the client class that would use the container to have this whole processing work transparent – he is interesed only in the result
  4. The processors have some logic (predicate) basing on which a processor is applicable to the current set of input data
  5. The results of the processing were then combined into a list and then reduced to a single output
There are numerous ways of dealing with this issue – I’ll present one that uses Spring with the @Primary annotation.

The solution

Let’s start with defining how our use case will fit to the aforementioned preconditions. Our set of data is a Person class that looks as follows:

Person.java

package com.blogspot.toomuchcoding.person.domain;

public final class Person {
private final String name;
private final int age;
private final boolean stupid;

public Person(String name, int age, boolean stupid) {
this.name = name;
this.age = age;
this.stupid = stupid;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}

public boolean isStupid() {
return stupid;
}
}

Nothing out of the ordinary. Now let us define the contract:

PersonProcessingService.java

package com.blogspot.toomuchcoding.person.service;

import com.blogspot.toomuchcoding.person.domain.Person;

public interface PersonProcessingService {
boolean isApplicableFor(Person person);
String process(Person person);
}

As stated in the preconditions each implementaiton of the PersonProcessingService has to define two points of the contract :

  1. whether it is applicable for the current Person 
  2. how it processess a Person.

Now let’s take a look at some of the Processors that we have – I’ll not post the code here cause it’s pointless – you can check out the code later on Github or on Bitbucket. We have the following @Component annotated implementations of PersonProcessingService:

  • AgePersonProcessingService
    • is applicable if Person’s age is greater or equal 18
    • returns a String containing “AGE” as processing takes place – that’s kind of silly but it’s just a demo right? 🙂
  • IntelligencePersonProcessingService
    • is applicable if a Person is stupid
    • returns a String containing “STUPID” as processing takes place
  • NamePersonProcessingService
    • is applicable if a Person has a name
    • returns a String containing “NAME” as processing takes place
The logic is fairly simple. Now our container of PersonProcessingServices would want to iterate for a given Person over the processors, check if the current processor is applicable (filter) and if that is the case add the String that is a result of processing of a Person to the list of responses (map – a function converting a Person to a String) and finaly join those responses by a comma (reduce). Let’s check it out how it’s done:

PersonProcessingServiceContainer.java

package com.blogspot.toomuchcoding.person.service;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;

import com.blogspot.toomuchcoding.person.domain.Person;

@Component
@Primary
class PersonProcessingServiceContainer implements PersonProcessingService {

private static final Logger LOGGER = LoggerFactory.getLogger(PersonProcessingServiceContainer.class);

@Autowired
private List<PersonProcessingService> personProcessingServices = new ArrayList<PersonProcessingService>();

@Override
public boolean isApplicableFor(Person person) {
return person != null;
}

@Override
public String process(Person person) {
List<String> output = new ArrayList<String>();
for(PersonProcessingService personProcessingService : personProcessingServices){
if(personProcessingService.isApplicableFor(person)){
output.add(personProcessingService.process(person));
}
}
String result = StringUtils.join(output, ",");
LOGGER.info(result);
return result;
}

public List<PersonProcessingService> getPersonProcessingServices() {
return personProcessingServices;
}
}


As you can see we have a container that is annotated with @Primary which means that if an implementation of the PersonProcessingService will have to be injected then Spring will pick the PersonProcessingServiceContainer to be injected. The cool thing is that we have an autowired list of PersonProcessingServices which means that all other implementations of that interface will get autowired there (the container will not autowire itself to the list!).

Now let’s check out the Spock tests that prove that I’m not telling any lies. If you aren’t using Spock already in your project then you should move it straight away 🙂

PersonProcessingServiceContainerIntegrationSpec.groovy

package com.blogspot.toomuchcoding.person.service
import com.blogspot.toomuchcoding.configuration.SpringConfiguration
import com.blogspot.toomuchcoding.person.domain.Person
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
import spock.lang.Unroll

import static org.hamcrest.CoreMatchers.notNullValue

@ContextConfiguration(classes = [SpringConfiguration])
class PersonProcessingServiceContainerIntegrationSpec extends Specification {

@Autowired
PersonProcessingService personProcessingService

def "should autowire container even though there are many implementations of service"(){
expect:
personProcessingService instanceof PersonProcessingServiceContainer
}

def "the autowired container should not have itself in the list of autowired services"(){
expect:
personProcessingService instanceof PersonProcessingServiceContainer
and:
!(personProcessingService as PersonProcessingServiceContainer).personProcessingServices.findResult {
it instanceof PersonProcessingServiceContainer
}
}

def "should not be applicable for processing if a person doesn't exist"(){
given:
Person person = null
expect:
!personProcessingService.isApplicableFor(person)
}

def "should return an empty result for a person not applicable for anything"(){
given:
Person person = new Person("", 17, false)
when:
def result = personProcessingService.process(person)
then:
result notNullValue()
result.isEmpty()
}

@Unroll("For name [#name], age [#age] and being stupid [#stupid] the result should contain keywords #keywords")
def "should perform different processing depending on input"(){
given:
Person person = new Person(name, age, stupid)
when:
def result = personProcessingService.process(person)
then:
keywords.every {
result.contains(it)
}
where:
name | age | stupid || keywords
"jan" | 20 | true || ['NAME', 'AGE', 'STUPID']
"" | 20 | true || ['AGE', 'STUPID']
"" | 20 | false || ['AGE']
null | 17 | true || ['STUPID']
"jan" | 17 | true || ['NAME']
}
}

The tests are pretty straight forward:

  1. We prove that the autowired field is in fact our container – the PersonProcessingServiceContainer.
  2. Then we show that we can’t find an object in the collection of autowired implementations of the PersonProcessingService, that is of PersonProcessingServiceContainer type
  3. In the next two tests we prove that the logic behind our processors is working
  4. Last but not least is the Spock’s finest – the where clause that allows us create beautiful paramterized tests.

Per module feature

Imagine the situation in which you have an implementation of the interface that is defined in your core module.

@Component
class CoreModuleClass implements SomeInterface {
...
}

What if you decide in your other module that has the dependence to the core module that you don’t want to use this CoreModuleClass and want to have some custom logic wherever the SomeInterface is autowired? Well – use @Primary!

@Component
@Primary
class CountryModuleClass implements SomeInterface {
...
}

In that way you are sure that wherever the SomeInterface has to be autowired it will be your CountryModuleClass that will be injected in the field.

Conclusion

In this post you could see how to

  • use the @Primary annotation to create a composite like container of interface implementations
  • use the @Primary annotation to provide a per module implementation of the interface that will take precedence over other @Components in terms of autowiring
  • write cool Spock tests 🙂

The code

You can find the code presented here on Too Much Coding’s Github repository or on Too Much Coding’s Bitbucket repository.