As you may have already noticed, we created two situations in the code of the preceding section— one coupled (getUserCoupled) and another decoupled (getUserDecoupled):
public Response getUserCoupled(
@PathParam("name") String name,
@PathParam("email") String email)
Why is this a coupled method and hence a coupled service? That's because it is highly attached to the method signature. Imagine it is a search service and "name" and "email" are filters. Now imagine that sometime in the future, you need to add another filter—one more parameter in the signature.
OK, you could keep the two methods available at the same time, so that you will not break the client contract and have to change all clients available. But maybe you have a lot of them— mobile, services, web pages, and many more. All of these need to be changed to support the new feature anyway. Wouldn't it be better to reduce the friction in this process?
Now, look at this:
public Response getUserDecoupled(@HeaderParam("User") User user)
In this User search method, what if you need to add a new parameter to the filter? Then, go ahead and add it! There are no changes in the contract, and all clients are happy.
If your User POJO starts with only two properties and ends with a hundred after a year, no problem. Your service contract is left untouched and even your clients, who are not using the new fields, are still working. Sweet!
The result of coupled/decoupled services can be seen in the calling service:
public Response doSomethingCoupled(String name, String email){
WebTarget service =
target.path("webresources/userService/getUserCoupled");
service.queryParam("name", name);
service.queryParam("email", email);
...
}
The calling service is coupled to the called one: it has to know the called service properties' names and needs to add/update each time it changes.
Now, look at this:
public Response doSomethingDecoupled(User user){
WebTarget service =
target.path("webresources/userService/getUserDecoupled");
Response response;
try {
response = service.request().header("User",
Entity.json(user)).get();
...
}
In this case, you only need to refer to the one and only service parameter ("User") and it will never change, no matter how the User POJO is changed.