Lesson 2: Expanding Our First Controller
In this lesson, we’re going to continue the work we started previously, by taking our naive controller implementation to the next level.
2. Lesson Notes
The relevant module you need to import when you're starting with this lesson is: m6-expanding-our-first-controller-start
If you want have a look at the fully implemented lesson, as a reference, feel free to import: m6-expanding-our-first-controller-end
2.1. The findOne() Method
Now that our web support is starting to take shape, let’s do some simple CRUD in our application.
Our current findOne implementation in the ProjectController simply returns some random data. However, what it should be doing is using the service layer.
So let’s inject the ProjectService via the constructor:
Now let’s use it in the findOne method.
Notice that we need the id of the Project, since that’s what we’re searching by. So let’s make sure that’s a parameter in the method here.
Next, we'll simply delegate to the service, extract the potential value and return:
The parameter also needs to be mapped to a path component, or path variable, by using the @PathVariable annotation.
Finally, we'll remove the hardcoded "1" in the URL and replace with the id path variable. Now the findOne method will be:
Let’s now run the application.
We'll open up Postman and consume it from the client side by calling: http://localhost:8080/projects/159.
2.2. Error Handling Problems
There are a few things to address here. We’ll, of course, dedicate a full lesson to improving our exception/error handling, so we won’t fix these here. But let’s at least have a quick look at what the problems are.
One is that we’re seeing the raw exception here which is obviously not ideal.
The second issue is the status code. Logically, we’re expecting back a 404 (Not Found) since we’re trying to access a Resource that isn’t found. However, notice what we’re getting a 500 Server Error which is not correct.
Finally, the third point is that, instead of us, proactively checking the result, we’re allowing the exception to be thrown by an internal piece of logic, namely, the Optional. It’s usually better to take control over that.
We’ll deal with all of the issues in a separate, dedicated lesson.
2.3. Write Operation
So far, we've seen a read operation. Let’s now do a write operation as well, as that’s going to involve other aspects of Spring MVC.
We’re going to do a simple save: basically, the creation of a new Project Resource.
First off, let’s define the basic operation with no mappings:
Next, we're going to map this to an HTTP POST using @PostMapping. We'll also map the body of the HTTP request to the Project variable here, using @RequestBody: