Overview
Spring is the framework for building enterprise-level Java applications. Spring Boot is built on top of Spring to simplify development by automating configuration and deployment (using embedded Tomcat/Jetty)
- Spring Boot Doc: https://docs.spring.io/spring-boot/index.html
- Bean : same as a component
- Dependency Injection (DI) : process of wiring beans together like how component A depends on result of component B
- Spring Application Context : the container that create and maintain components and inject them into beans as needed
- Controller : responsible for fetching and processing data
- Model : object responsible for ferrying data between a controller and the view responsible for rendering it
- View : responsible for rendering data into HTML
Bean and @Autowired
Beans are classes that have been labeled @Component, @Service, @Repository, @Controller, or etc.
- Spring will automatically create and manage those classes/beans on startup unless specified otherwise
- For any bean that needs another bean, use
@Autowiredannotation to inject the needed bean - Reduces code to create and manage classes
@Autowired: can be omitted if there is only one constructor
@Service
public class UserService { } // Spring will create a new UserService() bean at startup
----------------------------------------------------------------------------
@Service
public class OrderService { // Spring will create a new OrderService(UserService) bean at startup
private final UserService userService;
@Autowired
public OrderService(UserService userService) { // The required userService bean will be injected from what Spring created at startup
this.userService = userService;
}
}Setup
Starting New Project
- In VS Code command palette type:
Spring Initializr: create Maven projectorSpring Initializr: create Gradle project - Pick Spring Boot version
- Pick programming language
- Put in group id : identifier for organization or group in reverse domain name notation
- Examples:
com.googleorio.github.tuan - Put in artifact id : name of your project or module (Ex:
taco-cloud) - Pick package type: .jar or .war files
- Pick Java version
- Add dependencies
Testing Project
- To run the test classes on the app, use
./mvnw testin the command line ./mvnw clean test -Xto get rid of leftover class files or incomptible versions from previous build-Xis for debug mode
Running Project
- To run the app, use
./mvnw spring-boot:runin the command line - Can also use the Spring Boot Dashboard to start and run test by clicking the play and globe icons
- Normally runs on
http://localhost:8080/
Building Project
- The app will be run from an executable .jar file
- In the command line, use
./mvnw packageto build the app into thetarget/folder - In the command line, use
java -jar target/{appName}.jarto run the .jar file
Deploying Project
Ch 18 of Spring in Action (Walls, C.)
Dependencies
Core Dependencies
- Spring Boot Starter Web : adds REST API support using Spring MVC
- Build controllers, handle HTTP requests/responses
- Spring Boot Starter Test : includes JUnit, Mockito, and Spring Test
- For unit and integration testing
- Spring Boot Starter Validation/ Validation I/O : adds bean validation (JSR-380);
spring-boot-starter-validation- Replace a bunch of if-else or switch-case statements to validate data
@NotNull: field annotation to make sure the field is not empty or null@NotBlank: field annotation to make sure the field is not empty@Size(min=1, message="You must select at least 1 ingredient"): field annotation to make sure the field is at least 1 in length and display the message if not@Pattern(regexp="", message=""): field annotation to make sure the field matches the pattern@Digits(integer=3, fraction=0, message=""): field annotation to make sure the field has 3 digits and is a whole number@CreditCardNumber(message="")field annotation to make sure it's a valid credit card number using Luhn algorithm check- Validate request data using
@Validin the controller method parameter
@Data public class TacoOrder { @NotBlank(message = "Name is required") private String deliveryName; } -------------------------------- @PostMapping public String processOrder(@Valid TacoOrder order, Errors errors, SessionStatus sessionStatus) {
- Site: https://projectlombok.org/
- Lombok must be installed into IDE or else it will complain about missing getters/setters and methods
- Comes with the
Extension Pack for Javaextension in VS Code - Automatically generate getter/setter methods as well as equals(), hashCode(), toString(), etc
@DataCLASS annotation: composite annotations for@Getteron all fields,@Setteron all non-final fields,@ToString,@EqualsAndHashCode, and@RequiredArgsConstructor@Getterfield annotation: automatically creates a getter method for the field@Setterfield annotation: automatically creates a getter method for the field@ToStringclass annotation: automatically create a toString() method that has a format to include class name, field names and values; configurable@EqualsAndHashCodeclass annotation: equals() and hashCode() method- By default, uses all non-static, and non-transient fields, but configurable
@RequiredArgsConstructorclass annotation: automatically generates a constructor with one parameter for each field that is...final, but not initialized or that is annotated with@NonNull
- Automatically restarts your app when code changes; mainly code in
src/main/path - Does NOT automatically restart when dependencies change
- Automatic browser refresh when browser-destined resources (such as templates, JS, stylesheets, and so on) change
- Requires a LiveReload plugin in the browsers to work (available in Chrome, Safari, and Firefox)
- Automatic disabling of template caches
- Built in H2 Console, if the H2 database is in use
Database & Persistence Dependencies
- Spring Boot Starter Data JPA : simplifies database access using JPA and Hibernate
- For working with SQL databases using
@Entity,@Repository
- For working with SQL databases using
- Spring Boot Starter JDBC : enables low-level database access with JDBC
- Use for direct SQL execution or legacy DB connections
- Spring Boot Starter Data MongoDB : provides integration with MongoDB
- Use when working with NoSQL databases
- H2 Database : lightweight in-memory database
- Perfect for development and testing without external DB setup
- MySQL/PostgreSQL Driver : adds database driver support
- Used to connect your Spring Boot app to a relational database
- Spring Data Solr : enables integration with Apache Solr search platform
- Used to connect your Spring Boot app to a Solr server
Security & Authentication Dependencies
- Spring Boot Starter Security : adds authentication and authorization features
- Secure your routes, add login, and password encoding
- Spring Security OAuth2 Resource Server : supports OAuth2 and JWT authentication
- For token-based security in APIs
- Spring Security JWT : manages JSON Web Tokens
- Used for stateless authentication in REST APIs
API Communication & Serialization
- Spring Boot Starter WebFlux : supports reactive, non-blocking REST APIs
- Use for async or high-concurrency applications
- Jackson Databind : handles JSON serialization and deserialization
- Automatically included in
spring-boot-starter-web
- Automatically included in
- Spring Boot Starter WebClient : allows REST calls to external APIs
- Modern alternative to
RestTemplate
- Modern alternative to
Utility & Tooling Dependencies
- Spring Boot Actuator : exposes health and metrics endpoints
- Monitor and manage your application at runtime
- MapStruct : helps map between objects (e.g., DTOs ↔ Entities)
- Used for clean data transfer between layers
- ModelMapper : alternative object-mapping library
- Automatically converts between DTOs and entities
Cloud, Messaging, & Advanced Features
- Spring Boot Starter Data Redis : integrates with Redis for caching and data storage
- Use for improving performance or distributed caching
- Spring Boot Starter AMQP : supports message queues like RabbitMQ
- Use for asynchronous communication between services
- Spring Cloud : provides tools for microservices and distributed systems
- Useful for service discovery, configuration, and resilience
- Spring Boot Starter Mail : allows sending emails from your application
- Use for notifications, password resets, etc.
Project Structre
mvnwandmvnw.cmd: Maven wrapper scripts to build the project even if Maven is not installed on the computer- Build config file:
pom.xmlfor Maven orbuild.gradlefor Gradle - Spring Boot version
- Properties
- Dependencies
- Plugins
src/main/java/: Java source code/groupId/artifactId/projectNameApplication.java: Spring Boot main class that bootstraps the project- Where main app starts and contains config for Spring Framework or the config can be placed in a separate configuration class using annotation
@Configuration src/test/java/: test source code/groupId/artifactId/projectNameApplicationTests.java: simple test class to ensure Spring app context loads successfullysrc/main/resources/: static resources and config files (likeapplication.properties)/static/: static content (images, stylesheets, JS)/templates/: template files to render content to browser/application.properties: config properties for the app and dependenciesspring.application.name=taco-cloud: set the name of the apptarget/orbuild: compiled output (auto-generated)
Spring Core
@Component: class annotation to mark the class as a Spring-managed bean so that it can be injected later through@Autowired- A Spring-bean/component is an objectcreated by the Spring container that manages its lifecycle and can inject it anywhere you need
- A Spring-bean/component is a singleton object so there is one shared instance of it per Spring app context
- Spring bean/componnent can implement interfaces
- Be proxied (for transactions, caching, AOP, etc.)
- Be replaced or mocked for testing
@Autowired: field annotation to tell Spring to find a bean/component of this type and inject it hereConverterinterface : interface to convert a value to another value by implementing itsconvert()method
@Component
public class IngredientByIdConverter implements Converter<String, Ingredient> {
private Map<String, Ingredient> ingredientMap = new HashMap<>();
public IngredientByIdConverter() {
ingredientMap.put("FLTO",
new Ingredient("FLTO", "Flour Tortilla", Type.WRAP));
ingredientMap.put("COTO",
new Ingredient("COTO", "Corn Tortilla", Type.WRAP));
}
@Override
public Ingredient convert(String id) {
return ingredientMap.get(id);
}
}Spring MVC Module
For building web applications; whether to return view (HTML) or data (for REST API - Ch 7 of Spring in Action)
App
@Controller: handles incoming HTTP requests, processing them, and returning a view/JSP@RestController: handles incoming HTTP requests, processing them, and returning data (JSON/XML) directly@GetMapping("/"): method annotation that indicates that if an HTTP GET request is received for the root path "/" then the annotated method should handle that request@RequestMapping("/"): class annotation that indicates that if an HTTP GET request is received for the root path "/" then the annotated class should handle that request through the class that is annnoated with any of the following@GetMapping: method annotation for method that handles HTTP GET requests@PostMapping: method annotation for method that handles HTTP POST requests@PutMapping: method annotation for method that handles HTTP PUT requests@DeleteMapping: method annotation for method that handles HTTP DELETE requests@PatchMapping: method annotation for method that handles HTTP PATCH requests@SessionAttribute("modalName"): class attribute for Spring controllers to make sure Spring store the "modelName" so it persists across multiple requests- Used with
@ModelAttribute(name = "modelName"); method annotation that specifies the return object of this method will be labelled "modelName" and put into the model
@Controller
@SessionAttributes("tacoOrder") // 👈 Keeps "tacoOrder" in session so it can span several pages/requests
public class TacoOrderController {
@ModelAttribute("tacoOrder")
public Order order() {
return new Order();
}Testing
@WebMvcTest: annotates test class to run in the context of a Spring MVC app@Test: annotates test methods to be run@Autowired: to inject the class with a MockMVC object to drive the mockup
@WebMvcTest(HomeController.class)
public class HomeControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testHomePage() throws Exception {
mockMvc.perform(get("/"))
.andExpect(status().isOk())
.andExpect(view().name("home"))
.andExpect(content().string(
containsString("Welcome to...")));
}
}Spring Data
CRUD: create, read, update, and delete
CrudRepositoryprovides basic CRUD operations for your entities so there is no need to implement their methodsCrudRepository<Entity, ID>:Entity: parameter that tells which entity/table the CRUD operation are forID: parameter for the type of the primary key (ID field)- Usage:
public interface IngredientRepository extends CrudRepository<Order, Long> {} - Built-In Methods
save(S entity): insert or update an entityfindById(ID id): retrieve an entity by its IDfindAll(): retrieve all entitiesdeleteById(ID id): delete an entity by its IDdeleteAll() : delete all entitiescount(): count the total number of entities- Customizing Methods: Spring Data can also create custom methods by parsing the method name
List<Order> findByDeliverZip(String deliveryZip): return all entities by matching thedeliveryZipproperty
JDBC
Low-level framework for interacting with SQL database where you write the SQL queries yourself
JPA
High-level framework for SQL where SQL is generated automatically from entity mappings
@Entity: class annotation for the object that will get mapped directly to a table in database@Id: field annotation to designate it as the uniquely identify in the database; the primary key@GeneratedValue(strategy = GenerationType.AUTO): field annotation to let the database auto-generate the value for this field- Relationship Annotation
@ManyToMany: field annotation to designate a many-to-many relationship between two entities@ManyToOne: field annotation to designate a many-to-one relationship between two entities@OneToMany: field annotation to designate a one-to-many relationship between two entities@OneToOne: field annotation to designate a one-to-one relationship between two entities- Cascade Type: Example:
@ManyToMany(cascade = CascadeType.ALL) CascadeType.ALL: apply all cascade operations to the related child entitiesCascadeType.PERSIST: when the parent entity is saved, also save the related child entitiesCascadeType.MERGE: when the parent entity is updated, also update the related child entitiesCascadeType.REMOVE: when the parent entity is deleted, also delete the related child entities
Spring Security
Ch 5 and 12 of Spring in Action