June 01, 2018

Spring Boot Interview Questions And Answers

What is Spring Boot?
  • Spring Boot is not a framework, it is a way to ease to create stand-alone application with minimal or zero configurations.
  • With Spring Boot we can develop spring based application with very less configuration. It provides defaults for code and annotation configuration to quick start new spring projects within no time.
  • Aim of Spring Boot is to do rapid application development. It comes with the auto-dependency resolution, embedded HTTP servers, auto-configuration, management endpoints and Spring Boot CLI.
What is the difference between Spring and Spring Boot?
  • Spring is web application framework based on Java, and Spring Boot is a module of Spring.
  • Spring provides tools and libraries to create customized web applications, where as Spring Boot is used to create a Spring application (standalone) project which can just run/ execute
  • Spring is more complex than Spring Boot.
  • It takes time to have spring application up and running. Where as Spring Boot provides the shortest way to run a spring based application.
What are the advantages and disadvantages of using Spring Boot?
Advantages
  • Reduce Development and Testing time, which increases productivity
  • Use of JavaConfig helps avoid usage of XML.
  • Avoid lots of maven imports and the various version conflicts.
  • It avoids writing lots of boilerplate Code, Annotations and XML Configuration.
  • Provide Opinionated Development approach.
  • Quick start to development by providing defaults.
  • It provides Embedded HTTP servers like Tomcat, Jetty etc. to develop and test our web applications very easily.
  • Requires less configuration-Since there is no web.xml file. Simply add classes annotated with@Configuration and then you can add methods annotated with@Bean, and Spring will automatically load up the object and manage it like it always has. You can even add @Autowired to the bean method to have Spring autowire in dependencies needed for the bean.
  • Environment Based Configuration-Using these properties, you can pass into the application which environment you are using with:-Dspring.profiles.active={enviornment}. Spring will then load up the subsequent application properties file at (application-{environment}.properties) after loading up the main application properties file.
Disadvantages:
  • It is bit difficult and time consuming process to convert existing or legacy Spring Framework projects into Spring Boot Applications.
Which build tool have you used to develop Spring Boot Application?
Spring Boot application can be developed using Maven as well as Gradle.

System Requirements for Spring?
Spring Boot 2.1.7 release requires
  • Java 8 +
  • Spring Framework 5.1.9
Build Support
  • Maven 3.3+
  • Gradle 4.4+
Servlet Container Support
  • Tomcat 9.0-Servlet Version 4.0
  • Jetty 9.4-Servlet Version 3.1
  • Undertow 2.0-Servlet Version 4.0
How to create a simple Hello World project by using Spring Boot?
1). Let's create a 'Spring Starter Project' with a name 'HelloWorld' using Spring STS. Add 'web' dependencies of Spring Web and Spring Web Services. Create a maven or a gradle project, here I have selected Maven because of which pom.xml will be added in the project. This pom.xml will contain all the metadata for the project. All the dependencies are mentioned in pom.xml.
2). Once the project is created, you can see HelloWorldApplication.java file present in com.example.demo package. This class will have @SpringBootApplication annotation, this indicates that whenever we execute this particular project it will automatically this particular class will be executed.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HelloWorldApplication {

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

}
3). Let's create another class with the name AppConfiguration inside com.example.demo package, this will act as a rest controller. For this we need to add @RestController with the class declaration. Now we will add a method with a name 'hello()', which returns a simple text. To make it as a web-service we need to add @RequestMapping annotation, we need to add a url as well, in our case it will be '/hello'

package com.example.demo;

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

@RestController
public class AppConfiguration {

@RequestMapping("/hello")
public String hello()
{
return "Hello World";
}
}
4). Now if you run HelloWorldApplication, by default our application will run on 8080 port. Let's say this port is busy. To change the port number we need to configure it in a properties file. In the resources folder, you will see application.properties. Add the below line in the propery file, this will change the port to 8081.
server.port=8081
5). Now run HelloWorldApplication, once the server is started hit 'http://localhost:8081/hello' from the browser. It will print "Hello World".

What do you understand by Dependency Injection (DI)?
  • When writing a complex Java application, application classes should be as independent as possible of other Java classes to increase the possibility to reuse these classes and to test them independently of other classes while doing unit testing. Dependency Injection helps in gluing these classes together and same time keeping them independent.
  • i.e Dependency Injection design pattern allows us to remove the hard-coded dependencies and make our application loosely coupled, extendable and maintainable. For example, 'DEPENDENCY' means class A is dependent on class B. 'INJECTION' means that class B will get injected into class A by the IoC (Inversion of Control).
  • Dependency injection can happen in the way of passing parameters to the constructor or by post-construction using setter methods.
  • In DI mainly three classes are involved: Client Class (This is the dependent on service class. In above example A is the Client class), Service Class (This provide service to client class.  In above example B is the Service class) and Injector Class (It is responsible for injecting Service class object into the client class),
  • DI is based on Inversion of Control (IoC), which is the mechanism to achieve loose-coupling between Objects dependencies. In IoC, object coupling is bound at run time by an assembler object and is typically not known at compile time using static analysis.
  • Let's say you are feeling hungry and you want something to eat. You can either cook for yourself or order it from outside. The process of getting the food at your door step is IoC. In this case, you don't need to take additional responsiblity of cooking the food. 
  • Spring IoC container is the core of Spring Framework, it creates the object, wire them together, configure and manage their complete life cycle from creation till destruction.
  • From the provided configuration metadata, the container will get the instructions on what objects to instantiate, configure, and assemble. The configuration metadata can be represented either by XML, Java annotations, or Java code.
  • The Spring IoC container makes use of Java POJO classes and configuration metadata to produce a fully configured and executable system or application.
