Spring Boot for Dummies: Part 1.2 [The Basics]

Yash Patel
10 min readNov 23, 2023

--

In this part we will look at Dev Tools, Lombok, Swagger, Custom Banners, Spring IOC and Spring Actuators. So, let’s get started. If you have not read Part1.1, please go ahead and read that.

# Bootstrapping Development (Spring-Boot dev tools + Lombok + Swagger)

Spring-Boot dev tools

Spring Boot Dev Tools is a module that enhances the development experience of Spring Boot applications. It provides several features that can help you speed up your development cycle and improve your productivity. It gives some key features such as:

  • Live reload: Spring Boot Dev Tools can trigger a live reload of your application when changes are detected. This means that you can see your changes immediately without having to manually refresh your browser.
  • Property defaults: Spring Boot Dev Tools can automatically disable certain features that are not useful during development, such as template caching.

To add it to our application, add the following code under <dependencies> in pom.xml.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

On IntelliJ, it might not work out of the box, please enable the Build project automatically in settings. You can follow the instructions as follows.

  • In IntelliJ IDEA: go in settings (ctrl +alt+s) -> Build, Execution, Deployment -> compiler, check “Build project automatically”
  • In IntelliJ IDEA: press ctrl+shift+a then type “registry” and click on it. Then enable the option “compiler.automake.allow.when.app.running”. (may not be available in new versions, If not available skip this)
  • RESTART IntelliJ IDEA.

Lombok

It is a Java library that helps reduce boilerplate code in your Java projects. It does this by providing annotations that generate common code (such as constructors, getters, and setters) for you during the compilation process. This can lead to more concise and readable code. In short, we are reducing the boilerplate code.

To add it to our project we add the following code under <dependencies> tag in pom.xml.

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>

Scope: provided is used for dependencies that are necessary for compilation but are expected to be available at runtime in the environment where the application is deployed. To see what different types of scope are please go through this article.

Lombok may not work out of the box in IntelliJ Idea, you will need to enable annotation processing, please find the instructions here.

Lombok has various annotations that can replace the monotonous code in our project, such as constructors, getters, and setters. Here are some annotations from Lombok.

  • @Getter and @Setter: These annotations generate getters and setters for your class fields.
  • @ToString: Generates a toString() method for your class.
  • @EqualsAndHashCode: Generates equals() and hashCode() methods.
  • @NoArgsConstructor, @AllArgsConstructor: Generate constructors with no arguments or with all arguments, respectively.
  • @Data: Combines @ToString, @EqualsAndHashCode, @Getter, @Setter, and @RequiredArgsConstructor.
  • @Builder: Generates a builder pattern for your class, allowing for more readable code when creating objects.
  • @Value: Similar to @Data but creates an immutable class.
  • @Slf4j or @Log: Automatically adds a logger field to your class.

And many more. Lombok provides a range of annotations to cover various use cases.

Let’s add @Data annotation to our class ‘TodoTask’ and remove all getters and setters, as it will auto-generate it for us.

package com.simplytodo.entity;
import com.simplytodo.enums.TodoTaskStatus;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import java.util.Date;
@Data
public class TodoTask {
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
private static int idCounter = 0;
@Setter(AccessLevel.NONE)
private int id = idCounter++;
private String title;
private String description;
private TodoTaskStatus status = TodoTaskStatus.NOT_STARTED;
private Date dueDate;
private Date createdAt = Date.from(java.time.Instant.now());
}

@Data will generate getters and setters, required arguments constructor, and toString() method at runtime. The AccessLevel.None tells Lombok to not create either getter or setter for that particular field.

Note: In Spring Boot, field-level annotations take precedence over class-level annotations.

Swagger

Swagger is an open-source tool that helps generate documentation for RESTful web services. It provides a user-friendly interface for creating HTTP requests, testing APIs, and organizing requests into collections. Swagger is used by developers to design, test, and document all types of APIs.

To add Swagger to our application, you can use the springfox-swagger2 and springfox-swagger-ui dependencies. Add these dependencies to pom.xml.

<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>

Note: While I was setting up the project, The springfox swagger dependency seems to have problem with spring starter parent version 3.1.5 (v3+ in general), If you want to use above steps make sure your spring-boot-starter-parent version as 2.7.18-SNAPSHOT

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.18-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

