Microservices with Spring Cloud and Netflix OSS – 1

Since I have heard the word “microservices” for the first time, I tried to learn how to build something that could really be called a “microservice”, or at least a microservice-based application. Finally, after lots of tutorials, readings, books and so on, I found out the way Spring framework allows everybody to build a microservice application. This serie of articles is intended to give out a set of tutorials on how to use the framework and it is based on my personal experience.

First of all, let’s see what microservices are. This first post will cover some of the base concepts of this new architecture and introduce all the upcoming articles. Let’s suppose we have an application that permits to our users to place some reservations. The application has two basic functionalities: the users management and the reservations management. The whole thing is built in a monolithic way, so we just have a big database with a whole application built on top of it. A generic client, that could be a web application, or a mobile device, directly communicates with the monolithic application, as shown in figure.

Monolithic Application
Monolithic Application

This monolithic application has some pros and some contros. It is true that we only need an application server to have it running, but what happens if we need a replica of only a part of it, let’s say, the reservation management sub-system? We have to run a replica of the whole thing. Not only: developers would tend to write the application in a high coupled way, and the complexity of the code would increase very easily. Microservices could help us. In particular, let’s give a look at the basic patterns of the microservices way, as detailed in in the Patterns page at microservices.io. The firsts pattern we will adopt are API Gateway and Database per service. As the names suggest, starting from our monolithic application, we split it into two basic services, a Users service and a Reservations service. Both services will have their local database, built in order to store just the data needed by each service and anything else. Users’ informations will be stored in the Users service database, and when the Reservation service will need any information on a user, the service itself will ask the User service for it. In order to allow client to communicate with these services, we will set a gateway to which a client will have to connect. The gateway will know both Users and Reservations service, and will handle the requests and responses between services and clients.

API Gateway and Database per service
API Gateway and Database per service

We are now in the situation where we could easily deploy a new instance of our Reservation service, using either Multiple services per host pattern or Single service per host pattern. In both cases, we could have a replica of the service and it could be useful, for example, for a geographic distributed load balancer. This solution would give us a new problem: how would the API Gateway know that we have two running instances of the Reservation service? We could build a custom gateway and hard code this information in it, or we could use a ways better solution, called Discovery. Every single instance of our services would connect to a Discovery server, and whoever would need to know the endpoint to contact in order to consume a certain service, it could do contact the Discovery server and ask for a running endpoint. See both Server-side discovery pattern and Client-side discovery pattern for these concepts. The landscape for our application would then be as shown in the following figure.

Discovery service and Reservation service replicas
Discovery service and Reservation service replicas

As we can see in the figure, we now have two database instances in the Reservation service endpoints. I just represented them in a separate way, but we could easily consider it a unique database. For example, we could imagine it like a sharded MongoDB cluster.

Until now, I have represented the communication between the User service and the Reservation service as a remote procedure invocation, but it could also be done with a message bus, and the whole picture would then become like this.

Message bus
Message bus

We have covered all the basic patterns that a microservices architecture would bring. I will add an other component to this architecture: a config service. Let’s imagine we have just deployed our both Reservation service instances, and we need to change a configuration after a week. We will need to deploy again the instances, and it would require a short time of unreachability. It would be definitely better if both the instances would fetch the config files from a service designed for that mere purpose. In this condition, we could update the config file wherever the Config service would be able to read it from, and our Reservation service instance would be notified of the change so they can update the configurations.

Config service
Config service

In the next article we will start exactly from this last component: the Config service.

Dealing with Facebook User Location in Spring

I am currently developing an application that permits users to login via their Facebook accounts, and I am using Spring on the back-end side. In particular, Spring Social helps me to communicate with Facebook, wrapping the Graph API.

Since the application needs to know the whereabouts of a user, it is useful for me knowing the user location or hometown, when these informations are setted and the user choose to set their visibility to public. The first step in the process of reading the informations is to require the access to them. The application runs on iOS, and when it requests an access token to Facebook, it has to specify both user_location and user_hometown permissions. Without them, I would not be able to read neither the user’s location or the user’s hometown.

