15

I have a few layers in my WebApplication: Presentation, Service, DAO, Domain.

Services call DAO objects which reads data from a Database/File whatever.

I have a Controller that needs to fetch data from different Services and set them as part of the Response.

Should I put the logic to call different Services in the Controller method or should I create some sort of Facade which in turn will call different Services? If so, in what Layer should the Facade reside?

@Path("/")
public class MyController {

  @Autowired
  private FirstService firstService;

  @Autowired
  private SecondService secondService;

  @GET
  public Response getData(@QueryParam("query") final String query) {
      final MyResponse response = new MyResponse();

      // Service 1
      final String firstData = firstService.getData(query);
      response.setFirstData(query);


      if (someCondition) {
        // Service 2
        final String secondData = secondService.getData(query);
        response.setSecondData(query);
      }

      // more Service calls maybe

      return Response.status(Response.Status.OK).entity(response).build();
  }

}
Diyarbakir
  • 539
  • 2
  • 5
  • 12
  • 1
    Related [stackoverflow](http://stackoverflow.com/q/29394109) question. Personally I think your current code is fine. – avik Apr 25 '16 at 12:06
  • 1
    Yes. It's **dispatching** business what fits well into **Controller** purpose. I would not do what @lJoSeTe4ever suggest. That way is mixing up 2 services into 2 by its URL. It's coupling services. **So far, your solution is fine**, If you don't want to do such *if/else* I suggest to you to implement a *Broker*. Broker has all the service and it does the choice instead of doing it at *MyController*. *Broker* is like a global Service which concentrate all others into the same point. Depends on how many times you have to do the same *if/else* – Laiv Apr 25 '16 at 13:18

1 Answers1

11

In my humble opinion, the controller should be the "facade" itself, that means that the controller should decide which service to call, and the services should be in charge of generating the response object.

What I would do is to define a method per action, and discriminate the service using REST naming, something like this:

@Path("/")
public class MyController {

  @Autowired
  private FirstService firstService;

  @Autowired
  private SecondService secondService;

  @RequestMapping(value = "/service1/{query}", method = {RequestMethod.GET})
  public Response getData(@RequestParam("query") final String query) {

      return firstService.yourMethod(); // inside the service you handle the response.
  }

  @RequestMapping(value = "/service2/{query}", method = {RequestMethod.GET})
  public Response getData(@RequestParam("query") final String query) {

      return secondService.another(); // inside the service you handle the response.
  }

}
lJoSeTe4ever
  • 296
  • 2
  • 6
  • *I don't think* mixing up 2 services into 2 through its url is a good idea. If they are 2 independent services, then make 1 controller per Service. Even if they have the very same interface/features/urls/whatever. Plus you are placing the choice of which one to use at client-side. So you are placing a business choice into client-side, what means (in the worst scenario), 2 calls and your business scatered in 2 facades – Laiv Apr 25 '16 at 13:23
  • MVC pattern it self is a pattern. Controller should not be restricted to call one service. If Controller is restricted to call one service, then that service might have a chance to have two responsibility, which will disobey "single responsibility principle". – Young Hyun Yoo Feb 04 '18 at 09:37