Types of Dependency Injection:
1). Constructor - Dependencies are provided through the client class constructor. 
2). Setter - Injector method injects the dependency to the setter method exposed by the client.
3). Interface -Injector uses Interface to provide the dependency to the client class. The client must implement the interface that will expose a setter method which will accept a dependency.

Example of Dependency Injection
1). Let's create a 'Spring Starter Project' with a name 'DependencyInjectionDemo' using Spring STS. Add 'web' dependencies of Spring Web and Spring Web Services. Create a maven or a gradle project, here I have selected Maven because of which pom.xml will be added in the project. This pom.xml will contain all the metadata for the project. All the dependencies are mentioned in pom.xml.
2). Once the project is created, you can see DependencyInjectionDemoApplication.java file present in com.example.demo package. This class will have @SpringBootApplication annotation, this indicates that whenever we execute this particular project it will automatically this particular class will be executed.
3). Lets create a Student class inside com.example.demo package, add studentId and studentName and generate getters and setters. Override toString method and a display method, which will just print a statement. Also we need to add @Component annotation so that bean can be created by Dependency Injection.
package com.example.demo;
import org.springframework.stereotype.Component;

@Component
public class Student {
private int studentId;
private String studentName;
@Override
public String toString() {
return "studentId=" + studentId + ", studentName=" + studentName;
}
public void display()
{
System.out.println("Customer displaying...");
}
/*Getter and Setters*/
}

If we do not mention @Component, and try to create a bean via DI then we will get an error message "No qualifying bean of type 'com.example.demo.Student' available.
4). Now let's say we want to create an object of Student class, but we do not want to create it manually. In this case we need to use Dependency Injection. For this we will modify our DependencyInjectionDemoApplication class.
package com.example.demo;

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

@SpringBootApplication
public class DependencyInjectionDemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context= SpringApplication.run(DependencyInjectionDemoApplication.class, args);
Student student=context.getBean(Student.class);
student.display();
}
}
5). Now if you run DependencyInjectionDemoApplication, by default our application will run on 8080 port. Let's say this port is busy. To change the port number we need to configure it in a properties file. In the resources folder, you will see application.properties. Add the below line in the property file, this will change the port to 8081.
server.port=8081
6). When we execute DependencyInjectionDemoApplication, object of Student will be created and display method will be called. This is print "Customer displaying..." in the console.
7). Now let's extend this example and create another class Address. Our Student class will have a Address object. Let's see how we can do it with the help of Dependency Injection.
package com.example.demo;

import org.springframework.stereotype.Component;

@Component
public class Address {
public int houseNo;
public String address;
public void addressDisplay()
{
System.out.println("Displaying the address..");
}
/*Getter and Setters*/
}
8). Now we will modify our student class. Inside the display() method of Student class, we will call addressDisplay() method of Address class.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Student {
private int studentId;
private String studentName;
@Autowired
private Address address;
public void display()
{
System.out.println("Customer displaying...");
address.addressDisplay();
}
/*Getter and Setters*/
}
If we do not mention @Autowired annotation with the address variable, we will get a Null Pointer Exception at the run time. Our Student class is dependent on Address class, but it doesn't know the existence of Address class, that's why we need to use @Autowired annotation is used so that a class can recognize the Service class and make sure the dependencies are satisfied.
9). When we execute DependencyInjectionDemoApplication, object of Student will be created and display method will be called. This is print "Customer displaying...Displaying the address.." in the console.

Example to create a web application using Spring Boot:
1). To do this we need to first get the answers of three questions: What will be the request URL? What will it return? What is the controller.
2). Let's create a 'Spring Starter Project' with a name 'SpringWebAppDemo' using Spring STS. Add 'web' dependencies of Spring Web and Spring Web Services. Create a maven or a gradle project, here I have selected Maven because of which pom.xml will be added in the project. This pom.xml will contain all the metadata for the project. All the dependencies are mentioned in pom.xml.
3). Once the project is created, you can see SpringWebAppDemoApplication.java file present in com.example.demo package. This class will have @SpringBootApplication annotation, this indicates that whenever we execute this particular project it will automatically this particular class will be executed.
package com.example.demo;

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

@SpringBootApplication
public class SpringWebAppDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringWebAppDemoApplication.class, args);
}
}
4). Now we need to create a JSP. If the JSP option is not available in your eclipse/STS, then goto help- >  eclipse marketplace, and search for 'Eclipse Java EE Developer Tools'. Once you install and restart STS, JSP option will be available. Let's create a new folder WebApp inside src/main, and inside this folder we will create Courses.jsp.
 < %@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"% > 
 < !DOCTYPE html > 
 < html > 
 < head > 
 < meta charset="ISO-8859-1" > 
 < title > Scrutiny Courses < /title > 
 < /head > 
 < body > 
< b > Available courses are: < /b > 
1. Spring Boot.
2. Kafka.
3. Cassendra
4. Hibernate
 < /body > 
 < /html > 
5). We need to add jasper dependency in our pom.xml, so that server can convert JSP file into a servlet. If we do not add this, we will get an error at the run time. In my case the tomcat version is 9.0.27, so I have added the dependency accordingly.
 < dependency > 
     < groupId > org.apache.tomcat < /groupId > 
     < artifactId > tomcat-jasper < /artifactId > 
     < version > 9.0.27 < /version > 
 < /dependency > 