Also, make sure to add this line to your application.properties

spring.mvc.pathmatch.matching-strategy=ant_path_matcher

We will create a Docket bean in Spring Boot Configuration. Add a class SwaggerConfig under subpackage config as com.simplytodo.config

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.simplytodo.controller"))
.paths(PathSelectors.any())
.build();
}
}

In the above code, the api() method returns a Docket instance that specifies the base package for the controller classes and the path for which Swagger will generate documentation.

You can also add the description for endpoints with @ApiOperation annotation.

// Example for delete API endpoint
@ApiOperation(value = "Delete the todo task based on task id",
notes = "Pass in task id to delete task")
@DeleteMapping("/task/{id}")
public void deleteTask(@PathVariable int id){
todoService.delete(id);
}

If you run the application and go to http://localhost:8080/swagger-ui/index.html you will see the output as follows.

You can send the API calls from this UI instead of POSTMAN if you like.

#Adding Custom Banner

On spring Application startup, we generally see <Spring> in banner text.

We can add a custom banner to our application as shown below.

We need to make a banner first, go to https://devops.datenkollektiv.de/banner.txt/index.html.

and enter your custom text and select a banner style, then copy the text into a file named banner.txt and place it in the same folder as application.properties

Spring application looks in the resource folder by default for the banner.txt file. If you want to place it in some other directory, you need to add the following code to application.properties

spring.banner.location=classpath:/path/to/banner/bannername.txt

You can also add an image as a banner

spring.banner.image.location=classpath:banner.gif
spring.banner.image.width= 200
spring.banner.image.height= 150
spring.banner.image.margin= 10

However, using an image is generally not recommended as it takes time to load on application startup although it looks very cool.

# Springs IOC [and basic customization]

In Spring, IOC (Inversion of Control) is a design pattern that is used to remove the dependency of an application’s code on specific implementations. It is also known as dependency injection. The basic idea behind IOC is to let the framework take control of creating objects and managing their dependencies.

When using Spring IOC, the application’s objects are created and managed by the Spring container. The Spring container is responsible for wiring together the objects by injecting their dependencies.

The Spring container uses XML or Java-based configuration to define the beans (objects) and their relationships. It scans the configuration files and creates the beans as per the configuration. It also manages the lifecycle of the beans, including creating, initializing, and destroying them.

Dependency Injection in Spring

Dependency Injection is a key aspect of Spring IOC. It is the process of injecting the dependencies of an object instead of the object creating its dependencies. This allows for loose coupling between objects and promotes modular and testable code.

There are three main types of dependency injection in Spring:

  1. Constructor Injection: Dependencies are injected through a constructor. This ensures that all required dependencies are available when the object is created.
  2. Setter Injection: Dependencies are injected through setter methods. This allows for flexibility as dependencies can be changed at runtime.
  3. Field Injection: Dependencies are injected directly into class fields. This is the simplest form of injection but can make testing more difficult.

Spring IOC uses these injection types to wire the dependencies between objects.

There are two primary ways to register a class with Spring IOC:

  1. Using Annotations (Java Configuration):

In modern Spring applications, Java Configuration is more commonly used than XML configuration.

> Registering a class for Spring IOC (to be managed by spring)

The simplest way to achieve this is through @Component annotation. This annotation is used to mark a class as a Spring component, which means that it will be automatically registered with the Spring IOC container. You can also use other annotations such as @Service, @Repository, and @Controller depending on the type of component you want to register.

@Component
public class MyClass{}

> Registering with @Bean

Another way to register a class with Spring IOC is to use the @Bean annotation. This annotation is used to declare a method that produces a bean to be managed by the Spring container. You can define the bean in a configuration class and then use the @Import annotation to import the configuration class into your application context.

@Configuration 
public class AppConfig {
@Bean public MyService myService() { return newMyServiceImpl(); }
}

In this example, @Configuration marks this class as a configuration class. @Bean indicates that the method returns a bean that Spring should manage. The method name (myService) is the bean’s name in the Spring context.

2. Using XML Configuration:

XML configuration involves creating an XML file where you define your beans.

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="myService"class="com.example.MyServiceImpl" /> </beans>

In this example, the <bean> element is used to define a bean. id is the name of the bean and class is the fully qualified name of the class.

