In this lab you will implement basic Spring MVC Controllers to invoke application functionality and display results to the user.
What you will learn:
Specific subjects you will gain experience with:
ViewResolver
Estimated time to complete: 30 minutes
Quick instructions for this exercise have been embedded within
the lab materials in the form of TODO comments. To display them,
open the Tasks
view (Window >> Show View >>
Tasks (not Task
List)).
The instructions for this lab are organized into three main sections.
This project is already setup as a Spring Boot application -
check the pom.xml
to see the Spring
Boot dependencies being used (TODO-01). Do not modify the POM.
Run this as a Spring Boot application using Run As … Spring Boot App
(on
STS) or as a Java application on any other IDE (TODO-02).
Go to http://localhost:8080 and you should see a simple
home page. The original HTML is in src/main/resources/templates/index.html
.
Note | |
---|---|
If your application deploys successfully there should be a lot of logging output in the console window and the images on the page should appear correctly. |
If you click on either link you will get the Spring Boot "Whitelabel Error Page" because neither exists (status-404).
Open HelloController.java
and you
will see the home()
method that
allowed the home-page to work - it simply returned classpath:/templates/index.html
and since
this is a maven derived project, that translates to src/main/resources/templates/index.html
.
Add a new method (follow the instructions in TODO-03) to
implement the welcome page - which already exists at src/main/resources/templates/welcome.html
.
It expects a {{name}}
attribute.
Once the application restarts, return to the home page and see if the Hello page link works. You should see a minimal page containing the text "Hello from …".
Note | |
---|---|
The application includes Spring Boot Developer Tools which will automatically restart the application if any file in any of the Maven source directories is changed. |
Time to do something more challenging.
The Accounts application we are developing should allow users to see a list of all accounts in the system, then view details about a particular account. This desired functionality is shown below:
You should see a listing of all accounts by name with links to view details. Once implemented, clicking on a link will take you to the account details page as shown below (however this is not yet implemented).
First we need to activate the AccountController
which is partly written
for you but Spring MVC currently doesn’t recognize it.
(TODO-05) Modify the AccountController
as required.
Once the server restarts, return to the home page, http://localhost:8080, and click on the List Accounts link. You should see a list of accounts display successfully. This 'accountList' functionality has been pre-implemented for you. We will review and change some of that in a moment, but it at least gets you started with the functionality.
Now try clicking on one of the account links. You will get a 404 error page indicating there is no handler for this request because the 'accountDetails' functionality has not yet been implemented.
It is good practice to Unit test your classes and the AccountController
is no exception. Go to the
AccountControllerTests
, review the
only test in there, testHandleListRequest()
- try running it
(TODO-06). It should pass.
Because this is a Spring Boot application and Spring Web and Spring MVC are on the classpath, the Dispatcher Servlet and a default Spring MVC setup has been configured, allowing our controllers to work.
If you look in AccountsApplication.java
you will see:
@EntityScan
to find our
JPA domain objects.RootConfig
to define
our application and other beansOpen RootConfig.java
. What does it
do?
rewards-db
project).accountManager
bean - the key service that we are using to load accounts from the
database for display.MustacheViewResolver
so our template views
work.Finally, review the Java implementation of the AccountController
to see how it works:
@RequestMapping
annotation ties the /accountList
URL
to the accountList()
methodAccountManager
to load a list of
AccountsaccountList.html
template view to render the
list by returning its location as a String
MustacheViewResolver
hasn’t been
configured with their locationLets quickly summarize the big picture. What happened when you clicked on the Account List link?
The browser issued a GET request to http://localhost:8080/accountList
which
set the following steps in motion:
DispatcherServlet
.DispatcherServlet
then invoked
the accountList()
method on the AccountController
based on the @RequestMapping
annotation.AccountController
loaded
the account list and selected the "accountList.html" view.accountList.html
rendered the response which you see before you (actually the
Mustache Template processor did the rendering).At this point you should have a good feel for how everything works so far. You should also have an idea of how to add the remaining "accountDetails" functionality to this application. You simply need to define a new method encapsulating this functionality, test it, and map it to the appropriate URL. You’ll do that soon.
But first let’s get rid of those absolute paths to views.
The view name in our handler method uses an absolute path. this means the method is aware of the specific type and location of the views that will be rendered (HTML templates in this case). They are also long and tedious to use.
Spring recommends decoupling request handling from response rendering details. In this step, you will add a ViewResolver to provide a level of indirection.
(TODO-07a - TODO-7d) Do the following . Modify AccountController.accountList
to return the
logical view name accountList
.
Comment out the MustacheViewResolver
@Bean method in RootConfig
. Get
Spring Boot to set it up by specifying the necessary configuration
properties in application.properties
.
Modify the methods in HelloController
to return just the logical view name
Once the application has restarted, navigate through the web-site and ensure it all still works. If you are still able to view the home page, hello page and the list of accounts, your changes are correct.
Strictly speaking we should have tested this first, so return to
the AccountControllerTests
(TODO-08)
and refactor so that it expects the logical view name. Rerun the
test, it should work again.
Now you will implement the handler method that supports the functionality for the missing account details page. Once you have completed this section, you will no longer get a 404 when you click on an account link from the account list view. Instead, you will see the details of that account.
(TODO-09) In the AccountController
,
add a method to handle requests for account details. The method
should use the account identifier passed with the HTTP request to
load the account, add it to the model, and then select a view. What
attribute name will you use for the account attribute when you add
it to the model?
Tip | |
---|---|
In your web browser, try clicking on an account and look at the URL to see which parameter name is used to pass in the account identifier. Ignore the 404 error. The Mustache template has already been implemented for you.
Review it in the |
We’re almost done! There are two things we still have to do. First of all, we have to test the controller.
(TODO-10) Open AccountControllerTests
and review how the
accountList() method has been tested. As you can see, it just calls
the handler method (without having to worry about doing any web
setup) and inspects if the model has been correctly filled. In this
step, we will do the same for the accountDetails() method.
Implement a method called testHandleDetailsRequest() to test the controller - in a similar way to testHandleListRequest(). There should be one attribute in the model. What is its name? What type is it? Get the attribute and confirm it contains the right data. Don’t forget to annotate the new method with @Test.
Note | |
---|---|
The ability to test Spring MVC Controllers out-of-the-container is a useful feature. Strive to create a test for each controller in your application. You’ll find it proves more productive to test your controller logic using automated unit tests, than to rely solely on manual testing within your web browser. |
When all tests pass, carry on.
Finally (TODO-11) try to run the web application again and make sure the functionality you implemented works. If it doesn’t, try to find where you might have gone wrong and possibly talk to your instructor.
If there is time left, you can try this optional section.
Spring’s Mock MVC testing framework allows a JUnit test to
drive Spring MVC as if it was running in a container - enabling
more powerful testing that the simple AccountControllerTests
you have been
using.
Open the class MockMvcTests
and
follow the TODO steps. Most of the code has been written for you.
The important part is to see if you understand how the tests work -
we did not cover Mock MVC testing in the course notes.
For more information, refer to the online documentation.