6). Now lets create a controller with a CoursesController inside com.example.demo. We will add a service with a courses inside this controller, which will return Courses.jsp.
package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class CoursesController {
@RequestMapping("/courses")
public String courses() {
System.out.println("Welcome to courses...");
return "Courses.jsp";
}
}
7). If you run SpringWebAppDemoApplication, by default our application will run on 8080 port. Let's say this port is busy. To change the port number we need to configure it in a properties file. In the resources folder, you will see application.properties. Add the below line in the property file, this will change the port to 8081.
server.port=8081
8). Now if we run SpringWebAppDemoApplication, and then open http://localhost:8081/courses in the browser, it will show Courses.jsp.
9). If you @ResponseBody in our courses() service. and hit the webservice, it will not return the JSP instead it will show 'Courses.jsp' on the browser. Use @ResponseBody only if you want to return the data.

Now lets say, instead of returning 'Courses.jsp' from courses() service, we just want to return 'Courses' (without .jsp). In that case we need to make a little changes in our code.
1). We need to create a new folder inside src/main/WebApp/pages and move our Courses.jsp inside this page. This we need to add below lines in our application.properties file:
spring.mvc.view.prefix=/pages/
spring.mvc.view.suffix=.jsp
2). Now we need to modify our courses service. Instead of returning "Courses.jsp" we will now just return "Courses".
package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class CoursesController {
@RequestMapping("courses")
public String courses() {
System.out.println("Welcome to courses...");
return "Courses";
}
}
3). Now if we run SpringWebAppDemoApplication, and then open http://localhost:8081/courses in the browser, it will show Courses.jsp.

What is JavaConfig?
Spring JavaConfig is a product of the Spring community that provides a pure-Java approach to configuring the Spring IoC Container. It thus helps avoid using XML configurations.
The advantages of JavaConfig:
  • Object-oriented configuration: Because configurations are defined as classes in JavaConfig, users can take full advantage of object-oriented features in Java. One configuration class may subclass another, overriding its @Bean methods, etc.
  • Reduced or eliminated XML configuration: The benefits of externalized configuration based on the principles of dependency injection have been proven. However, many developers would prefer not to switch back and forth between XML and Java. JavaConfig provides developers with a pure-Java approach to configuring the Spring container that is conceptually similar to XML configuration. It is technically possible to configure the container using only JavaConfig configuration classes, however in practice many have found it ideal to mix-and-match JavaConfig with XML.
  • Type-safe and refactoring-friendly: JavaConfig provides a type-safe approach to configuring the Spring container. With generics, it is now possible to retrieve beans by type rather than by name, free of any casting or string-based lookups.
How to reload the changes on Spring Boot without having to restart server?
This can be achieved using Developer tools (Dev Tools). Once this dependency is configured, whenever any changes is made in the code, the embedded tomcat will restart. Thus, the dev tools, helps to improve the productivity of developers.

Dev tool will eliminates the need for manually deploying the changes every time. Spring Boot doesn’t have this feature when it has released it’s first version.
< dependency >
< groupId >org.springframework.boot< /groupId >
< artifactId >spring-boot-devtools< /artifactId >
< optional >true< /optional >
< /dependency >


What is Actuator in Spring Boot?
  • Actuator is one of the key feature in Spring Boot framework. 
  • It helps us to access the current state of the running application in production environment. There are several metrics that has to be checked and monitored in the production environment. Even some external applications may be using those services to trigger the alert message to concerned person. Actuator module exposes set of REST endpoints that can be directly accessed as a HTTP URL to check the status.
  • It provides several endpointsto retrieve this kind of information over the web.
  • It also provides a lot of insight and metrics about application health e.g. CPU and memory usage, number of threads etc.
  • It's important to secure your Spring Actuator endpoints because it exposes a lot of confidential information and a potentially dangerous one-two. e.g with /shutdown endpoint anyone can kill your Spring Boot application. FYI, Shutdown is an endpoint that allows the application to be gracefully shutdown. This feature is not enabled by default. We can enable this by using management.endpoint.shutdown.enabled=true in our application.properties file.
  • We can use Spring Security to secure Spring Actuator endpoints).
How to disable Actuator endpoint security in Spring Boot?
By default all sensitive HTTP endpoints are secured such that only users that have an ACTUATOR role may access them. Security is enforced using the standard HttpServletRequest.isUserInRole method. We can disable security by using:
management.security.enabled=false

It is suggested to disable security only if the actuator endpoints are accessed behind firewall.

How to enable/disable the Actuator?
To enable features to add the dependency (Maven/Gradle) to the spring-boot-starter-actuator, i.e. Starter. If you don't want the actuator to be enabled, then don't add the dependency.

 < dependencies > 
 < dependency > 
 < groupId > org.springframework.boot < /groupId > 
 < artifactId > spring-boot-starter-actuator < /artifactId > 
 < /dependency > 
 < /dependencies > 

How to run Spring boot application to custom port?
We can specify the port in application.properties. e.g:
server.port=8090

What is the difference between an embedded container and a WAR?
We can run Spring Boot application as a JAR from the command prompt without setting up a web server. But to run a WAR file, we need to first set up a web server like Tomcat which has Servlet container and then we need to deploy WAR there.