When the application finally gets the token and send it to the back-end, I start collecting informations from the user’s profile. Regarding the location or hometown, I am interested in knowing the country where the user is located or is from, and since I will handle l10n directly on the application, I just need Facebbok to tell me the country code of user’s location and hometown.

The documentation of Graph API specifies that this information, the country code, can be read at this address:

https://graph.facebook.com/v2.6/LOCATION_ID?fields=location{country_code}

where the LOCATION_ID is, obviously, the id read from user’s location or hometown.
Searching is Spring Social documentation, I found that the FacebookTemplate has no API implementation for the location service. I have to use the RestOperations interface in order to send Facebook my request and handle the result.

And here started my headhaches. The Graph API requires the authentication, so I had to add the access token to the query string of the service. In order to have a clean code, I’ve set a constant, containing my url, with some placeholders where I need to put some values:

The brackets could give some problems using String.format(), so I encoded them in their relative entities:

The double % is needed to escape the % character, or a String.format would consider %7B and %7D as placeholders too. Everything is ready for building the request and consuming the service. Assuming that I have an object of type org.springframework.social.facebook.api.User, called user, and the access token, of type String, in a variable called token, I build the final path:

Everything seems clear. Spring’s documentation tells me that a RestOperations has the useful getForObject method. This method, though, encodes every entity in the given url. In my initial url I wrote %7B to encode an open bracket. The method getForObject, encoding the %, would transform the %7B into %%7B, and it would be totally wrong. Instead of that method signature, then, I had to prefere the one accepting an URI instead of a String.

Now, building an URI from a String containing an url is pretty simple, but I had to consider that the url would be encoded by the URI’s constructor. I also had to encode the dot in the url, so the initial constant became like this:

This request would return an object with a location and and id. The location itself would contains a country_code. I built a couple of DTOs, so I could read the response in a nice way. Here are both the DTOs and the full code used to make the request.

The same can be done with the user’s hometown, knowing that its id get be obtained with user.getHometown().getId(). In this code I used two custom DTOs because I only needed the country’s code, and not other informations. The Graph API supports a lot more of fields, so the same request can be done with more parameters and modifying the DTOs.

MongoDB on WildFly using Hibernate OGM – pt 1

Recently, I was developing some services based on Openshift, the Red Hat’s Service As a Platform, and I choose to use WildFly 8.2 as application server, and MongoDB 2.4 to store my data. Since it was my first time using MongoDB, I had to study how to communicate from my EJBs to the database, and I’ve found that I could use either Morphia or Hibernate OGM. The second one gives you drivers to communicate with other NOSQL databases, so I choose Hibernate OGM, and started to configure my project and the application server to use it. As I thought, it was not so easy like every guide or official documentation tells, so here I will explain how I successfully made it work.

I will not explain here how to set up WildFly nor MongoDB. For those, the official documentations are the best places where to find informations, so here are the links:

As I said, I choose Hibernate OGM, and in the moment I write this article, the latest final version is the 4.1.3, so I will refer to this version in the rest of the article. You can also refer to the official Reference Guide.

Modules: let’s add to WildFly the NOSQL declination

WildFly is the newest JBoss’s application server (AS from now on). It already includes full support for Hibernate, but not for the NOSQL declination, so we need to configure it directly on the AS, and we can do it adding the right modules. Modules for Hibernate OGM can be downloaded here. The archive contains all the JARs and XMLs that have to be added to WildFly in order to make OGM works with a NOSQL database. In particular, the archive contains the JAR files for supporting MongoDB, but also CouchDB, InfiniSpan and Neo4J. To make MongoDB work, only its JARs need to be added, but I added all the modules as they are in the archive. When I deployed my war file to my OpenShift application, I had to add the same modules on the remote installation of WildFly, simply sending all the modules with SFTP and restarting the AS.

Dependencies, because WildFly has to know it

Simply adding modules in WildFly is not enough to use those modules in an application. That is because of the way WildFly works with modules. In fact, as the official documentation explains, I had to add an xml file into my project, to tell WildFly that my application will require one of those modules I previously added. I created, then, a Dynamic Web Application Project in Eclipse, and added a jboss-deployment-structure.xml file into WebContent > WEB-INF, as shown in the below image.

