The microservices

So we split the monolith into three projects (microservices): the user service, the user address service, and the gateway service.

The user service classes remained unchanged after the migration from the monolith version. So there's nothing to comment on.

The UserAddress class had to be changed to become a microservice. The first change was made on the entity.

Here is the monolith version:

@Entity
public class UserAddress implements Serializable {

...

@Column
@ManyToOne
private User user;

...

public UserAddress(User user, String street, String number,
String city, String zip) {
this.user = user;
this.street = street;
this.number = number;
this.city = city;
this.zip = zip;
}

...

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}

...

}

Here is the microservice version:

@Entity
public class UserAddress implements Serializable {

...

@Column
private Long idUser;

...

public UserAddress(Long user, String street, String number,
String city, String zip) {
this.idUser = user;
this.street = street;
this.number = number;
this.city = city;
this.zip = zip;
}

public Long getIdUser() {
return idUser;
}

public void setIdUser(Long user) {
this.idUser = user;
}

...

}

Note that in the monolith version, user was an instance of the User entity:

private User user;

In the microservice version, it became a number:

private Long idUser;

This happened for two main reasons:

  1. In the monolith, we have the two tables in the same database (User and UserAddress), and they both have physical and logical relationships (foreign key). So it makes sense to also keep the relationship between both the objects.
  2. The microservice should have its own database, completely independent from the other services. So we choose to keep only the user ID, as it is enough to load the address properly anytime the client needs.

This change also resulted in a change in the constructor.

Here is the monolith version:

public UserAddress(User user, String street, String number, 
String city, String zip)

Here is the microservice version:

public UserAddress(Long user, String street, String number, 
String city, String zip)

This could lead to a change of contract with the client regarding the change of the constructor signature. But thanks to the way it was built, it wasn't necessary.

Here is the monolith version:

public Response add(UserAddress address)

Here is the microservice version:

public Response add(UserAddress address)

Even if the method is changed, it could easily be solved with @Path annotation, or if we really need to change the client, it would be only the method name and not the parameters (which used to be more painful).

Finally, we have the gateway service, which is our implementation of the API gateway design pattern. Basically it is the one single point to access the other services.

The nice thing about it is that your client doesn't need to care about whether the other services changed the URL, the signature, or even whether they are available. The gateway will take care of them.

The bad part is that it is also on a single point of failure. Or, in other words, without the gateway, all services are unreachable. But you can deal with it using a cluster, for example.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.46.78