By default, the Spring IOC container initializes beans as singleton. However, you can configure the container to initialize beans as prototype, request, session, or global-session. Here is how you can configure the container to initialize beans as prototype:

  1. Use the @Scope annotation to specify the scope of the bean. The @Scope annotation is used to declare the scope of a bean. You can use the following values for the scope:
  • singleton: This is the default scope. The container creates a single instance of the bean, and all requests for the bean return the same object.
  • prototype: The container creates a new instance of the bean every time a request for the bean is made.
  • request: The container creates a new instance of the bean for each HTTP request.
  • session: The container creates a new instance of the bean for each HTTP session.
  • global-session: The container creates a new instance of the bean for each global HTTP session.
@Component
@Scope("prototype")
public class MyBean {
// ...
}

There are more ways to customize Spring IOC containers, but they fall outside the scope of this article, we will discuss them as needed in further parts. If you would like me to add an IOC-specific article, please comment on the post.

# Spring Actuator [Gauging App performance]

Spring Boot Actuators are a set of built-in tools and endpoints that provide insight into the internals of a Spring Boot application. They allow you to monitor and interact with your application at runtime. Actuators expose information about application health, metrics, environment properties, request mappings, and more.

Internally, Actuators are implemented as @Endpoint annotated beans. These beans expose specific information or actions through HTTP endpoints. When you include the spring-boot-starter-actuator dependency in your project, Spring Boot auto-configures these endpoints.

Actuators use Spring’s powerful @Endpoint and @ReadOperation/@WriteOperation annotations to define endpoints. They also leverage Spring’s robust security features, allowing you to secure these endpoints if needed.

In order to add this to your project, please add it to the pom.xml file of the project under <dependencies> tag.

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

By default, Actuators are enabled for basic information. You can customize which endpoints are exposed and their configuration in your application.properties or application.yml file.

For example, to enable all endpoints, you can add the following to your application.properties:

# expose all actuator endpoints 
management.endpoints.web.exposure.include=*

# If we want to show this for only authorized users
management.endpoint.health.group.custom.show-components=when_authorized

After doing this you can go to endpoint http://localhost:8080/actuator/beans to see all the beans in application.

Some default Spring Boot Actuator endpoints include:

  • /actuator/health: Provides information about the health of the application.
  • /actuator/info: Provides general information about the application.
  • /actuator/metrics: Exposes various metrics about the application, such as memory usage, CPU usage, and request counts.
  • /actuator/beans: Lists all the beans in the application context.
  • /actuator/mappings: Provides information about the request mappings in the application.
  • /actuator/env: Exposes the environment properties of the application.

These are just a few examples. There are many more endpoints available, and you can also create your own custom endpoints.

To create a custom Spring Boot Actuator endpoint, you can follow these steps:

  1. Create a new class and annotate it with @Endpoint to define your endpoint. You can also use additional annotations like @ReadOperation and @WriteOperation to specify the type of operations your endpoint supports.
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;

@Endpoint(id = "todo-actuator-endpoint")
public class TodoActuatorEndpoint {
@ReadOperation
public String customOperation() {
// Implement your custom logic here
return "Todo custom endpoint response";
}
}

2. Register your endpoint with the application context. You can do this by creating a configuration class and using the @Bean annotation.

import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ActuatorConfig {
@Bean
public TodoActuatorEndpoint customEndpoint() {
return new TodoActuatorEndpoint();
}
}

3. Customize the endpoint ID and URL mapping. By default, the endpoint ID is derived from the class name. You can customize it using the id attribute of the @Endpoint annotation. You can also customize the URL mapping by specifying a prefix in the application.properties file.

management.endpoints.web.base-path=/actuator

Test your custom endpoint by accessing the URL in your browser or using a tool like cURL.

GET /actuator/todo-actuator-endpoint

This will invoke the customOperation() method in your custom endpoint class and return the response.

You can read about this in more detail at spring’s official documentation here. I also recommend going through this Baeldung article about spring boot actuators.

If you have any questions, please feel free to discuss in comments, I will try to reply for as soon as possible. Thank you. Happy Coding :)

Here is the link to part 2.1

--

--

Yash Patel

Software Developer. Extremely Curious | Often Wrong | Always Learning.