Spring MVC Interview Questions and Answers for Beginners and Experienced

In this article, we will discuss 10 frequently asked Spring MVC interview questions with answers for beginners and experienced candidates.

YouTube Video

1. What is Spring MVC?

Spring MVC is a popular Java Web MVC framework for building web applications as well as RESTful web services. 

The MVC term signifies that it follows the Model View Controller design pattern. It implements all the basic features of the core Spring framework like Dependency Injection and Inversion of Control.


2. Why Should We Use Spring MVC?

Spring MVC implements a clear separation of concerns that allows us to develop and unit test our applications easily.

The all the Spring MVC components like:
  • Dispatcher Servlet
  • Controllers
  • View Resolvers
  • Views, Models
  • ModelAndView
  • Model and Session Attributes
are completely independent of each other, and they are responsible for one thing only.

Another important thing is that we aren't tied to a specific view technology (for example, JSP), but we have the option to choose from the ones we like the most ( Thymeleaf, Freemarker, Mustache, etc).

Also, we don't use Spring MVC only in web applications development but in the creation of RESTful web services as well.

3. How does Spring MVC Works Internally or Explain Spring MVC Request Flow?

The below diagram represents how an HTTP request is processed from start to end in the Spring MVC framework step by step.

Step 1 - When the client (browser) sends an HTTP request to a specific URL. The DispatcherServlet of Spring MVC receives the request.
Step 2 DispatcherServlet consult to HandlerMapper to identify which controller is responsible to handle the HTTP request.
Step 3 - HandlerMapper selects the controller which is mapped to the incoming request URL and returns the (selected Handler) and Controller details to DispatcherServlet.
Step 4 - Now DispatcherServlet knows which controller is responsible to process the request so DispatcherServlet will forward that request to the corresponding controller to process the request.
Step 5 - Now the Controller process the request, validates the request and creates a model with data. Finally, the Controller returns the logical name of view and model to the DispatcherServlet.
Step 6 - DispatcherServlet consult ViewResolver to resolve a logical view with the physical view that exists in the application.
Step 7 ViewResolver responsible to map logical view with an actual view and return the actual view details back to the DispatcherServlet.
Step 8 - Now DispatcherServlet sends the view and model to the View component.
Step 9 - The View component merges view and model and forms a plain HTML output. Finally, the View component sends HTML output back to the DispatcherServlet.
Step 10 - The DispatcherServlet finally sends HTML output as a response back to the browser for rendering.

4. What is the Difference Between @Controller and @RestController?

The main difference between the @Controller and @RestController annotations is that the @ResponseBody annotation is automatically included in the @RestController. This means that we don't need to annotate our handler methods with the @ResponseBody. We need to do this in a @Controller class if we want to write response type directly to the HTTP response body (Ex: JSON or XML).

