Spring Boot + @RestController + REST API

In this blog, we will learn the difference between @Controller and @RestController. How @RestController works internally – with the help of a working example.

Spring Boot @Controller and @RestController Annotations

Usually, dispatcher servlet is responsible for identifying the controller and appropriate request handler method inside the controller by URL matching.

@Controller: A spring mvc controller is used typically in GUI-based applications where the response is generally HTML content.

e.g.

@Controller
@ResponseBody
@RequestMapping("employees")
public class EmployeeController 
{
    @RequestMapping(value = "/{name}", method = RequestMethod.GET, produces = "application/json")
    public Employee getEmployeeByName(@PathVariable String name) {
 
        //pull date
 
        return employee;
    }
}

@RestController:  It is a convenience annotation that is itself annotated with @Controller and @ResponseBody. The handler methods will return the JSON/XML response directly to client rather using view resolvers.

e.g.
@RestController
@RequestMapping("employees")
public class EmployeeController 
{
    @RequestMapping(value = "/{name}", method = RequestMethod.GET, produces = "application/json")
    public Employee getEmployeeByName(@PathVariable String name) {
 
        //pull date
 
        return employee;
    }
}

Spring Boot: @RestController

package com.the.basic.tech.info.rest.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

// http://localhost:8080/spring-boot-rest-api/userlogin
// http://localhost:8080/spring-boot-rest-api/adminlogin

@RestController
public class SpringBootRestController {
	@RequestMapping("/userlogin")
	public String userValidation() {
		return "User: Successfully logged in!";
	}

	@RequestMapping("/adminlogin")
	public String adminValidation() {
		return "Admin: Successfully logged in!";
	}
}

Maven File (pom.xml)

Maven dependencties file would be like as below

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.example</groupId>
	<artifactId>spring-boot-rest-api</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.4</version>
	</parent>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
	</dependencies>
	<properties>
		<java.version>1.8</java.version>
	</properties>
</project>

Spring Boot: Project Structure

High level project structure

Spring Boot Project Structure

Spring Boot: SpringBootSecurityConfig

We need to extend WebSecurityConfigurerAdapter class as below

package com.the.basic.tech.info.rest.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SpringBootSecurityConfig extends WebSecurityConfigurerAdapter {

	// Authentication : set user/password details and mention the role
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.inMemoryAuthentication()
				.passwordEncoder(org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance())
				.withUser("user").password("pass").roles("USER").and().withUser("admin").password("pass")
				.roles("USER", "ADMIN");
	}

	// Authorization : mention which role can access which URL
	protected void configure(HttpSecurity http) throws Exception {
		http.httpBasic().and().authorizeRequests().antMatchers("/userlogin").hasRole("USER").antMatchers("/adminlogin")
				.hasRole("ADMIN").and()
				// sample logout customization
				.logout().logoutUrl("/logout").deleteCookies("remove").invalidateHttpSession(false).and().csrf()
				.disable().headers().frameOptions().disable();
	}
}

Application Configurations: application.yaml

Actuator endpoints we are using here for application health monitoring.

# Management
server:
  port: 8080
  servlet.context-path: /spring-boot-rest-api/
endpoints:
  hawtio:
    enabled: true
  jolokia:
    enabled: true
management:
  endpoints:
    web:
      exposure:
        include: info, health, metrics, hawtio, env

      base-path: /monitoring      
  endpoint:
    health:
      show-details: always
info:
  app:
    spring-boot-rest-api
    description:This is a microservice for springboot application testing

Spring Boot: SpringBootRestMain

package com.the.basic.tech.info.rest;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootRestMain {
	public static void main(String[] args) {
		SpringApplication.run(SpringBootRestMain.class, args);
	}
}

Spring Boot: Run Application

We need to run below maven command for running the application.

mvn spring-boot:run
Application Logs:
2021-06-05 20:25:26.427  INFO 7700 --- [           main] c.t.b.tech.info.rest.SpringBootRestMain  : No active profile set, falling back to default profiles: default
2021-06-05 20:25:29.432  INFO 7700 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-06-05 20:25:29.455  INFO 7700 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-06-05 20:25:29.456  INFO 7700 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.44]
2021-06-05 20:25:29.768  INFO 7700 --- [           main] o.a.c.c.C.[.[.[/spring-boot-rest-api]    : Initializing Spring embedded WebApplicationContext
2021-06-05 20:25:29.768  INFO 7700 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3243 ms
2021-06-05 20:25:30.921  INFO 7700 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-06-05 20:25:31.502  INFO 7700 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Will secure any request with [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@8f2098e, org.springframework.security.web.context.SecurityContextPersistenceFilter@35764bef, org.springframework.security.web.header.HeaderWriterFilter@131ff6fa, org.springframework.security.web.authentication.logout.LogoutFilter@58860997, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@161f6623, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@5d5160e6, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@d8d9199, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@6c6366cf, org.springframework.security.web.session.SessionManagementFilter@216914, org.springframework.security.web.access.ExceptionTranslationFilter@3ae9d1e2, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@f679798]
2021-06-05 20:25:31.538  INFO 7700 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 4 endpoint(s) beneath base path '/monitoring'
2021-06-05 20:25:31.619  INFO 7700 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path '/spring-boot-rest-api'
2021-06-05 20:25:31.651  INFO 7700 --- [           main] c.t.b.tech.info.rest.SpringBootRestMain  : Started SpringBootRestMain in 6.047 seconds (JVM running for 6.878)
2021-06-05 20:25:31.899  INFO 7700 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/spring-boot-rest-api]    : Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-06-05 20:25:31.899  INFO 7700 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2021-06-05 20:25:31.907  INFO 7700 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 3 ms

Spring Boot: Snapshots

Admin Login, it will prompt for username/password: http://localhost:8080/spring-boot-rest-api/adminlogin

username/password: admin/pass

Spring Boot: Snapshots
Spring Boot: Snapshots

User Login, it will prompt for username/password: http://localhost:8080/spring-boot-rest-api/userlogin

username/password: user/pass

And after successful login, it will display below screen.

Spring Boot: Snapshots

Download Source Code (Attached)

Kindly, let me know in case I missed anything. Have a nice day 🙂