Deployment structure
jboss-deployment-structure.xml

The content of the file is the following one:

With this code, I simply tell WildFly that it needs to load two modules: org.hibernate and org.hibernate.ogm.mongodb. Obviously, since I have already set the modules in WildFly, it already know all the required dependencies of these two modules, and will load all of them dependencies.

Project’s dependencies

Once I have set up everything on the AS side, it is time to start to code. In my project, I added the dependency below in the maven POM file:

Every settings are documented in the Official Hibernate OGM’s reference guide linked above.

Persistence unit

Once everything is settled with modules and dependencies, the next step is to configure a persistence unit that will be used to communicate with MongoDB. The persistence.xml file needs to be at the right location, that is WebContent > WEB-INF > classes > META-INF > persistence.xml, as shown in the picture below. Every other location will not work with Hibernate OGM and WildFly.

persistence.xml
persistence.xml

The content of the file is the following:

All the values are self-explanatory. The “hibernate.ogm.datastore.provider” key is set to “mongodb”, as I am using MongoDB. It can be set with other values, as specified in the Hibernate OGM Official reference, if other Databases are used. I have choosen to refer to an exampleDB Database for this article, and the persistence unit is called “ExamplePU”. In this file, I will need to add a reference for each entity I will need to be handled by Hibernate OGM, as I will explain below in the article.

Entities

It’s time to create some entities. In this article, I used two entities: one to map a generic User, and one other, to map a generic Session, referenced by the User. Since I am using MongoDB, I want to embed the session directly into the user. Probably, there are better ways to design a relationship between users and sessions, but, in this article, I just want to show how to use entities and embeddable entities.

I created the class User, and decorated it with the annotation @Entity from the standard JPA. Below is the code, excluding for the setters and getters.

The @Id and @GeneratedValue annotations are also from JPA, since Hibernate OGM works with the standard JPA’s annotations. The id attribute must be of ObjectId type, in order to work with MongoDB and Hibernate OGM as an identifier. In the User class, there is a session attribute of the type Session. The Session class is listed below:

As I said before, I want to embed the session directly into the user, without creating a new document for the sessions. The @Embeddable annotation, then, tells MongoDB to embed the session directly into the user’s document. This will create, in MongoDB, something like the example below, where we can see the embedded session:

Since I created a class decorated with the @Entity annotation, I had to tell Hibernate OGM to handle it, using the persistence.xml file. In that file, I simply added the reference to the User class. The reference to the Session class is not needed, because it is not annotated with @Entity. The persistence.xml file will then be as following.

The entity manager

I now needed to create some EJB layer that will help me to access to the data layer. Since I need an entity manager to communicate with MongoDB, I created a stateless EJB that provides all the entity managers I could set for my application. In this example, only one persistence unit is set, so my factory will only provide one entity manager. The code below does what I just described:

In the @PersistenceContext annotation, I specified the name of the persistence unit I have already set in the persistence.xml file.

Accessing the data

At this time, everything is ready to access datas, from writing it into the database, to reading it from the database. Since I used EJBs in my project, I firstly created an interface, in this way:

The interface declares two methods, that are all I needed to start writing to and reading from my database, and below is the implementation:

First of all, I created a stateless bean, so I can use it everywhere in my project just decorating an attribute with the @EJB annotation. I then added the reference to the entity manager, and injected the value provided from the factory I created above using the @Inject annotation.

The insert into the database is really simple and does not need any further explanation. Searching into the database using Hibernate OGM, instead, requires some attentions. I needed to obtain the session from the entity manager, and using that session, I can query my database, using HQL, the Hibernate Query Language. In the moment I write this article, Hibernate OGM does not support Criterias, so the only permitted options are using either QBE or HQL, and I definitely prefere the second one.

With this, I conclude this article. Obviously, everything explained here can be extended and used in better ways, but this is a good start if you just want to start using MongoDB in WildFly, connecting to it through Hibernate Search.

Every suggestion and correction is welcome!

EDIT: based on some updates in Hibernate and on comments, I added a 2nd part on this article. You can read it here.