What embedded containers does Spring Boot support?
Tomcat, Jetty, and Undertow. By default, Tomcat is used as an embedded containers but we can change it to Jetty or Undertow.

What is YAML?
YAML is a human-readable data serialization language. It is commonly used for configuration files. Compared to properties file, YAML file is much more structured and less confusing in case we want to add complex properties in the configuration file.

How to implement security for Spring boot application?
spring-boot-starter-security dependency is used to implement security in Spring Boot. This requires very little code. The config class will have to extend WebSecurityConfigurerAdapter and override its methods.

If you are using Maven, then add below dependency in pom.xml:
 < dependency >
 < groupId > org.springframework.boot < /groupId >
 < artifactId > spring-boot-starter-security < /artifactId >
 < scope > test < /scope >
 < /dependency >


By adding the spring boot security starter dependency the basic security has already been configured by default. We can further customize the security configuration by writing our own authorization and authentication.

Let's create a new class SecurityConfig that extends the WebSecurityConfigurerAdapter and overrides its methods.

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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("adminUser")
                .password("adminPass").roles("USER");
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**").authorizeRequests().anyRequest().hasRole("USER")
                .and().formLogin().loginPage("/login.jsp")
                .failureUrl("/login.jsp?error=1").loginProcessingUrl("/login")
                .permitAll().and().logout()
                .logoutSuccessUrl("/welcome.html");

    }
}


Add a new page named login.jsp. Users will get redirected to this page for adding credentials.

Whenever user tries to open http://localhost:8080/welcome.html, the control will be automatically redirected to http://localhost:8080/login.jsp. When the user enters correct credentials, they will be able to visit all the other URLs correctly.

How to convert a simple Maven project into Spring Boot project?
We need to add 'spring-boot-starter-parent' in pom.xml. e.g:
< 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 > khs.springboot< /groupId >
    < artifactId > spring-api< /artifactId >
    < version > 0.0.1-SNAPSHOT< /version >
    < name > Spring Boot API< /name >

    < parent >
        < groupId > org.springframework.boot< /groupId >
        < artifactId > spring-boot-starter-parent< /artifactId >
        < version > 1.5.10.RELEASE< /version >
        < relativePath / >
    < /parent >

< /project > 

Adding below dependency, will add all the web related jars in your project:
 < dependency >
     < groupId > org.springframework.boot < /groupId >
     < artifactId > spring-boot-starter-web < /artifactId >
 < /dependency >  


To specify the Java version:
 < properties >
     < java.version > 1.8 < /java.version >
 < /properties >  < properties >
     < java.version > 1.8 < /java.version >
 < /properties > 


What is the use of @SpringBootApplication annotation in spring boot?
Earlier we need to annotate our Application class or Main class with quite a lot of annotations to start with e.g.
1). @Configuration to enable Java-based configuration,
2). @ComponentScan to enable component scanning,
3). @EnableAutoConfiguration to enable Spring Boot's auto-configuration feature, by adding beans based on class path settings, other beans, and various property settings.

but now you can do all that by just annotating your Application class with @SpringBootApplication, which is available from Spring 1.2 onwards.

We can say, the @SpringBootApplication annotation is equivalent to using @Configuration, @EnableAutoConfiguration and @ComponentScan with their default attribute.

@SpringBootApplication also marks the class as a BootStrap class which means you can run it as a normal Java class.

What are the parameters accepted in the @SpringBootApplication annotation?
excludeNames: Exclude the list of fully qualified class names from the auto configuration. This parameter added since spring boot 1.3.0.
scanBasePackageClasses: Provide the list of classes that has to be applied for the @ComponentScan.
scanBasePackages: Provide the list of packages that has to be applied for the @ComponentScan. This parameter added since spring boot 1.3.0.

What is Auto Configuration in Spring boot?

  • Spring boot auto configuration scans the classpath, finds the libraries in the classpath and then attempt to guess the best configuration for them, and finally configure all such beans.
  • It is always applied after user-defined beans have been registered.
  • It makes development easier and faster.

We can create a custom configuration for a MySQL data source in spring boot as
@Configuration 
public class MySQLAutoconfiguration {
    //.....
}

Auto-configuration works with help of @Conditional annotations such as @ConditionalOnBean and @ConditionalOnClass. e.g:

If class path scanning finds EnableAspectJAutoProxy, Aspect, Advice and AnnotatedElement classes and spring.aop.auto=false is not present in properties file then Spring boot will configure the Spring AOP module for us.

@Configuration
@ConditionalOnClass({ EnableAspectJAutoProxy.class, 
            Aspect.class, 
            Advice.class, 
            AnnotatedElement.class })

@ConditionalOnProperty(prefix = "spring.aop", 
            name = "auto", 
            havingValue = "true", 
            matchIfMissing = true)
public class MySQLAutoconfiguration {
    //.....
}

How to exclude any package without using the basePackages filter?
Spring Boot provides a trickier option for achieving this without touching the component scan. We can use the exclude attribute while using the annotation @SpringBootApplication.

@SpringBootApplication(exclude= {User.class})
public class FooAppConfiguration {}

How to run spring boot as a standalone application?
SpringApplication.run(YourMain.class, args);
  • This sets up default configuration.
  • Starts Spring application context.
  • Performs class path scan.
  • Start inbuild Tomcat server.

How to add a REST Controller in Spring Boot application?
A Controller is a Java class, which is marked with annotations. It contais the menthod, which will be called whenever user access the configured URL's.