@Controller annotation example: in the below code snippet notice the @ResponseBody added to each of the handler methods in the return value.
@Controller
@RequestMapping
("/api/v1") public class EmployeeController { @Autowired private EmployeeRepository employeeRepository; @GetMapping("/employees") public
@ResponseBody List<Employee> getAllEmployees() { // logic goes here } @GetMapping("/employees/{id}") public @ResponseBody ResponseEntity<Employee> getEmployeeById(@PathVariable(value = "id") Long employeeId) throws ResourceNotFoundException { // logic goes here } @PostMapping("/employees") public @ResponseBody Employee createEmployee(@Valid @RequestBody Employee employee) { // logic goes here } @PutMapping("/employees/{id}") public @ResponseBody ResponseEntity<Employee> updateEmployee(@PathVariable(value = "id") Long employeeId, @Valid @RequestBody Employee employeeDetails) throws ResourceNotFoundException { // logic goes here } @DeleteMapping("/employees/{id}") public @ResponseBody Map<String, Boolean> deleteEmployee(@PathVariable(value = "id") Long employeeId) throws ResourceNotFoundException { // logic goes here } }
To use @RestController in the above example, all we need to do is modify the @Controller to @RestController and remove the @ResponseBody from each method. The resultant class should look like the following:
@RestController
@RequestMapping("/api/v1")
public class EmployeeController {
    @Autowired
    private EmployeeRepository employeeRepository;

    @GetMapping("/employees")
    public List<Employee> getAllEmployees() {
         // logic goes here
    }

    @GetMapping("/employees/{id}")
    public ResponseEntity<Employee> getEmployeeById(@PathVariable(value = "id") Long employeeId)
        throws ResourceNotFoundException {
       // logic goes here
    }
    
    @PostMapping("/employees")
    public Employee createEmployee(@Valid @RequestBody Employee employee) {
        // logic goes here
    }

    @PutMapping("/employees/{id}")
    public ResponseEntity<Employee> updateEmployee(@PathVariable(value = "id") Long employeeId,
         @Valid @RequestBody Employee employeeDetails) throws ResourceNotFoundException {
       // logic goes here
    }

    @DeleteMapping("/employees/{id}")
    public Map<String, Boolean> deleteEmployee(@PathVariable(value = "id") Long employeeId)
         throws ResourceNotFoundException {
        // logic goes here
    }
}
@RestController is a combination @Controller and @ResponseBody annotations.

5. What Are the @RequestBody and the @ResponseBody Annotations?

The @RequestBody annotation, used as a handler method parameter, binds the HTTP Request body to a transfer or a domain object. Spring automatically deserializes incoming HTTP Requests to the Java object using HTTP Message Converters.

For example: Let's client sends an HTTP POST request with a JSON as request body:
{
   "firstName": "Ramesh",
   "lastName": "fadatare",
   "emailId": "[email protected]"
}
public class Employee {
    private long id;
    private String firstName;
    private String lastName;
    private String emailId;
    // getters and setters
}
Now we can use @RequestBody annotation to directly bind JSON to Java object:
    @PostMapping("/employees")
    public @ResponseBody Employee createEmployee(@Valid @RequestBody Employee employee) {
        return employeeRepository.save(employee);
    }
When we use the @ResponseBody annotation on a handler method in the Spring MVC controller, it indicates that we'll write the return type of the method directly to the HTTP response body. We'll not put it in a Model, and Spring won't interpret it as a view name.

For example, The below method handler write a List of employees to the HTTP response body and @ResponseBody annotation converts the List of employee objects to a JSON array of objects:
    @GetMapping("/employees")
    public @ResponseBody List<Employee> getAllEmployees() {
        return employeeRepository.findAll();
    }

6. How to Handle Exceptions in Spring MVC Applications?

We have three options for exceptions handling in Spring MVC:
  • Using HTTP Status Codes
  • Controller-Based Exception Handling (Using @ExceptionHandler)
  • Global Exception Handling (Using @ExceptionHandler)

Using HTTP Status Codes

Normally any unhandled exception thrown when processing a web request causes the server to return an HTTP 500 response. However, any exception that you write yourself can be annotated with the @ResponseStatus annotation When an annotated exception is thrown from a controller method, and not handled elsewhere, it will automatically cause the appropriate HTTP response to be returned with the specified status code.

For example, here is an exception for a missing order.

@ResponseStatus(value=HttpStatus.NOT_FOUND, reason="No such Order")  // 404
 public class OrderNotFoundException extends RuntimeException {
     // ...
 }
And here is a controller method using it:

 @RequestMapping(value="/orders/{id}", method=GET)
 public String showOrder(@PathVariable("id") long id, Model model) {
     Order order = orderRepository.findOrderById(id);

     if (order == null) throw new OrderNotFoundException(id);

     model.addAttribute(order);
     return "orderDetail";
 }
A familiar HTTP 404 response will be returned if the URL handled by this method includes an unknown order id.

Controller-Based Exception Handling

Another way to handle the exceptions is by using the @ExceptionHandler annotation. We add @ExceptionHandler methods to any controller and use them to handle the exceptions thrown from inside that controller. 
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<?> resourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
  ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
  return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
}

Global Exception Handling

The third option for handling errors is by @ControllerAdvice classes. It'll allow us to apply the same techniques, only this time at the application level and not only to the particular controller. To enable this, we need to use the @ControllerAdvice and the @ExceptionHandler together. This way exception handlers will handle exceptions thrown by any controller.

For example:
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<?> resourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
        return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<?> globleExcpetionHandler(Exception ex, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage(), request.getDescription(false));
        return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

7. What Are the Annotations You Used in Your Spring MVC Applications?

  • @Controller
  • @RequestBody Annotation
  • @RequestMapping
  • @GetMapping
  • @PostMapping
  • @PutMapping
  • @DeleteMapping
  • @PatchMapping
  • @ControllerAdvice
  • @ResponseBody Annotation
  • @ExceptionHandler
  • @ResponseStatus
  • @PathVariable
  • @RequestParam
  • @RestController
  • @ModelAttribute
  • @CrossOrigin
  • @InitBinder
Apart from the above annotations, if you have used any other Spring web annotations then don't forget to mention them in the interview.

Read more about Spring MVC annotations at Spring MVC Annotations with Examples

8. What Is the Use of @Autowired Annotation?

We can use the @Autowired to mark a dependency which Spring is going to resolve and inject. We can use this annotation with a constructorsetter, or field injection.

Constructor Injection:
@RestController
public class CustomerController {
    private CustomerService customerService;
 
    @Autowired
    public CustomerController(CustomerService customerService) {
        this.customerService = customerService;
    }
}
Setter Injection:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CustomerController {
    private CustomerService customerService;
 
    @Autowired
    public void setCustomerService(CustomerService customerService) {
        this.customerService = customerService;
    }
}
Field Injection:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CustomerController {
    @Autowired
    private CustomerService customerService;
}
Learn more about @Autowired annotation at Spring @Autowired Annotation with Example

9. What is the use of @ModelAttribute annotation?

The @ModelAttribute annotation is one of the most important annotations in Spring MVC. It binds a method parameter or a method return value to a named model attribute and then exposes it to a web view.

@ModelAttribute can be used either as a method parameter or at the method level.

At the Method Level

When the annotation is used at the method level it indicates the purpose of that method is to add one or more model attributes.
@ModelAttribute
public void addAttributes(Model model) {
    model.addAttribute("msg", "Hello World");
}
@ModelAttribute methods are invoked before the controller methods annotated with @RequestMapping are invoked.

As a Method Argument

When used as a method argument, it indicates the argument should be retrieved from the model.

For example, the employee form data will be bound to Employee bean using @ModelAttribute annotation:

@RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public String submit(@ModelAttribute("employee") Employee employee) {
    // Code that uses the employee object

    return "employeeView";
}

10. Explain @PathVariable @RequestParam Annotations?

@PathVariable annotation

With the @PathVariable annotation, we bind the request URL template path variable to the method variable. 
For instance, with the http://localhost:8080/springmvc/hello-world/100/Ramesh/ URL, the 100 value is bound to the id variable and the "Ramesh" value to the name variable.
    @GetMapping(path = "/hello-world/{id}/{name}")
    public HelloWorldBean helloWorldPathVariable(@PathVariable long id, 
        @PathVariable(name = "name") String name) {
        return new HelloWorldBean(id, name);
    }

@RequestParam annotation

With @RequestParam annotation, we can extract values from the query string.

    @GetMapping(path = "/hello-world")
    public HelloWorldBean helloWorldPathVariable(@RequestParam long id, 
        @RequestParam String name) {
        return new HelloWorldBean(id, name);
    }
While @RequestParams extract values from the query string, @PathVariables extract values from the URI path.

Comments