Spring Boot Beginner's Guide

Spring Boot is an open-source framework developed by Pivotal, a part of VMware, and is designed to simplify the setup and development of Spring applications. It provides a variety of features that help streamline the process, including embedded servers, pre-configured templates, and a variety of utilities that make it easier to build stand-alone, production-grade Spring-based applications.

Prerequisites

Before diving into Spring Boot, it's essential to have a basic understanding of the following concepts:

  1. Java Programming: Familiarity with Java is crucial as Spring Boot applications are primarily written in Java.

  2. Maven or Gradle: Understanding of build tools like Maven or Gradle will help in managing dependencies.

  3. Basic Web Development: Knowledge of web development concepts like HTTP, RESTful APIs, and basic front-end technologies (HTML, CSS, JavaScript) is beneficial.

Setting Up Development Environment

  1. Install Java Development Kit (JDK)

    • Download and install the latest JDK from the Oracle or OpenJDK.
  2. Install an Integrated Development Environment (IDE)

    • Popular choices are IntelliJ IDEA, Eclipse, or VSCode. IntelliJ IDEA is highly recommended for its powerful features and Spring Boot support.
  3. Install Maven or Gradle

Creating a Spring Boot Project

Using Spring Initializr

Spring Initializr is a web-based tool to generate Spring Boot projects quickly. You can access it at start.spring.io.

  1. Go to start.spring.io.

  2. Choose your project metadata:

    • Project: Maven Project

    • Language: Java

    • Spring Boot: 2.x.x or latest

    • Group: com.example

    • Artifact: demo

    • Name: demo

  3. Select dependencies:

    • Spring Web
  4. Click "Generate" to download the project as a zip file.

  5. Unzip the file and open it in your IDE.

Creating the Project Structure

The typical structure of a Spring Boot project looks like this:

demo
│
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── example
│   │   │           └── demo
│   │   │               ├── DemoApplication.java
│   │   ├── resources
│   │       ├── application.properties
│   └── test
│       └── java
│           └── com
│               └── example
│                   └── demo
└── pom.xml

Writing Your First Spring Boot Application

Creating a REST Controller

A REST controller handles HTTP requests and returns data in JSON format.

package com.example.demo;

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

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello, Spring Boot!";
    }
}

Explanation:

  • @RestController is a Spring annotation that marks the class as a RESTful web service controller.

  • @GetMapping("/hello") maps HTTP GET requests to the hello() method.

Main Application Class

The main class is the entry point of the Spring Boot application.

package com.example.demo;

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

@SpringBootApplication
public class DemoApplication {

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

Explanation:

  • @SpringBootApplication is a convenience annotation that combines @Configuration, @EnableAutoConfiguration, and @ComponentScan.

  • SpringApplication.run() starts the application.

Running the Application

To run the application, simply execute the main class DemoApplication from your IDE, or use the command line:

mvn spring-boot:run

Or for Gradle:

gradle bootRun

Accessing the Application

Open your web browser and navigate to http://localhost:8080/hello. You should see the message "Hello, Spring Boot!"

Some Key Concepts

What is Spring Boot ?

Spring Boot is an open-source framework developed by Pivotal Team. It simplifies the process of creating stand-alone, production-grade Spring-based applications with minimal effort. It provides a set of tools and conventions to speed up development, reduce boilerplate code, and streamline the configuration of Spring applications.

  • Key Features:

    • Auto-Configuration: Automatically configures your application based on the dependencies you have added to the project.

    • Standalone Applications: You can create a runnable JAR file that contains an embedded server, making it easy to deploy and run anywhere.

    • Spring Initializr: A web-based tool to quickly bootstrap a Spring Boot project with the necessary dependencies.

    • Production-Ready Metrics: Provides tools for monitoring and managing your application.

How Spring Boot works internally ?

Bootstrapping:

  1. Application Class: It all starts with your main application class, typically annotated with @SpringBootApplication. This class kicks off the whole process.

  2. Creating the Application Context: Spring Boot creates the application context, a container that manages all the objects your application needs.