@RestController, which is a stereotype annotation can be used with anyclass to make it a REST controller. The @RestController annotation informs to the Spring to render the result back to the caller.

What is the difference between spring @Controller and @RestController annotations in Spring Boot?
In Spring framework, a Controller is a class which is responsible for preparing a model Map with data to be displayed by the view as well as choosing the right view itself.

This Controller class can also directly write into response stream by using @ResponseBody annotation and complete the request. The behavior of writing directly into response stream is very useful for responding calls to RESTful web services, because their we just return data instead of returning a view.

Let us take an exmple to understand the difference between @Controller and @RestController annotations:

1).
@Controller
public class MyRESTClass{

  @RequestMapping(value={"/url"})
  @ResponseBody
  public ObjectResponse restFunction(){
      //...
      return instance
   }
}


2).
@RestController
public class MyRESTClass{

  @RequestMapping(value={"/url"})
  public ObjectResponse restFunction(){
      //...
      return instance
   }
}


When you use @RestController the @ResponseBody is activates by default, we don't need to add it explicitly. We can say, @RestController is composition of @Controller and @ResponseBody.

@RestController was added into Spring 4.0, which made the development of RESTful Web Services in Spring framework a bit easier, where as @Controller is an old annotation, exists since Spring started supporting annotation, officially it was added on Spring 2.5 version.

The job of @Controller is to create a Map of model object and find a view, but @RestController simply return the object and object data is directly written into HTTP response as JSON or XML.

The @Controller annotation indicates that the class is a "Controller" e.g. a web controller while @RestController annotation indicates that the class is a controller where @RequestMapping methods assume @ResponseBody semantics by default i.e. servicing REST API.

Once you mark a class @RestController then every method is written a domain object instead of a view.

What is the user of @RequestMapping annotation?
The @RequestMapping annotation is used to provide routing information. It tells to the Spring that any HTTP request should map to the corresponding method. We need to import org.springframework.web.annotation package in our file. e.g:
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
   
    @RequestMapping("/greet")
    public String greet()
    {
        return "Hello! User";
    }
}


Open 'http://localhost:8080/greet' in the browser, it will display "Hello! User".

What is the difference between @GetMapping and @RequestMapping(method = RequestMethod.GET) in Spring Boot?

  • Both @GetMapping and @RequestMapping are annotations for mapping HTTP GET requests onto specific handler methods in Spring boot. 
  • @GetMapping is the newer annotation, which was introduced in Spring 4.3
  • Typical way to implement the URL handler using traditional @RequestMapping annotation: @RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
  • The new approach makes it possible to shorten this simply to: @GetMapping("/get/{id}")
  • Spring currently supports five types of inbuilt annotations for handling different types of incoming HTTP request methods which are GET, POST, PUT, DELETE and PATCH. These annotations are: @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping

How can we return Objects from a Controller?
Let us take an example to understand this. Supposse we are creating a REST web-service which returns list of all employees, instead of return a 'String', we will return  List < Employee > .

1). Create a POJO class:
public class Employee {
    private int employeeId;
    private String employeeName;
   
    public Employee()
    {
        super();
    }
    public Employee(int employeeId, String employeeName) {
        super();
        this.employeeId = employeeId;
        this.employeeName = employeeName;
    }
   
    //getters and setters
}


2). Create a EmployeeController, which has method getAllEmployees(). This method returns list of all the employees.

@RestController
public class EmployeeController {

    @RequestMapping("/getAllEmployees")
    public List < Employee >  getAllEmployees()
    {
        List < Employee >  employees=new ArrayList < Employee > ();
        employees.add(new Employee(001, "Lissey Barnett"));   
        employees.add(new Employee(002, "Himaanshu Shuklaa"));
        employees.add(new Employee(003, "Robert D'mello"));   
        return employees;
    }
}


Now, when you open http://localhost:8080/getAllEmployees in the browser, it will return below JSON:
[{"employeeId":1,"employeeName":"Lissey Barnett"},{"employeeId":2,"employeeName":"Himaanshu Shuklaa"},{"employeeId":3,"employeeName":"Robert D'mello"}]
The Spring Boot, has automatically converted List < Employee >  into a JSON String. The generated JSON has key names corresponding to the property names of the Employee class and values are the values of those properties.

What is the significance of @Service annotation?
It is used to create a business service. In Spring, business service is typically Singleton. When the application starts up, Spring container creates instance of the business service and keeps the instance in memory, so that others can use it.

To declare a particular class as a business service, we need to use a Strerotype annotation @Service.

1). Create a Pojo class:
public class Company {
    private int companyId;
    private String companyName;
   
    public Company()
    {
        super();
    }
    public Company(int companyId, String companyName) {
        super();
        this.companyId = companyId;
        this.companyName = companyName;
    }
   
    //getters and setters
}
2). Now we will create a service class:
import org.springframework.stereotype.Service;

@Service
public class CompanyService {
    private List companies=Arrays.asList(
    new Company(784, "Google"),
    new Company(785, "Microsoft"),
    new Company(786, "KHS Pvt. Ltd."));   
   
    public List getAllCompanies()
    {
        return companies;
    }
}

3). To use the business service, we need to declare a private variable of this class in our controller with @Autowired annotation. e.g:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
public class ServiceController {
    @Autowired
    private CompanyService companyService;
   
    @RequestMapping("/getAllCompanies")
    public List getAllCompanies()
    {
        return companyService.getAllCompanies();
    }
}

