Level 7 - Milestone 5
Milestone 5 - The Service Layer
This milestone is dedicated to the service package, and adding a service layer class for our
application
Before completion of this milestone, students will:
- Add a service-layer class for their application
- Add a method that is called from the controller class
Add a Service Class
Create a packaged named "service" at the same level as the presentation package. Service-layer
classes
contain all of the "business logic" of the application. Perhaps one of the best ways
to describe what the service layer contains, is by describing what it doesn't do. Remember that
the controller
classes are used to simply map request URLs to the method that we want called when they are hit,
and the
repository layer is responsible for simply retrieving a piece of data; all other code belongs in
the
service layer.
The @Service is a stereotype annotation for @Component. @Service tells us humans that this
class is a service-layer class, but is functionally the same as @Component: it allows Spring
to recognize this class during component scanning, and therefore handle the instantiation of
this
class for us.
For now, we will just move the simple functionality from our controller class down into the
service layer.
Having done this, your service class will look similar to this:
package org.jointheleague.api.cheetah.Cheetah_Search.service; import org.springframework.stereotype.Service; @Service public class LocService { public String getResults(String query){ return "Searching for books related to " + query; } }
Connecting the Controller and Service class
We now need to have the method in our controller class call the method in our service class.
Remember
that the big picture is our controller class receives a request which is passed to the service
layer. The service
layer will, in turn, call a method in a repository-layer class to retrieve the relevant data,
which will then be
returned all the back up through the classes to the user.
Before we can call the method in our service layer, we need to give the controller class an
instance of
the service class to work with. Luckily Spring makes this easy for us. Because of the Spring's
dependency injection,
we will not use the "new" keyword to instantiate any of our controller, service, or repository
layer classes, Spring handles
that for us. In this case, all we need to do is add field for the service class in the
controller, and provide a constructor
that takes that service class as a parameter. Again, Spring will take it from there and actually
supply the controller
class with an instance of the service class when the controller class itself is automatically
instantiated by Spring.
Your controller class should now look something like this:
package org.jointheleague.api.cheetah.Cheetah_Search.presentation; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiResponse; import io.swagger.annotations.ApiResponses; import org.jointheleague.api.cheetah.Cheetah_Search.service.LocService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class LocController { private final LocService locService; public LocController(LocService locService) { this.locService = locService; } @GetMapping("/searchLocResults") @ApiOperation(value = "Searches for articles matching the search term", notes = "Response may include multiple Result values.", response = String.class) @ApiResponses(value = { @ApiResponse(code = 200, message = "Result(s) found"), @ApiResponse(code = 404, message = "Result(s) not found") }) public String getResults(@RequestParam(value="q") String query){ return locService.getResults(query); } }
Our Use of the Service Layer
Given the desired functionality of our application, our service class will remain rather sparse. However, if we wanted to manipulate data or process it in any way, we would add code to handle that within the service layer. Another common scenario handled by the service layer is converting our data into a specific "domain object" that we intend to return to our user in a certain format. Domain objects are especially useful when combining information from multiple sources into a singular format, which allows us to return a uniform set of data to the user.
Summary of Code Changes for this Milestone
-
Cheetah-Search
- src
- main
- java
- org.jointheleague.level7.cheetah
- config
- ApiDocConfig.java
- presentation
- HomeController.java
- LocController.java
- service
- resources
- application.yml
- build.gradle