  3. Auto-configuration: This is where the magic happens. Spring Boot scans for dependencies on your classpath and automatically configures beans (components) based on those dependencies. For example, if you include spring-boot-starter-data-jpa, it auto-configures beans for connecting to a database using JPA.

  4. Web Application Type: Spring Boot figures out what type of web application you're building (Servlet-based or reactive) by looking for specific dependencies like spring-boot-starter-web.

Bean Management:

  1. Spring IoC Container: The application context acts as an Inversion of Control (IoC) container. It creates and manages all the beans (objects) your application needs.

  2. Bean Lifecycle: Spring manages the lifecycle of each bean, calling methods like init() and destroy() at appropriate times.

Configuration:

  1. Properties: Spring Boot reads configuration properties from various sources like application.properties and environment variables. These properties can be used to fine-tune the auto-configured beans.

  2. Command-Line Arguments: Spring Boot can also process command-line arguments passed when you start the application.

Starting the Application:

Once everything is configured and ready, Spring Boot starts your application, typically by running a web server or any other functionality you've defined.

What is annotation in java ?

  • Annotations are like tags starting with the @ symbol.

  • They can be attached to various parts of your code like classes, methods, variables, or even packages.

  • They provide additional information that can be processed by different tools.

Common Uses of Annotations:

  • Compiler Checks: Some annotations can be used by the compiler to find errors or warnings in your code. For instance, the @Override annotation indicates you're overriding a method from a parent class.

  • Code Generation: Frameworks like Spring Boot use annotations to automatically configure parts of your application based on the libraries you include.

  • Documentation: Annotations can also be used for documentation purposes, similar to Javadoc comments.

Creating Custom Annotations

Java allows you to define your own annotations to suit your specific needs. Here's the basic structure:

@interface MyCustomAnnotation {
  // Define elements (optional)
  String value() default "";
}
  • The @interface keyword declares it as an annotation.

  • You can define elements within the annotation to hold additional information.

  • In this example, value is an element with a default string value.

Using Custom Annotations

Once you've defined your annotation, you can use it on your code elements:

@MyCustomAnnotation(value = "This is a test annotation")
public class MyClass {
  // ...
}

What is Dependency Injection and Inversion of Control ?

Dependency injection (DI) and inversion of control (IoC) are related concepts in software design that promote loose coupling and testability. Here's a breakdown with a simple example:

Inversion of Control (IoC):

  • Traditional Approach: Imagine a class EmailService that needs to send emails. It might directly create an SMTPSender object to handle sending. This tightly couples EmailService to a specific implementation.

  • IoC Principle: IoC flips this control. Instead of creating its own dependencies (SMTPSender), EmailService relies on an external entity to provide them. This external entity, often a container or framework, "injects" the dependencies.

Dependency Injection (DI):

  • DI in Action: DI is a technique that implements IoC. In our example, the EmailService class wouldn't create the SMTPSender itself. Instead, it would either:

    • Have a constructor that takes an SMTPSender argument:

        public class EmailService {
            private final SMTPSender smtpSender;
      
            public EmailService(SMTPSender smtpSender) {
                this.smtpSender = smtpSender;
            }
      
            public void sendEmail(String message) {
                // Use smtpSender to send the email
            }
        }
      
    • Have a setter method to inject the SMTPSender:

        public class EmailService {
            private SMTPSender smtpSender;
      
            public void setSMTPSender(SMTPSender smtpSender) {
                this.smtpSender = smtpSender;
            }
      
            public void sendEmail(String message) {
                // Use smtpSender to send the email
            }
        }
      
  • Benefits of DI:

    • Loose Coupling: Classes depend on interfaces or abstractions (like SMTPSender) instead of concrete implementations. This makes them more flexible and easier to test.