Now, when you hit http://localhost:8080/getAllCompanies from browser, it will show list of all the companies:
[{"companyId":784,"companyName":"Google"},{"companyId":785,"companyName":"Microsoft"},{"companyId":786,"companyName":"KHS Pvt. Ltd."}]

What is the use of @RequestParam and @PathVariable in Spring Boot?
Both @RequestParam and @PathVariable annotations are used for accessing the values from the request. The key difference between @RequestParam and @PathVariable is that, @RequestParam used for accessing the values of the query parameters, where as @PathVariable used for accessing the values from the URI template.

Suppose you want to get a single company, then first you need to define a method to get the company details from id in CompanyService class.

public Company getCompanyById(int id)
{
    return companies.stream().filter(company->company.getCompanyId()==id).findFirst().get();
}

Inside the ServiceController, let's define two methods.

@RequestMapping("/getAllCompanies/{id}")
public Company getCompanyById(@PathVariable int id)
{       
    return companyService.getCompanyById(id);
}
   
@RequestMapping("/getAllCompaniesFromId/{compId}")
public Company getCompanyFromId(@PathVariable("compId") int id)
{       
    return companyService.getCompanyById(id);
}

Now when you hit http://localhost:8080/getAllCompanies/786, it will print
{"companyId":786,"companyName":"KHS Pvt. Ltd."}

And when you hit http://localhost:8080/getAllCompaniesFromId/786, it will print
{"companyId":784,"companyName":"Google"}


What is the use of @RequestBody and @ResponseBody annotations in SpringBoot?
@RequestBody annotation maps the HttpRequest body to a transfer or domain object, enabling automatic deserialization of the inbound HttpRequest body onto a Java object.

Spring automatically deserializes the JSON into a Java type assuming an appropriate one is specified. By default, the type we annotate with the @RequestBody annotation must correspond to the JSON sent from our client-side controller.

@ResponseBody annotation tells a controller that the object returned is automatically serialized into JSON and passed back into the HttpResponse object.

How can you create a new resource using POST in Spring Boot?
Let's say, we want add a new company. For this first we need to add a addCompany() method in CompanyService.
public void addCompany(Company company)
{
    companies.add(company);
}

Now define a method in ServiceController. Since we want to use POST, we need define method in @RequestMapping.
@RequestMapping(method=RequestMethod.POST, value="/getAllCompanies")
public void addCompany(@RequestBody Company company)
{
    companyService.addCompany(company);
}

Now, when you call http://localhost:8080/getAllCompanies/ from POSt method, by passing below input, it will add a company:
{"companyId":787,"companyName":"Funny Zone Limited"}

To verify whether, the 'Funny Zone Limited' is added in the list or not, hit http://localhost:8080/getAllCompanies/,
[{"companyId":784,"companyName":"Google"},{"companyId":785,"companyName":"Microsoft"},{"companyId":786,"companyName":"KHS Pvt. Ltd."},{"companyId":787,"companyName":"Funny Zone Limited"}]

How can we implement Update in Spring Boot?
Add a updateCompany() method in CompanyService class.
public void updateCompany(int id, Company company)
{
    for (int i=0; i<=companies.size(); i++)
    {
        Company existingCompany=companies.get(i);
        if(existingCompany.getCompanyId()==id)
        {
            companies.set(i, company);
            return;
        }
    }
}

Now add a method inside ServiceController class:
@RequestMapping(method=RequestMethod.PUT, value="/getAllCompanies/{id}")
public void updateCompany(@RequestBody Company company, @PathVariable int id)
{
    companyService.updateCompany(id, company);
}

When you call http://localhost:8080/getAllCompanies/784 by PUT method and pass below parameter,it will replace the details of Company with id 784.
{"companyId":784,"companyName":"Scrutiny PR Agency"}

To verify whether, company with id 784 is updated in the list or not, hit http://localhost:8080/getAllCompanies/,
[{"companyId":784,"companyName":"Scrutiny PR Agency"},{"companyId":785,"companyName":"Microsoft"},{"companyId":786,"companyName":"KHS Pvt. Ltd."}]

How can we implement Delete in Spring Boot?
Add deleteCompanyById() method inside CompanyService:
public void deleteCompanyById(int id)
{
    companies.removeIf(company->company.getCompanyId()==id);
}

Now, deleteCompanyById() methid inside ServiceController:
@RequestMapping(method=RequestMethod.DELETE, value="/getAllCompanies/{id}")
public void deleteCompanyById(@PathVariable int id)
{       
    companyService.deleteCompanyById(id);
}

When you call http://localhost:8080/getAllCompanies/ from DELETE method, by passing some id, it will delete the corresponding company from the list.

What are different HTTP methods available?
  • GET: It is used to retrieve information. GET requests must be safe and idempotent, meaning regardless of how many times it repeats with the same parameters, the results are the same. GET requests can also be partial or conditional.
  • POST: It is often used to create a new entity, but it can also be used to update an entity.
  • PUT: It is used to store an entity at a URI. PUT can create a new entity or update an existing one. A PUT request is idempotent. Idempotency is the main difference between the expectations of PUT versus a POST request. PUT replaces an existing entity. If only a subset of data elements are provided, the rest will be replaced with empty or null.
  • PATCH: It only update the specified fields of an entity at a URI. A PATCH request is neither safe nor idempotent. That's because a PATCH operation cannot ensure the entire resource has been updated.
  • DELETE: This request is used when the resource need to be removed; however, the resource does not have to be removed immediately. It could be an asynchronous or long-running request.
