I have a Spring Boot WebMVC application (with Thymeleaf) that is moving away from a direct database connection in favor of API calls to another service. I am wondering what the best architecture would be for calling the API and displaying the results to the user. Would RestTemplate be better to put in the Service class, or the Controller class (especially when thinking about error handling)? Also, would WebClient be better over RestTemplate even though it isn't using WebFlux?
Here is currently what I am thinking:
Entity:
public class Entity {
public String id;
public String name;
...
}
Service:
public class EntityService {
@Autowired
private RestTemplate restTemplate;
public List<Entity> getAllEntities() {
return restTemplate.getForObject("https://localhost.com:8081/entities", Entity.class);
}
}
Controller:
public class EntityController {
@Autowired
private EntityService entityService;
@GetMapping("/entities")
public String getAllEntities(Model model) {
model.addAttribute(entityList, entityService.getAllEntities())
return "entity"
}
}
HTML:
<!-- entity.html -->
<head>
...
</head>
<body>
<div th:each="entity : #{entityList}">
<label th:text="${entity.id}"/>
<label th:text="${entity.name}"/>
</div>
</body>
CodePudding user response:
"It depends" is the answer to all your questions :)
So to work out the answers, you need to think about your application, how big it's going to get and how you will keep it all under control as it matures. The things I'd consider are:
How many upstream API calls will your app make? If there's only 1 and virtually no business logic, then a
Service
layer might just add noise, however if you start doing things other than just straight up displaying bean properties then the less code sitting in theController
the clearer the app will be to the next person. I like to keep Controllers specific to the transport - eg HTTP or gRPC - and dealing with things like response codes, headers etc, so I generally move theif
s off to a service layer.RestTemplate
vsWebClient
is usually a great distraction. If you are using traditional blocking Spring Boot, useRestTemplate
, if you are using Reactive then useWebClient
. It doesn't really matter that much from the application code perspective, it's usually not a huge job to replace one with the other if you've got the application architecture thought out.
Another thing - try avoid a controller
package, a service
package and a model
package, group all this stuff together under the business context - in this case an Entity
, but we all know there is going to be a service, controller, models etc etc.
You really don't want to have 300 controller classes in the controller
package, best they are grouped together in a way that would make sense to the users or the product owner of an app..
My final bit of advice would be to not be afraid to change as the app gets bigger. Ensure your tests are reliable enough that you can refactor the app as you go. Things like replacing RestTemplate
with something else, changing the app structure and so on.