    • Testability: You can easily inject mock objects for dependencies during testing, isolating the class being tested.

Simple Analogy:

Think of IoC and DI like preparing a meal. Traditionally, you might chop all the vegetables yourself (tight coupling). With IoC, someone else prepares the ingredients (dependencies) you need, giving you more control over the recipe (your class).

How RestController works ?

Spring RestController is a powerful annotation used to build RESTful APIs in Spring applications. Here's a breakdown of its functionalities with code examples:

1. Request Handling:

  • A @RestController class handles incoming HTTP requests and returns responses.

  • It combines the functionalities of @Controller (for handling requests) and @ResponseBody (for treating response as response body).

2. Request Mapping:

  • The @RequestMapping annotation maps specific HTTP request methods (GET, POST, etc.) to handler methods within the controller class.

3. Path Variables:

  • Path variables allow capturing dynamic parts of the request URL.

  • You define them within the @RequestMapping path using curly braces {} and access them as method arguments.

Example:

@RestController
@RequestMapping("/api/users")
public class UserController {

  @GetMapping("/{id}")
  public User getUserById(@PathVariable Long id) {
    // Fetch user from database based on id
    return user;
  }
}

4. Request Parameters:

  • Request parameters are key-value pairs sent in the URL query string.

  • You can access them using the @RequestParam annotation on method arguments.

Example:

@GetMapping("/search")
public List<User> searchUsers(@RequestParam(name = "name", required = false) String name) {
  // Search users based on name parameter
  return users;
}

5. Request Body:

  • The request body contains data sent along with the request (usually in POST or PUT methods).

  • You can access the request body using the @RequestBody annotation on a method argument. Spring automatically converts it to a Java object based on the content type (often JSON).

Example:

@PostMapping("/users")
public User createUser(@RequestBody User user) {
  // Save user object to database
  return savedUser;
}

6. ResponseEntity:

  • The ResponseEntity class provides a comprehensive way to return responses from controller methods.

  • It allows you to specify the HTTP status code, response headers, and the actual response body.

Example:

@GetMapping("/users/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
  User user = getUserFromDatabase(id);
  if (user == null) {
    return ResponseEntity.notFound().build(); // Return 404 Not Found
  }
  return ResponseEntity.ok(user); // Return 200 OK with user object
}

7. Available Request Method Annotations:

Spring provides annotations for various HTTP request methods:

  • @GetMapping: Maps GET requests.

  • @PostMapping: Maps POST requests.

  • @PutMapping: Maps PUT requests for updating resources.

  • @DeleteMapping: Maps DELETE requests for deleting resources.

  • @PatchMapping: Maps PATCH requests for partial updates.

How to connect database ?

1. Dependencies:

  • Add the necessary dependencies to your pom.xml file. Include:

    • spring-boot-starter-data-jpa: Provides JPA data access functionalities.

    • mysql-connector-java: The MySQL JDBC driver for connecting to the database.

2. Database Configuration:

  • Configure your database connection details in application.properties (or yml):

Properties

spring.datasource.url=jdbc:mysql://localhost:3306/your_database_name
spring.datasource.username=your_username
spring.datasource.password=your_password
  • Replace the placeholders with your actual database details (URL, username, password).

3. JPA Entity:

  • Create a model class representing your database table.

  • Annotate it with @Entity to indicate it maps to a database table.

  • Define member variables with appropriate annotations like @Id for the primary key.

Example:

@Entity
public class User {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;
  private String name;
  private String email;
  // Getters and setters
}

4. JPA Repository:

  • Create a repository interface extending JpaRepository from spring-data-jpa.

  • This interface provides CRUD (Create, Read, Update, Delete) operations for your entity class.

Example:

public interface UserRepository extends JpaRepository<User, Long> {
  // You can add custom finder methods here
}

5. Using the Repository:

  • Inject the repository into your service or controller class using dependency injection.

  • Use the repository methods to interact with your database (save, find, update, delete).

Example (Controller):

@RestController
@RequestMapping("/users")
public class UserController {

  @Autowired
  private UserRepository userRepository;

  @GetMapping("/{id}")
  public User getUserById(@PathVariable Long id) {
    return userRepository.findById(id).get();
  }
}