What is the difference between the HTTP put and post methods?
  • Although both PUT and POST methods can be used to perform create and update operation in REST WebServices, the main difference between these two HTTP method is Idempotency. Like GET,  PUT request is also idempotent in HTTP, which means it will produce the same results if executed once more multiple times. If you execute POST request multiple times, it will end up create that many orders, but when you execute PUT it will always produce the same result because of its idempotent.
  • In the context of REST WebService, POST is often used to create a new entity, where as PUT is often used to update an existing entity.
How to change Tomcat port in Spring Boot?
In Spring Boot, by default the embedded Tomcat runs on 8080. We can change it by adding server.port in the application.properties file.

/src/main/resources/application.properties add below line, it will set HTTP port to 8888:
server.port=8888

How can we connect to an external database like MSSQL or oracle with Spring boot?

  1. First we need to add the dependency for database connector in pom.xml.
  2. Then we need to remove (if added) the H2 Dependency from pom.xml
  3. Includes the schema and table to establish your database.
  4. Add DB configuration in application.properties to connect to the database.
  5. Restart the application.

Example of Dependency Injection
1). Let's create a 'Spring Starter Project' with a name 'DependencyInjectionDemo' using Spring STS. Add 'web' dependencies of Spring Web and Spring Web Services. Create a maven or a gradle project, here I have selected Maven because of which pom.xml will be added in the project. This pom.xml will contain all the metadata for the project. All the dependencies are mentioned in pom.xml.
2). Once the project is created, you can see DependencyInjectionDemoApplication.java file present in com.example.demo package. This class will have @SpringBootApplication annotation, this indicates that whenever we execute this particular project it will automatically this particular class will be executed.
3). Lets create a Student class inside com.example.demo package, add studentId and studentName and generate getters and setters. Override toString method and a display method, which will just print a statement. Also we need to add @Component annotation so that bean can be created by Dependency Injection.

package com.example.demo;
import org.springframework.stereotype.Component;

@Component
public class Student {
private int studentId;
private String studentName;

@Override
public String toString() {
return "studentId=" + studentId + ", studentName=" + studentName;
}
public void display()
{
System.out.println("Customer displaying...");
}
/*Getter and Setters*/
}

If we do not mention @Component, and try to create a bean via DI then we will get an error message "No qualifying bean of type 'com.example.demo.Student' available.
4). Now let's say we want to create an object of Student class, but we do not want to create it manually. In this case we need to use Dependency Injection. For this we will modify our DependencyInjectionDemoApplication class.

package com.example.demo;

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

@SpringBootApplication
public class DependencyInjectionDemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context= SpringApplication.run(DependencyInjectionDemoApplication.class, args);
Student student=context.getBean(Student.class);
student.display();
}
}

5). Now if you run DependencyInjectionDemoApplication, by default our application will run on 8080 port. Let's say this port is busy. To change the port number we need to configure it in a properties file. In the resources folder, you will see application.properties. Add the below line in the property file, this will change the port to 8081.
6). When we execute DependencyInjectionDemoApplication, object of Student will be created and display method will be called. This is print "Customer displaying..." in the console.
7). Now let's extend this example and create another class Address. Our Student class will have a Address object. Let's see how we can do it with the help of Dependency Injection.

package com.example.demo;

import org.springframework.stereotype.Component;

@Component
public class Address {
public int houseNo;
public String address;

public void addressDisplay()
{
System.out.println("Displaying the address..");
}
/*Getter and Setters*/
}
8). Now we will modify our student class. Inside the display() method of Student class, we will call addressDisplay() method of Address class.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class Student {
private int studentId;
private String studentName;
@Autowired
private Address address;

public void display()
{
System.out.println("Customer displaying...");
address.addressDisplay();
}
/*Getter and Setters*/
}
If we do not mention @Autowired annotation with the address variable, we will get a Null Pointer Exception at the run time. Our Student class is dependent on Address class, but it doesn't know the existence of Address class, that's why we need to use @Autowired annotation is used so that a class can recognize the Service class and make sure the dependencies are satisfied.
9). When we execute DependencyInjectionDemoApplication, object of Student will be created and display method will be called. This is print "Customer displaying...Displaying the address.." in the console.

Example to create a web application using Spring Boot:
1). To do this we need to first get the answers of three questions: What will be the request URL? What will it return? What is the controller.
2). Let's create a 'Spring Starter Project' with a name 'SpringWebAppDemo' using Spring STS. Add 'web' dependencies of Spring Web and Spring Web Services. Create a maven or a gradle project, here I have selected Maven because of which pom.xml will be added in the project. This pom.xml will contain all the metadata for the project. All the dependencies are mentioned in pom.xml.
3). Once the project is created, you can see SpringWebAppDemoApplication.java file present in com.example.demo package. This class will have @SpringBootApplication annotation, this indicates that whenever we execute this particular project it will automatically this particular class will be executed.

package com.example.demo;

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

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

4). Now we need to create a JSP. If the JSP option is not available in your eclipse/STS, then goto help- >  eclipse marketplace, and search for 'Eclipse Java EE Developer Tools'. Once you install and restart STS, JSP option will be available. Let's create a new folder WebApp inside src/main, and inside this folder we will create Courses.jsp.

 < %@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"% > 
 < !DOCTYPE html > 
 < html > 
 < head > 
 < meta charset="ISO-8859-1" > 
 < title > Scrutiny Courses < /title > 
 < /head > 
 < body > 
