NetBeans Project

Full version of the quiz server

In the previous lecture I showed a basic example of a Spring Boot application that could pull quiz questions out of a quiz database. In this lecture we are going to complete the example by making it possible to interact with the full quiz database. I will also be providing a front end to test the full application. The front end allows students to take the quiz, and then saves their answers in the database.

The front end

To demonstrate that our server is functional I have provided a web application that you can run in a browser.

To run the front end, start by downloading the project folder by clicking the folder above. The project makes use of a quiz database. You will need to create an empty quiz database in the MySQL workbench and then import the database files located in the database folder in the project folder.

To run the full application, build and run the NetBeans project to start up the back end server. Then, open the web folder inside the project folder and double-click on the quiz.html file to load the front end in a browser.

Select a student and quiz and click Start to load the quiz questions.

After clicking the radio buttons to answer the questions, click Submit. The web application will send the answers the user give to the back end server and then display a confirmation message.

What we need to do

The first example Spring Boot project that I showed in the previous lecture nodes classes for working with the questions table in the quiz database. We will not need to make any modifications to those classes.

For the full version we need to add classes to work with the quizzes, students, and responses tables. The table below shows the additional URL and verb combinations our server will need to support.

URLVerbDescription
/quizzesGETFetch a list of all available quizzes
/studentsGETFetch a list of all available students
/answersPOSTPost an answer to the table of responses

Additional data classes

The first step is to add any additional data classes we need. For each table in the database we need to set up a Java class whose structure matches that of the table.

Here is the Student class:

public class Student {
    private int id;
    private String name;
    
    public Student() {}
    
    public int getId() { return id; }
    public String getName() { return name; }
    
    public void setId(int id) { this.id = id; }
    public void setName(String name) { this.name = name; }
}

The Quiz class:

public class Quiz {
    private int id;
    private String title;
    
    public Quiz() {}
    
    public int getId() { return id; }
    public String getTitle() { return title; }
    
    public void setId(int id) { this.id = id; }
    public void setTitle(String title) { this.title = title; }
}

The Answer class:

public class Answer {
    private int student;
    private int question;
    private String response;
    
    public Answer() {}
    
    public int getStudent() { return student; }
    public int getQuestion() { return question; }
    public String getResponse() { return response; }
    
    public void setStudent(int student) { this.student = student; }
    public void setQuestion(int question) { this.question = question; }
    public void setReponse(String response) { this.response = response; }
}

I have also set up row mapper classes for the student and quiz data classes.

DAO classes

Each table also gets a DAO class that handles traffic to and from its table. The only one of these that I will show here is the AnswerDAO class. This class needs to handle inserts:

@Repository
public class AnswerDAO {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    public void save(Answer answer) {
        String insertSQL = "INSERT INTO responses (student,question,response) values (?, ?, ?)";
        jdbcTemplate.update(insertSQL,answer.getStudent(),answer.getQuestion(),answer.getResponse());
    }
}

The code here follows the same pattern that we saw in the last lecture. The only difference here is that we are setting up a SQL string with multiple place holders. To execute the insert statement we call the update() method. The first parameter to update() is the SQL string. The remaining parameters are values used to fill in the place holders.

Controller classes

This version features three new controller classes.

The StudentController class supports a single request, a GET request that fetches the list of all of the students.

@RestController
@RequestMapping("/students")
@CrossOrigin(origins="*")
public class StudentController {
    private StudentDAO studentDAO;
    
    public StudentController(StudentDAO dao) {
        this.studentDAO = dao;
    }
    
    @GetMapping()
    public List<Student> fetchAll() {
        return studentDAO.findAll();
    }
    
}

Unlike the GET request we saw in the last lecture, this request does not need query parameters.

The QuizController class is similar. It supports a simple GET request to fetch a list of all quizzes.

The AnswerController supports a single request, a POST request that allows a client to upload a single answer to a single question.

@RestController
@RequestMapping("/answers")
@CrossOrigin(origins="*")
public class AnswerController {
    private AnswerDAO answerDAO;
    
    public AnswerController(AnswerDAO dao) {
        this.answerDAO = dao;
    }
    
    @PostMapping
    public void save(@RequestBody Answer answer) {
        answerDAO.save(answer);
    }
}

In a POST request a client will send a JSON representation of the data to post in the body of the request. To receive that body and turn it into an object, we add a single parameter to the save() method that is annotated with @RequestBody.

Testing a Spring Boot server

Once we have constructed a Spring Boot server we will want to test each of the requests it supports. One way to test the server is to write a front end that can send each one of those requests. For this example I have written a simple web application consisting of an HTML page and some JavaScript code to go along with it.

When the application runs in a browser you can use the developer tools in the browser to watch the interactions between the browser and the server.

For example, when I open the web page in the Chrome browser I can right-click in the page and choose the Inspect command to bring up the Chrome developer tools.

Clicking on the Network tab in the developer tools and reloading the page shows all of the traffic that flows from the server to browser. Here we can see the students and quizzes GET requests that the page sent. Clicking on one of these requests and clicking the Response sub-tab shows the JSON code that the server sent to the browser.

Clicking the Start button will cause the page to send a request for a list of questions in the selected quiz. You can click on that request in the Network area to see the data that the server sent us.

Once we have answered all of the questions and clicked Submit the page will send a separate POST to the server for each question we answered.

Each POST actually appears twice in the list, because the browser first sends a special OPTIONS request to the server to see if it will accept the POST, and then sends the POST. If you click on one of the POST requests you can see the JSON code that the page sent to the server by clicking on the Payload subtab for that request.

Testing without a front end

How do you test a Spring Boot server if you don't have a front end application written? To do that we can make use of a special tool, Postman. You can download Postman from https://www.getpostman.com/apps.

The Postman application allows you to construct requests using all available HTTP verbs, and provides a very nice graphical interface for constructing your requests and viewing responses.

To make a new request in Postman you simply select the method type and enter the URL. Clicking Send sends your request to the server and displays the response that comes back.

To send a POST request change the method to POST, enter the URL, and then click the Body tab to enter a body for the request. Select the "raw" format for the body and select JSON as the content type. Type out the JSON code for the object you want to send in the editor and then click Send. If everything is set up correctly the server should respond with an HTTP status code of 200 to indicate that the request was successful.