< b > Available courses are: < /b > 
1. Spring Boot.
2. Kafka.
3. Cassendra
4. Hibernate
 < /body > 
 < /html > 

5). We need to add jasper dependency in our pom.xml, so that server can convert JSP file into a servlet. If we do not add this, we will get an error at the run time. In my case the tomcat version is 9.0.27, so I have added the dependency accordingly.

 < dependency > 
     < groupId > org.apache.tomcat < /groupId > 
     < artifactId > tomcat-jasper < /artifactId > 
     < version > 9.0.27 < /version > 
 < /dependency > 

6). Now lets create a controller with a CoursesController inside com.example.demo. We will add a service with a courses inside this controller, which will return Courses.jsp.

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class CoursesController {
@RequestMapping("/courses")
public String courses() {
System.out.println("Welcome to courses...");
return "Courses.jsp";
}
}

7). If you run SpringWebAppDemoApplication, by default our application will run on 8080 port. Let's say this port is busy. To change the port number we need to configure it in a properties file. In the resources folder, you will see application.properties. Add the below line in the property file, this will change the port to 8081.
server.port=8081
8). Now if we run SpringWebAppDemoApplication, and then open http://localhost:8081/courses in the browser, it will show Courses.jsp.
9). If you @ResponseBody in our courses() service. and hit the webservice, it will not return the JSP instead it will show 'Courses.jsp' on the browser. Use @ResponseBody only if you want to return the data.

Now lets say, instead of returning 'Courses.jsp' from courses() service, we just want to return 'Courses' (without .jsp). In that case we need to make a little changes in our code.
1). We need to create a new folder inside src/main/WebApp/pages and move our Courses.jsp inside this page. This we need to add below lines in our application.properties file:
spring.mvc.view.prefix=/pages/
spring.mvc.view.suffix=.jsp
2). Now we need to modify our courses service. Instead of returning "Courses.jsp" we will now just return "Courses".

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class CoursesController {
@RequestMapping("courses")
public String courses() {
System.out.println("Welcome to courses...");
return "Courses";
}
}

3). Now if we run SpringWebAppDemoApplication, and then open http://localhost:8081/courses in the browser, it will show Courses.jsp.

Create a submission form in Spring Boot

1). Let's create a 'Spring Starter Project' with a name 'SubmissionForm' using Spring STS. Add 'web' dependencies of Spring Web and Spring Web Services. Create a maven or a gradle project, here I have selected Maven because of which pom.xml will be added in the project. This pom.xml will contain all the metadata for the project. We will add dependencies for Spring Web, Spring Web Services, H2 Database, Jersey and Spring Data JPA
2). Once the project is created, you can see SubmissionFormApplication.java file present in com.example.demo package. This class will have @SpringBootApplication annotation, this indicates that whenever we execute this particular project it will automatically this particular class will be executed.
3). Inside the main folder, we will create another folder with a name webapp, inside it create another folder pages and then inside this folder we will create addcustomers.jsp. From this JSP we can add our customers.

 < %@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"% > 
 < !DOCTYPE html > 
 < html > 
 < head > 
 < meta charset="ISO-8859-1" > 
 < title > Customers < /title > 
 < /head > 
 < body > 

 < form method="post" action="addCustomers" > 
Customer Id:  < input type="text" name="cid" >  < br/ > 
Customer Name:  < input type="text" name="cname" >  < br/ > 
Customer Email Id:  < input type="email" name="cemail" >  < br/ > 

< br/ > 
< input type="submit" value="Submit" > 
 < /form > 
 < /body > 
 < /html > 

4). We will create another JSP viewcustomer.jsp

 < %@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"% > 
 < !DOCTYPE html > 
 < html > 
 < head > 
 < meta charset="ISO-8859-1" > 
 < title > Customer Details < /title > 
 < /head > 
 < body > 
 < h2 > Customer Details < /h2 > 
 < h4 > 
Id: ${cid}  < br/ > 
Name: ${cname}  < br/ > 
Email: ${cemail}  < br/ > 
 < /h4 > 
 < /body > 
 < /html > 

5). Now we will create a Controller with a name FormController.

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class FormController {
@GetMapping("customer")
public String customer() {
return "addcustomers";
}

@PostMapping("addCustomers")
public String addCustomers(@RequestParam("cid") int cid,
@RequestParam("cname") String cname,
@RequestParam("cemail") String cemail,
ModelMap modelMap) {
modelMap.put("cid", cid);
modelMap.put("cname", cname);
modelMap.put("cemail", cemail);
return "viewcustomer";
}
}

6).We need to add jasper dependency in our pom.xml, so that server can convert JSP file into a servlet. If we do not add this, we will get an error at the run time. In my case the tomcat version is 9.0.27, so I have added the dependency accordingly.
  < dependency > 
      < groupId > org.apache.tomcat < /groupId > 
      < artifactId > tomcat-jasper < /artifactId >  
      < version > 9.0.27 < /version > 
  < /dependency > 
7). Add below lines in application.properties
server.port=8081
spring.mvc.view.prefix=/pages/
spring.mvc.view.suffix=.jsp
8). If you open http://localhost:8081/customer in broswer, below page will open. When you submit the details, addCustomers.jsp will be shown

-K Himaanshu Shuklaa

No comments:

Post a Comment