Repository: in28minutes/in28minutes.github.io Branch: master Commit: dfb80ebffd41 Files: 241 Total size: 2.6 MB Directory structure: gitextract_bk9ds43v/ ├── .gitignore ├── 404.html ├── CNAME ├── Gemfile ├── _blog/ │ ├── 1-springboot.md │ ├── 2-spring-framework.md │ ├── 3-springboot-jpa.md │ ├── 4-springboot-microservices.md │ ├── 5-springboot-unit-testing.md │ ├── articles/ │ │ ├── 2016-01-01-article-template-full-stack.md │ │ ├── 2016-01-01-article-template.md │ │ ├── 2017-01-17-spring-boot-basic-rest-service-top20.md │ │ ├── 2017-01-21-spring-initializr-web-application.md │ │ ├── 2017-01-28-spring-boot-unit-testing-with-junit-top20.md │ │ ├── 2017-01-29-spring-boot-autoconfiguration-top20.md │ │ ├── 2017-01-30-spring-boot-integration-testing.md │ │ ├── 2017-01-30-spring-boot-starter-parent.md │ │ ├── 2017-01-30-spring-boot-starter-projects.md │ │ ├── 2017-01-30-spring-boot-starter-security.md │ │ ├── 2017-01-30-spring-boot-web-application-top20.md │ │ ├── 2017-02-02-spring-boot-vs-spring-mvc-vs-spring.md │ │ ├── 2017-07-05-introduction-to-jpa-with-spring-boot.md │ │ ├── 2017-07-06-introduction-to-web-services-restful-and-soap.md │ │ ├── 2017-10-11-spring-boot-master-class.md │ │ ├── 2017-10-13-spring-in-10-steps.md │ │ ├── 2017-10-14-spring-interview-questions.md │ │ ├── 2017-10-15-spring-master-class.md │ │ ├── 2017-10-16-spring-micro-services.md │ │ ├── 2017-10-17-spring-web-services.md │ │ ├── 2017-10-18-springboot-in-10-steps.md │ │ ├── 2017-10-19-SpringMvcStepByStep.md │ │ ├── 2017-11-11-eclipse-in-5-steps.md │ │ ├── 2017-11-12-in28minutes-connect.md │ │ ├── 2017-11-13-jpa-and-hibernate-with-spring-boot.md │ │ ├── 2017-11-14-jpa-in-10-steps.md │ │ ├── 2017-11-15-junit-in-5-steps.md │ │ ├── 2017-11-15-spring-boot-and-spring-jdbc-with-h2.md │ │ ├── 2017-11-16-maven-in-5-steps.md │ │ ├── 2017-11-17-mockito-in-5-steps.md │ │ ├── 2017-11-18-JavaWebApplicationStepByStep-JSP-Servlets.md │ │ ├── 2017-12-01-spring-boot-and-jpa-hibernate-with-h2-top20.md │ │ ├── 2017-12-02-spring-boot-and-iBatis-with-h2.md │ │ ├── 2017-12-03-spring-boot-and-h2-an-inmemory-database-top20.md │ │ ├── 2017-12-04-connecting-spring-boot-with-other-databases-mySql-Oracle-etc.md │ │ ├── 2017-12-06-introduction-to-spring-data-rest.md │ │ ├── 2017-12-07-introduction-to-spring-data-with-spring-boot.md │ │ ├── 2017-12-08-integrating-with-bootstrap-and-jquery.md │ │ ├── 2017-12-09-integrating-static-content-css-js-with-spring-boot.md │ │ ├── 2017-12-10-spring-boot-project-with-eclipse-and-maven-top20.md │ │ ├── 2017-12-12-logging-with-spring-boot.md │ │ ├── 2017-12-13-spring-boot-unit-testing-with-junit-and-mockito-top20.md │ │ ├── 2017-12-14-spring-boot-developer-tools.md │ │ ├── 2017-12-15-implementing-aop-with-spring-boot.md │ │ ├── 2017-12-16-spring-boot-java-and-xml-application-contexts-top20.md │ │ ├── 2017-12-17-spring-boot-embedded-servers-top20.md │ │ ├── 2017-12-18-spring-boot-application-configuration-top20.md │ │ ├── 2017-12-19-spring-boot-application-configuration-yaml.md │ │ ├── 2017-12-20-spring-boot-application-configuration-profiles.md │ │ ├── 2017-12-21-spring-boot-and-component-scan-top20.md │ │ ├── 2017-12-23-spring-boot-interview-questions-top20.md │ │ ├── 2017-12-24-spring-interview-questions-top20.md │ │ ├── 2017-12-25-spring-boot-rest-service-with-jpa-top20.md │ │ ├── 2017-12-26-spring-boot-exception-handling-for-rest-services-top20.md │ │ ├── 2017-12-27-spring-boot-validation-for-rest-services-top20.md │ │ ├── 2017-12-28-spring-boot-HATEOAS-for-rest-services.md │ │ ├── 2017-12-29-spring-boot-content-negotiation-xml-and-json.md │ │ ├── 2017-12-30-spring-boot-documenting-with-swagger.md │ │ ├── 2017-12-31-spring-boot-versioning-restful-services.md │ │ ├── 2018-01-01-spring-boot-soap-web-service.md │ │ ├── 2018-01-02-spring-boot-example-projects-with-code-top20.md │ │ ├── 2018-01-03-spring-boot-rest-api-example-projects-with-code.md │ │ ├── 2018-01-04-getting-started-with-spring-boot-projects-with-code.md │ │ ├── 2018-01-05-spring-boot-microservices-part1-top20.md │ │ ├── 2018-01-06-spring-boot-microservices-part2.md │ │ ├── 2018-01-07-spring-boot-microservices-part3.md │ │ ├── 2018-01-08-spring-boot-microservices-part4.md │ │ ├── 2018-01-09-spring-boot-microservices-part5.md │ │ ├── 2019-02-02-the-in28minutes-way.md │ │ ├── 2019-02-03-spring-boot-maven-eclipse-troubleshooting-guide-and-faq.md │ │ ├── 2019-02-03-spring-boot-tutorials-for-beginners.md │ │ ├── 2019-02-18-064-Monolith-To-Microservice.md │ │ ├── 2019-03-27-spring-boot-react-crud-full-stack-with-maven-top20.md │ │ ├── 2019-04-10-Architecture-Goal-Of-An-Architect.md │ │ ├── 2019-04-10-Architecture-Introduction-To-Software-Architecture.md │ │ ├── 2019-04-10-Architecture-Top-Architect-Responsibilities.md │ │ ├── 2019-04-10-Architecture-Top-Qualities-Great-Architects.md │ │ ├── 2019-04-10-Architecture-Why-Have-Multiple-Layers.md │ │ ├── 2019-04-10-Component-Scan.md │ │ ├── 2019-04-10-Dependency-Injection.md │ │ ├── 2019-04-10-Introduction-To-Spring-Boot.md │ │ ├── 2019-04-10-Introduction-To-Spring-Data-REST.md │ │ ├── 2019-04-10-Introduction-To-Spring-Framework.md │ │ ├── 2019-04-10-Introduction-To-spring-Data.md │ │ ├── 2019-04-10-Inversion-Of-Control.md │ │ ├── 2019-04-10-Spring-Batch.md │ │ ├── 2019-04-10-Spring-Projects.md │ │ ├── 2019-04-10-SpringModules.md │ │ ├── 2019-04-10-What-Is-A-Dependency.md │ │ ├── 2019-04-10-What-Is-A-Profile.md │ │ ├── 2019-04-17-Software-Design-001-FiveThings-DesignReview.md │ │ ├── 2019-04-17-Software-Design-003-EvolutionaryDesign.md │ │ ├── 2019-04-17-Software-Design-006-WhatIsCoupling.md │ │ ├── 2019-04-17-Software-Design-008-Cohesion.md │ │ ├── 2019-04-17-Software-Design-012-What-Is-Abstraction.md │ │ ├── 2019-04-17-Software-Design-016-Five-Tips-Simple-Design.md │ │ ├── 2019-04-17-Software-Design-019-Encapsulation.md │ │ ├── 2019-04-17-Software-Design-109-Design-Patterns-For-Beginners.md │ │ ├── 2019-05-07-spring-boot-react-spring-security-basic-and-jwt-authentication.md │ │ ├── 2019-05-08-Microservice-Basics-056-The-Cloud.md │ │ ├── 2019-05-09-Microservice-Basics-063-Introduction-To-Spring-Cloud.md │ │ ├── 2019-05-10-Microservice-Basics-065-Microservices-SOA-Differences.md │ │ ├── 2019-05-11-Microservice-Basics-066-Challenges-With-Microservices.md │ │ ├── 2019-05-12-Microservice-Basics-067-Advantages-Of-Microservices.md │ │ ├── 2019-05-19-Microservice-Terminology-051-Why-Service-Discovery-With-Eureka.md │ │ ├── 2019-05-19-Microservice-Terminology-058-Centralized-Configuration.md │ │ ├── 2019-05-20-Microservice-Terminology-059-API-Gateway.md │ │ ├── 2019-05-21-Microservice-Terminology-057-Centralized-Logging-In-Microservices.md │ │ ├── 2019-05-22-Microservice-Terminology-055-Dynamic-Scaling.md │ │ ├── 2019-05-23-Microservice-Terminology-053-Fault-Tolerance.md │ │ ├── 2019-06-12-Microservice-Best-Practices-037-Vertical-Slice.md │ │ ├── 2019-06-12-Microservice-Best-Practices-046-Why-Asynchronous-Communication.md │ │ ├── 2019-06-12-Microservice-Best-Practices-048-Why-Build-An-Archetype.md │ │ ├── 2019-06-12-Microservice-Best-Practices-050-Why-Message-Queues-Asynchronous-Communication.md │ │ ├── 2019-06-12-Microservice-Best-Practices-060-Event-Driven-Architectures.md │ │ ├── 2019-06-12-Microservice-Best-Practices-068-The-12-Factor-App-CLoud-Native-Best-Practices.md │ │ ├── 2019-06-20-Programming-Basics-002-AspectOrientedProgramming.md │ │ ├── 2019-06-20-Programming-Basics-080-5-Things-Think-About-Programming.md │ │ ├── 2019-06-20-Programming-Basics-088-Introduction-To-Object-Oriented-Programming.md │ │ ├── 2019-08-28-Automation-Testing-024-Mocking.md │ │ ├── 2019-08-28-Automation-Testing-026-Five-Types-Of-Automation-Tests.md │ │ ├── 2019-08-28-Automation-Testing-099-Top-Six-Java-Unit-Testing-Frameworks.md │ │ ├── 2019-08-28-Automation-Testing107-JUnit-Unit-Testing-Best-Practices.md │ │ ├── 2019-09-07-spring-boot-videos.md │ │ ├── 2019-09-08-Java-Programmer-035-In-Memory-Database.md │ │ ├── 2019-09-09-Java-Programmer-036-EmbeddedServers.md │ │ ├── 2019-09-10-Java-Programmer-089-Introduction-To-Maven.md │ │ ├── 2019-09-11-Java-Programmer-100-Five-Great-Tools-To-Learn.md │ │ ├── 2019-09-12-Java-Programmer-101-Five-Great-Languages-To-Learn.md │ │ ├── 2019-09-13-Java-Programmer-102-Five-Great-Frameworks-To-Learn.md │ │ ├── 2019-10-07-spring-boot-vue-crud-full-stack-with-maven.md │ │ ├── 2019-11-03-udemy-courses-discount-codes.md │ │ ├── 2019-11-15-Code-Quality-025-Five-Things-About-CI.md │ │ ├── 2019-11-15-Code-Quality-070-Refactoring.md │ │ ├── 2019-11-15-Code-Quality-077-CodeSmells.md │ │ ├── 2019-11-15-Code-Quality-078-5-Important-Coding-Standards.md │ │ ├── 2019-11-15-Code-Quality-079-Code-Quality-Overview.md │ │ ├── 2019-11-15-Code-Quality-105-Introduction-To-Coding-Standards.md │ │ ├── 2019-11-15-Code-Quality-106-Code-Review-Best-Practices.md │ │ ├── 2019-11-15-Code-Quality-108-Static-Analysis-Best-Practices.md │ │ ├── 2019-11-15-Code-Quality-Terminology-069-Technical-Debt.md │ │ ├── 2019-11-15-Code-Quality-Terminology-071-Readability-Of-Code.md │ │ ├── 2019-11-15-Code-Quality-Terminology-072-Legacy-Code.md │ │ ├── 2019-11-15-Code-Quality-Terminology-073-Code-Duplication.md │ │ ├── 2019-11-15-Code-Quality-Terminology-074-Code-Coverage.md │ │ ├── 2019-11-15-Code-Quality-Terminology-075-Code-Complexity.md │ │ ├── 2019-11-15-NFR-028-Portability.md │ │ ├── 2019-11-15-NFR-029-Performance.md │ │ ├── 2019-11-15-NFR-030-Scalability.md │ │ ├── 2019-11-15-NFR-031-Reusability.md │ │ ├── 2019-11-15-NFR-032-Reliability.md │ │ ├── 2019-11-15-NFR-033-Maintainability.md │ │ ├── 2019-11-15-NFR-034-Security.md │ │ ├── 2019-11-15-NFR-040-Non-Functional-Requirements.md │ │ ├── 2019-11-15-NFR-041-Web-Application-Security-OWASP-Top-Ten-Flaws.md │ │ ├── 2019-11-15-NFR-045-Modularity.md │ │ ├── 2019-11-15-NFR-047-Availability.md │ │ ├── 2019-11-15-REST-API-007-REST-WhatIs-HATEOAS.md │ │ ├── 2019-11-15-REST-API-013-REST.md │ │ ├── 2019-11-15-REST-API-014-SOAP-v-REST.md │ │ ├── 2019-11-15-REST-API-018-Contract-First.md │ │ ├── 2019-11-15-REST-API-021-Code-First.md │ │ ├── 2019-11-15-REST-API-098-REST-API-Web-Services-Best-Practices.md │ │ ├── 2019-11-15-Software-Design-Principles-005-SingleResponsibilityPrinciple.md │ │ ├── 2019-11-15-Software-Design-Principles-009-PrinciplesOfSimpleDesign.md │ │ ├── 2019-11-15-Software-Design-Principles-015-Dependency-Inversion-Principle.md │ │ ├── 2019-11-15-Software-Design-Principles-017-Open-Closed-Principle.md │ │ ├── 2019-11-15-Software-Design-Principles-022-SOLID-Principles.md │ │ ├── 2019-11-15-Software-Design-Priniples-039-Separation-Of-Concerns.md │ │ ├── 2020-01-01-Taking-Spring-Boot-To-Cloud.md │ │ ├── 2020-02-24-DevOps.md │ │ ├── 2020-03-14-Docker.md │ │ ├── 2020-09-28-best-practices-in-microservices.md │ │ ├── 2020-09-28-demoposition-design-pattern-microservices.md │ │ ├── 2020-10-06-oauth2-authorization-grant-flowchart.md │ │ ├── 2020-10-07-oauth2-client-credentials-grant-flowchart.md │ │ ├── 2020-10-08-oauth2-implicit-grant-flowchart.md │ │ ├── 2020-10-09-oauth2-resource-owner-password-credentials-grant-flowchart.md │ │ ├── 2020-11-02-single-signon-flowchart.md │ │ └── 2020-11-12-understanding-json-web-token.md │ ├── index.md │ ├── java-programming.md │ ├── programming.md │ ├── restapi.md │ ├── software-design.md │ └── swcodequality.md ├── _config.yml ├── _includes/ │ ├── footer.html │ ├── head.html │ ├── nav.html │ ├── newsletter.html │ └── trustedby.html ├── _layouts/ │ ├── about.html │ ├── blog.html │ ├── category.html │ ├── default.html │ ├── home.html │ ├── page.html │ ├── post.html │ └── resources.html ├── about.md ├── assets/ │ ├── css/ │ │ ├── animate.css │ │ ├── custom.css │ │ ├── lineicons.css │ │ ├── syntax.css │ │ └── ud-styles.css │ ├── js/ │ │ └── main.js │ └── scss/ │ ├── _404.scss │ ├── _about.scss │ ├── _banner.scss │ ├── _blog-details.scss │ ├── _blog.scss │ ├── _common.scss │ ├── _contact.scss │ ├── _default.scss │ ├── _faq.scss │ ├── _features.scss │ ├── _footer.scss │ ├── _header.scss │ ├── _hero.scss │ ├── _login.scss │ ├── _mixin.scss │ ├── _pricing.scss │ ├── _team.scss │ ├── _testimonials.scss │ ├── _variables.scss │ └── ud-styles.scss ├── blog-details.html ├── google-cloud-ace-resources.md ├── google-cloud-cdl-resources.md ├── index.md └── presentation.pptx ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ _site .sass-cache .jekyll-cache .jekyll-metadata vendor delivery.zip .DS_Store _old-posts/ ~$presentation.pptx # See http://help.github.com/ignore-files/ for more about ignoring files. # compiled output /dist /tmp /out-tsc # dependencies /node_modules # IDEs and editors /.idea .project .classpath .c9/ *.launch .settings/ *.sublime-workspace # IDE - VSCode .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json # misc /.sass-cache /connect.lock /coverage /libpeerconnection.log npm-debug.log yarn-error.log testem.log /typings # System Files .DS_Store Thumbs.db # Compiled class file *.class # Log file *.log # BlueJ files *.ctxt # Mobile Tools for Java (J2ME) .mtj.tmp/ # Package Files # *.jar *.war *.ear *.tar.gz *.rar *.cmd *.classpath *.settings *.project *.mvn mvnw target *.DS_Store # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* ================================================ FILE: 404.html ================================================ --- permalink: /404.html layout: page title: Oops! ---

44

OOPSSSSS..: We are searching!

Sorry, the page you're looking for cannot be accessed

{% include newsletter.html %} ================================================ FILE: CNAME ================================================ www.springboottutorial.com ================================================ FILE: Gemfile ================================================ source "https://rubygems.org" gem "jekyll", "~> 4.2.2" group :jekyll_plugins do gem "jekyll-feed" gem "jekyll-seo-tag" # gem 'jekyll-analytics' end platforms :mingw, :x64_mingw, :mswin, :jruby do gem "tzinfo", "~> 1.2" gem "tzinfo-data" end gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin] gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby] gem "webrick", "~> 1.7" ================================================ FILE: _blog/1-springboot.md ================================================ --- layout: category title: Spring Boot slug: SpringBoot image: /images/spring-boot-category.png --- ================================================ FILE: _blog/2-spring-framework.md ================================================ --- layout: category title: Spring Framework slug: SpringFramework image: /images/spring-framework-category.png --- ================================================ FILE: _blog/3-springboot-jpa.md ================================================ --- layout: category title: Spring Boot JPA slug: SpringBootJPA image: /images/spring-data-category.png --- ================================================ FILE: _blog/4-springboot-microservices.md ================================================ --- layout: category title: Spring Boot Microservices slug: SpringBootMicroservices image: /images/microservices-category.png --- ================================================ FILE: _blog/5-springboot-unit-testing.md ================================================ --- layout: category title: Spring Boot Unit Testing slug: SpringBootUnitTesting image: /images/unit-test-category.png --- ================================================ FILE: _blog/articles/2016-01-01-article-template-full-stack.md ================================================ --- layout: post title: TODO date: 2025-03-09 12:31:19 summary: TODO categories: ZZZZZZ permalink: /full-stack-url --- In this guide, you’ll learn how to create a full-stack application with **Angular**, **React**, or **Vue.js** on the frontend, and **Spring Boot** powering the backend REST API. ## Todo - How to import and run projects from git repository? - Create videos based on full stack articles. We will and create a TODO***. ## You will learn - What? - Why? - How? - Where? - When? ## Resources/URLs/Entities Overview In this guide, we’ll be building **TODO services** step by step. > The REST API can be extended to integrate with other microservice infrastructure components and function as an independent microservice. ## Complete Maven Project With Code Examples > All the code examples from this guide are available in our GitHub Repo- https://github.com/in28minutes/spring-boot-examples/tree/master/TODO_URL ## Project Structure The following screenshot illustrates the structure of the project we will create. ![Image](/images/SpringBootRestService-ProjectStructure.png "Spring Boot Rest Service - Project Structure") A few important files in this project: - **`StudentController.java`** – REST controller exposing the three service methods discussed above. - **`Course.java`, `Student.java`, `StudentService.java`** – Business logic layer. - `StudentService` provides methods that are consumed by the REST controller. - **`StudentControllerIT.java`** – Integration tests for the REST services. - **`StudentControllerTest.java`** – Unit tests for the REST services. - **`StudentServicesApplication.java`** – Entry point for the Spring Boot application. - To run the application, launch this file as a **Java Application**. - **`pom.xml`** – Project configuration and dependencies. - Includes **Spring Boot Starter Web** for building REST APIs. ## Tools You Will Need - **Maven 3.0+** – for building the Spring Boot API project - **npm** and **webpack** – for building the frontend - **IDE of your choice** - *Eclipse* or *IntelliJ IDEA* for Java - *Visual Studio Code* for JavaScript, TypeScript, Angular, or React - **JDK 17+** – required for running the Spring Boot backend - **Node v8+** – required for running the frontend - **Embedded Tomcat** – comes built into Spring Boot Starter Web #### Installing Node.js (npm) & Visual Studio Code - 🎥 **Playlist**: [YouTube – Node.js & VS Code Setup](https://www.youtube.com/playlist?list=PLBBog2r6uMCQN4X3Aa_jM9qVjgMCHMWx6) - **Steps** - Step 01 – Install **Node.js** and **npm** (Node Package Manager) - Step 02 – Quick introduction to **npm** - Step 03 – Install **Visual Studio Code** (Frontend JavaScript Editor) --- #### Installing Java, Eclipse, IntelliJ IDEA & Embedded Maven - 🎥 **Playlist**: [YouTube – Java, Eclipse & Maven Setup](https://www.youtube.com/playlist?list=PLBBog2r6uMCSmMVTW_QmDLyASBvovyAO3) - **Steps** - Step 00 – Overview: Installing **Java**, **Eclipse**, and **Maven** - Step 01 – Install **Java JDK** - Step 02 – Install **Eclipse IDE** or **IntelliJ IDEA** - Step 03 – Use **Embedded Maven** in Eclipse - Step 04 – Troubleshooting Java, Eclipse, and Maven setup ## Article Begins Some theory ## Bootstrapping Spring Boot REST API with Spring Initializr Creating a REST service with **Spring Initializr** is simple and straightforward. In this guide, we’ll use **Spring Web MVC** as our web framework. [Spring Initializr](http://start.spring.io/) is an excellent tool for bootstrapping Spring Boot projects, allowing you to generate a ready-to-run application in just a few clicks. ![Image](/images/Spring-Initializr-Web.png "Web, Actuator and Developer Tools") ![Image](/images/Spring-Initializr-Web-JPA.png "Web, JPA, Hibernate and Developer Tools") As shown in the image above, follow these steps: 1. Launch **Spring Initializr** and configure the project: - Set **Group** as `TODO` - Set **Artifact** as `TODO` - Add the following dependencies: - Spring Web - Spring Boot DevTools - `TODO` 2. Click **Generate Project** to download the project archive. 3. Import the project into **Eclipse** or **IntelliJ IDEA** - `File` → `Import` → `Existing Maven Project` 4. To understand all the files included in this project, refer to: `TODO` ## Bootstrapping Angular Frontend with Create React App Change title to 'My Full Stack Application with Spring Boot and React' in index.html ```typescript import React, { Component } from 'react'; class InstructorApp extends Component { render() { return (

Instructor Application

) } } export default InstructorApp ``` npm add axios npm add react-router-dom npm add formik ## 📺 Recommended Watch ### 🔹 Angular + Spring Boot - [Full Stack Application Architecture - Angular + Spring Boot](https://youtu.be/7ZsHQNlkF2g) - [Installing Angular CLI - Awesome Tool to Create Angular Projects](https://youtu.be/e9JhAwtW9Hk) - [Using Angular CLI to Create and Launch an Angular Application](https://youtu.be/0PlPY0wlNaw) - [Importing Angular App into Visual Studio Code](https://youtu.be/rMZNsb685r4) - [Angular Project Structure](https://youtu.be/ZOq9S8nSCF0) - [Generating an Angular Component with `ng generate`](https://youtu.be/8YC-4u3jm94) --- ### 🔹 React + Spring Boot - [Full Stack Application Architecture - Spring Boot and React](https://youtu.be/TTWH_Q7uSlY) - [Create React App - Create and Launch a React Application](https://youtu.be/PR1pXhesetg) - [Importing React App into Visual Studio Code](https://youtu.be/Cw-bSD6Q8xI) - [React Project Structure](https://youtu.be/wI5G8FNFrto) - [React Components](https://youtu.be/OmwcVGZWM98) ## STEP 1 : TODO ## Step N : Executing the TODO Service Here’s how you can run this **GET service** in **Postman**—my favorite tool for testing REST APIs (see image below). ![Image](/images/ExecutingGetRestServiceUsingPostman.png "Executing Rest Service From Postman") ## Executing a POST Rest Service Here’s an example request you can try out: ```json ``` The image below demonstrates how to execute this **POST service** using **Postman**, a widely used tool for testing REST APIs. Steps: 1. Open the **Body** tab and select **raw**. 2. From the dropdown menu, choose **JSON**. 3. Paste the example request into the body. ![Image](/images/ExecutingPostRestServiceUsingPostman.png "Executing Post Rest Service From Postman") ## Complete Code Example - TODO ================================================ FILE: _blog/articles/2016-01-01-article-template.md ================================================ --- layout: post title: TODO date: 2025-03-09 12:31:19 summary: TODO categories: SpringBootMicroservices permalink: /url --- This guide will help you create a TODO***. ## You will learn - What? - Why? - How? - Where? - When? ## Resources/URLs/Entities Overview In this guide, we will create three services using proper URIs and HTTP methods: ## Project Code Structure Following screenshot shows the structure of the project we will create. ![Image](/images/TODO.png "TODO-DESC") A few details: - SpringBootTutorialBasicsApplication.java - The Spring Boot Application class generated with Spring Initializer. This class acts as the launching point for application. - `pom.xml` - Contains all the dependencies needed to build this project. We will use Spring Boot Starter AOP. ## Tools you will need - Maven 3.0+ is your build tool - Your favorite IDE. We use IntelliJ, Eclipse. - JDK 17+ ## Complete Maven Project With Code Examples > Our GitHub repository has all the code examples - https://github.com/in28minutes/spring-boot-examples/tree/master/TODO_URL ## Article Begins Some theory ## Bootstrapping with Spring Initializr Creating a REST service with **Spring Initializr** is quick and efficient. In this example, we will use **Spring Web MVC** as our web framework. The [Spring Initializr](http://start.spring.io/) provides an excellent way to bootstrap Spring Boot projects, enabling developers to generate a fully functional application setup in just a few steps. ![Image](/images/Spring-Initializr-Web.png "Web, Actuator and Developer Tools") ![Image](/images/Spring-Initializr-Web-JPA.png "Web, JPA, Hibernate and Developer Tools") As illustrated in the image above, the following steps need to be performed: - Launch **Spring Initializr** and configure the project: - Set **Group** as `TODO` - Set **Artifact** as `TODO` - Add the following dependencies: - Spring Web - Spring Boot DevTools - `TODO` - Click **Generate Project** to download the starter zip. - Import the project into your IDE (Eclipse or IntelliJ IDEA): - `File` → `Import` → `Existing Maven Project` - To explore and understand all the files included in this project, refer to: `TODO` ## STEP 1 : TODO ## Step N : Executing the TODO Service The image below demonstrates how to execute this **GET service** using **Postman**, a popular tool for testing REST APIs. ![Image](/images/ExecutingGetRestServiceUsingPostman.png "Executing Rest Service From Postman") ## Executing a POST Rest Service An example request is shown below: ```json ``` The image below demonstrates how to execute this **POST service** using **Postman**, a popular tool for testing REST APIs. Make sure to: - Go to the **Body** tab and select **raw**. - Choose **JSON** from the dropdown menu. - Copy the above request into the request body. ![Image](/images/ExecutingPostRestServiceUsingPostman.png "Executing Post Rest Service From Postman") ## Complete Code Example - TODO ================================================ FILE: _blog/articles/2017-01-17-spring-boot-basic-rest-service-top20.md ================================================ --- layout: post title: Creating a REST Service with Spring Boot date: 2025-03-09 07:14:13 summary: Setting up a basic example REST Service with Spring Boot. Its a cake walk. categories: SpringBoot permalink: /creating-rest-service-with-spring-boot image: /images/rest-api-category.png --- ![Image](/images/ExecutingPostRestServiceUsingPostman.png "'Executing Post Rest Service From Postman'") In this guide, you’ll learn how to build a simple **REST service** with **Spring Boot**. ![Image](/images/SpringBootRestService-ProjectStructure.png 'Spring Boot Rest Service - Project Structure') ## You will learn - **What is a REST Service?** - **How to bootstrap a REST service application with Spring Initializr?** - **How to create a GET REST service** for retrieving the courses that a student is registered for? - **How to create a POST REST service** for registering a course for a student? - **How to execute REST services using Postman?** ## Rest Services in this Guide In this guide, we will create three services using proper URIs and HTTP methods: - **`@GetMapping("/students/{studentId}/courses")`** Retrieve all the courses a specific student has registered for. - **HTTP Method:** GET - **Example URI:** `/students/Student1/courses` - **`@GetMapping("/students/{studentId}/courses/{courseId}")`** Retrieve details of a specific course for a specific student. - **HTTP Method:** GET - **Example URI:** `/students/Student1/courses/Course1` - **`@PostMapping("/students/{studentId}/courses")`** Register a student for a new course. - **HTTP Method:** POST - **Example URI:** `/students/Student1/courses` ## Tools You Will Need - **Maven 3.0+** – Build tool for managing dependencies and building the project - **IDE of your choice** – We recommend *Eclipse* or *IntelliJ IDEA* - **JDK 17+** – Required to run the Spring Boot application ## Complete Maven Project with Code Examples You can find the complete project with code samples in our GitHub repository: 👉 [Browse Code Examples](https://github.com/in28minutes/in28minutes.github.io/tree/master/code-zip-files) ### Available Project - **REST Services with Unit and Integration Tests** Download: `Website-springbootrestservices-simplerestserviceswithunitandintegrationtests.zip` ## What is REST? REST stands for **REpresentational State Transfer**. It is an architectural style that defines a set of constraints for building scalable web services. Any service following these rules is called a **RESTful Service**. ### Key Constraints of REST - **Client–Server**: Clear separation between the service provider (server) and the consumer (client). - **Uniform Interface**: Resources are identified using URIs (e.g., `/students/1/courses`). - **Stateless**: Each request is independent; the server does not store client state. - **Cacheable**: Responses can be cached (e.g., using HTTP caching). - **Layered System**: Clients don’t need to know if they are talking directly to the server or through intermediaries ( like caches, proxies, or load balancers). ## Richardson Maturity Model The **Richardson Maturity Model (RMM)** helps identify how mature a RESTful Web Service is, based on how well it follows REST principles. It defines four levels (0–3): - **Level 0: The Swamp of POX** - REST in name only — action-based URIs. - Example: - `http://server/getPosts` - `http://server/deletePosts` - `http://server/doThis` - **Level 1: Resources** - Use of resource-based URIs (nouns instead of actions). - Still missing proper use of HTTP methods. - Example: - `http://server/accounts` - `http://server/accounts/10` - **Level 2: HTTP Verbs** - Combine resources with proper HTTP methods (GET, POST, PUT, DELETE). - Example: - `GET /accounts/10` → Retrieve account - `POST /accounts` → Create account - `PUT /accounts/10` → Update account - `DELETE /accounts/10` → Delete account - URIs can look like: - `/posts/1/comments/5` - `/accounts/1/friends/1` - **Level 3: HATEOAS (Hypermedia as the Engine of Application State)** - Responses include not just data, but also links to possible next actions. - Example (Facebook user resource): - Returns user details **plus links** for: - Recent posts - Recent comments - Friend list ## Using Appropriate Request Methods When designing RESTful APIs, always use the correct **HTTP methods** for clarity and consistency. Best practices for each method: - **GET** - Purpose: Retrieve data (read-only). - Should not update anything. - Should be **idempotent** (multiple identical requests return the same result). - Possible Response Codes: - `200 OK` → Success - `404 Not Found` → Resource not found - `400 Bad Request` → Invalid request - **POST** - Purpose: Create a **new resource**. - Response should ideally include JSON with a link to the newly created resource. - Possible Response Codes: - `200 OK` → Success (less common) - `201 Created` → Resource successfully created - `400 Bad Request` → Invalid input - **PUT** - Purpose: Update an **existing known resource**. - Example: Update client details. - Possible Response Codes: - `200 OK` → Successfully updated - `404 Not Found` → Resource not found - **DELETE** - Purpose: Delete a resource. - Possible Response Codes: - `200 OK` → Successfully deleted - `404 Not Found` → Resource not found ## Project Structure The following screenshot shows the structure of the project we will create: ![Image](/images/SpringBootRestService-ProjectStructure.png 'Spring Boot Rest Service - Project Structure') ### A Few Details - **`StudentController.java`** – REST controller exposing the three service methods discussed earlier. - **`Course.java`, `Student.java`, `StudentService.java`** – Business logic for the application. `StudentService` provides methods consumed by the REST controller. - **`StudentControllerIT.java`** – Integration tests for the REST services. - **`StudentControllerTest.java`** – Unit tests for the REST services. - **`StudentServicesApplication.java`** – Launcher for the Spring Boot application. Run this file as a Java Application to start the service. - **`pom.xml`** – Maven build file containing all dependencies. We use **Spring Boot Starter Web** here. ## Bootstrapping Spring Boot REST API with Spring Initializr Creating a REST service with **Spring Initializr** is very simple. We will use **Spring Web MVC** as our web framework. [Spring Initializr](http://start.spring.io/) is a great tool to quickly bootstrap your Spring Boot projects. ![Image](/images/Spring-Initializr-Web.png 'Web, Actuator and Developer Tools') As shown in the image above, follow these steps: - Launch **Spring Initializr** and choose the following: - **Group**: `com.in28minutes.springboot` - **Artifact**: `student-services` - **Dependencies**: - Spring Web - Spring Boot Actuator - Spring Boot DevTools - Click **Generate Project**. - Import the project into **Eclipse**: `File -> Import -> Existing Maven Project` - If you want to explore all the files that are part of this project, you can go here: [Project Files](#) ## Implementing Business Service for Your Application Every application needs data. Instead of connecting to a real database, we will use an `ArrayList` as an **in-memory data store**. ### Domain Model - A **Student** can register for multiple **Courses**. - A **Course** has: - `id` - `name` - `description` - a list of steps to complete the course - A **Student** has: - `id` - `name` - `description` - a list of courses they are currently registered for ### StudentService Methods The `StudentService` provides the following methods: - `public List retrieveAllStudents()` → Retrieve details of all students - `public Student retrieveStudent(String studentId)` → Retrieve details of a specific student - `public List retrieveCourses(String studentId)` → Retrieve all courses for a student - `public Course retrieveCourse(String studentId, String courseId)` → Retrieve details of a specific course for a student - `public Course addCourse(String studentId, Course course)` → Add a new course for a student ### Reference Implementation Check the exact implementation of the `StudentService` and model classes in the following files: - `src/main/java/com/in28minutes/springboot/model/Course.java` - `src/main/java/com/in28minutes/springboot/model/Student.java` - `src/main/java/com/in28minutes/springboot/service/StudentService.java` ## Adding a Couple of GET REST Services The `StudentController` exposes two GET services: ```java private final StudentService studentService; public StudentController(StudentService studentService) { this.studentService = studentService; } ``` - Uses Spring **Dependency Injection** to wire the `StudentService` into the controller. - `@GetMapping("/students/{studentId}/courses")` Exposes a GET service to retrieve all courses for a given student, where `studentId` is provided as a path variable. - `@GetMapping("/students/{studentId}/courses/{courseId}")` Exposes a GET service to retrieve details of a **specific course** for a given student. - `@PathVariable String studentId` The `studentId` from the URI is automatically mapped to this parameter in the controller method. ```java package com.in28minutes.springboot.controller; import com.in28minutes.springboot.model.Course; import com.in28minutes.springboot.service.StudentService; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import java.net.URI; import java.util.List; @RestController @RequestMapping("/students/{studentId}/courses") public class StudentController { private final StudentService studentService; public StudentController(StudentService studentService) { this.studentService = studentService; } @GetMapping() public List retrieveCoursesForStudent(@PathVariable String studentId) { return studentService.retrieveCourses(studentId); } @GetMapping("/{courseId}") public Course retrieveDetailsForCourse( @PathVariable String studentId, @PathVariable String courseId) { return studentService.retrieveCourse(studentId, courseId); } } ``` ## Executing the Http Get Operation Using Postman We will access a request to http://localhost:8080/students/Student1/courses/Course1 to test the service. And will receive the following response shown in the below. ```json { "id": "Course1", "name": "Spring", "description": "10 Steps", "steps": [ "Learn Maven", "Import Project", "First Example", "Second Example" ] } ``` The screenshot below shows how you can execute this **GET service** in **Postman** — my favorite tool for testing REST APIs. ![Image](/images/ExecutingGetRestServiceUsingPostman.png 'Executing Rest Service From Postman') ## Adding an HTTP POST Operation REST Service An **HTTP POST** operation should return a **201 (Created)** status when the resource is successfully created. Key elements in our implementation: - `@PostMapping("/students/{studentId}/courses")` Maps the URI for handling **POST requests**. - `@RequestBody Course newCourse` Binds the request body to a `Course` object. - `ResponseEntity.created(location).build()` Returns a **201 Created** response along with the **Location** header pointing to the newly created resource. ```java @PostMapping() public ResponseEntity registerStudentForCourse(@PathVariable String studentId, @RequestBody Course newCourse) { var course = studentService.addCourse(studentId, newCourse); if (course == null) return ResponseEntity.noContent().build(); URI location = ServletUriComponentsBuilder.fromCurrentRequest() .path("/{id}") .buildAndExpand(course.id()) .toUri(); return ResponseEntity.created(location) .build(); } ``` ## Executing a Http POST Operation Rest Service The example request below demonstrates how to register a new course for a student. It includes all the required course details in the request body. ```json { "name": "Microservices", "description": "10 Steps", "steps": [ "Learn How to Break Things Up", "Automate the hell out of everything", "Have fun" ] } ``` The screenshot below shows how to execute this **POST operation** in **Postman** — my favorite tool for testing REST services. Make sure to: - Go to the **Body** tab. - Select **raw**. - Choose **JSON** from the dropdown. - Copy the request JSON (shown above) into the body. The URL we use is http://localhost:8080/students/Student1/courses. ![Image](/images/ExecutingPostRestServiceUsingPostman.png 'Executing Post Rest Service From Postman') ## Complete Code Example Our GitHub repository has all the code examples - [https://github.com/in28minutes/spring-boot-examples/tree/master/spring-boot-rest-services-with-unit-and-integration-tests](https://github.com/in28minutes/spring-boot-examples/tree/master/spring-boot-rest-services-with-unit-and-integration-tests) ================================================ FILE: _blog/articles/2017-01-21-spring-initializr-web-application.md ================================================ --- layout: post title: Spring Initializr - Bootstrap Your Spring Boot Applications at F1 speed! date: 2025-09-06 06:14:13 summary: Discover what Spring Initializr is and how to rapidly Bootstrap a Spring Boot Web Application. categories: SpringBoot permalink: /spring-initialzr-bootstrap-spring-boot-applications image: /images/spring-boot-category.png --- ![Image](/images/Spring-Initializr-Web.png 'Web, Actuator and Developer Tools') [Spring Initializr](http://start.spring.io/) is a great tool to quickly bootstrap your Spring Boot projects. ![Image](/images/Spring-Initializr-Web-ApplicationStructure.png 'Spring Initializr Web Application - Folder Structure') It enables you to construct a wide range of **Spring Boot-based applications** using a simple user interface. With Spring Initializr, you can bootstrap applications such as: - Web Applications - RESTful Applications - Batch Applications Spring Boot provides a diverse set of starter projects, and Spring Initializr is compatible with all of them (and more). Some commonly used starters include: - `spring-boot-starter-web-services` – Build applications exposing **SOAP Web Services** - `spring-boot-starter-web` – Build **Web applications** & **RESTful services** - `spring-boot-starter-test` – Write Unit and Integration Tests - `spring-boot-starter-jdbc` – Build traditional **JDBC applications** - `spring-boot-starter-hateoas` – Add **HATEOAS** features to make your services more RESTful - `spring-boot-starter-security` – Implement **authentication and authorization** using Spring Security - `spring-boot-starter-data-jpa` – Use **Spring Data JPA with Hibernate** - `spring-boot-starter-cache` – Enable caching support in your applications - `spring-boot-starter-data-rest` – Quickly expose simple REST services using Spring Data REST --- 👉 In this guide, we will focus on creating a **simple web application** with **Spring Initializr**. ## Bootstrapping a Web Application with Spring Initializr Creating a web application with **Spring Initializr** is straightforward and fast. With just a few clicks, you can generate a fully working Spring Boot project and import it into your IDE. ![Image](/images/Spring-Initializr-Web.png 'Web, Actuator and Developer Tools') As shown in the image above, follow these steps: - Launch **Spring Initializr** [http://start.spring.io/](http://start.spring.io/) and choose the following: - **Group**: `com.in28minutes.springboot` - **Artifact**: `student-services` - **Dependencies**: - Spring Web - Spring Boot Actuator - Spring Boot DevTools - Click the **Generate Project** button at the bottom of the page. - Import the project into **Eclipse** or **IntelliJ IDEA**. ## Project Structure Established After importing the Maven project, the following project structure is created (as shown in the screenshot). ![Image](/images/Spring-Initializr-Web-ApplicationStructure.png "'Spring Initializr Web Application - Folder Structure'") ### Key Project Files - **StudentServicesApplication.java** – The main launcher class for Spring Boot. It initializes Auto Configuration and the Spring Application Context. - **application.properties** – Central configuration file for the application. - **StudentServicesApplicationTests.java** – Basic test launcher for running unit tests. - **pom.xml** – Declares project dependencies such as Spring Boot Starter Web, Actuator, and DevTools. It also uses the Spring Boot Starter Parent as the parent POM. ## Completely Created Code When the project is generated, the following key files are included. ### /pom.xml The `pom.xml` is the backbone of the project, managing dependencies and build configuration. Three important configurations are included: - **Spring Boot Parent POM** – Provides default configuration for dependency versions and plugins. 👉 [Learn more](http://www.springboottutorial.com/spring-boot-starter-parent) - **Spring Boot Starter Web** – Adds support for building web applications and RESTful services. 👉 [Learn more](http://www.springboottutorial.com/spring-boot-starter-projects) - **Spring Boot Maven Plugin** – Simplifies building and running Spring Boot applications directly from Maven. ```xml 4.0.0 org.springframework.boot spring-boot-starter-parent 4.0.0-M2 com.in28minutes.springboot student-services 0.0.1-SNAPSHOT student-services Demo project for Spring Boot 21 org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-devtools runtime true org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin ``` --- ### /src/main/java/com/in28minutes/springboot/StudentServicesApplication.java This is the **main entry point** of the Spring Boot application. - **`@SpringBootApplication`** – A convenience annotation that enables: - Auto Configuration - Component Scanning - Configuration support 👉 [Learn more about Auto Configuration](http://www.springboottutorial.com/spring-boot-auto-configuration) - Signifies that this is a Spring Boot application - It is a composite annotation that combines the following annotations - `@SpringBootConfiguration` + `@EnableAutoConfiguration` + `@ComponentScanning` - **`SpringApplication.run(...)`** – A static method to bootstrap and launch the Spring Boot application. ```java package com.in28minutes.springboot.studentservices; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class StudentServicesApplication { public static void main(String[] args) { SpringApplication.run(StudentServicesApplication.class, args); } } ``` --- ### /src/main/resources/application.properties ``` ``` --- ### /src/test/java/com/in28minutes/springboot/StudentServicesApplicationTests.java This is the **default test class** generated by Spring Initializr. - It uses **Spring Boot Test support** to start the entire application context. - Provides a simple way to verify that the Spring Boot application loads successfully. - Serves as a good starting point to add **integration tests** for your services and controllers. 👉 [Learn more about Integration Testing in Spring Boot](http://www.springboottutorial.com/integration-testing-for-spring-boot-rest-services) ```java package com.in28minutes.springboot.student_services; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class StudentServicesApplicationTests { @Test void contextLoads() { } } ``` --- ## Running the application When you execute StudentServicesApplication.java as a Java application, the following log is generated. ``` /Users/puneethsai/Library/Java/JavaVirtualMachines/corretto-21.0.7/Contents/Home/bin/java -XX:TieredStopAtLevel=1 -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:/Users/puneethsai/Applications/IntelliJ IDEA Ultimate.app/Contents/lib/idea_rt.jar=58604 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath /Users/puneethsai/Downloads/student-services/target/classes:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-starter-actuator/4.0.0-M2/spring-boot-starter-actuator-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-starter/4.0.0-M2/spring-boot-starter-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-starter-logging/4.0.0-M2/spring-boot-starter-logging-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/ch/qos/logback/logback-classic/1.5.18/logback-classic-1.5.18.jar:/Users/puneethsai/.m2/repository/ch/qos/logback/logback-core/1.5.18/logback-core-1.5.18.jar:/Users/puneethsai/.m2/repository/org/apache/logging/log4j/log4j-to-slf4j/2.24.3/log4j-to-slf4j-2.24.3.jar:/Users/puneethsai/.m2/repository/org/apache/logging/log4j/log4j-api/2.24.3/log4j-api-2.24.3.jar:/Users/puneethsai/.m2/repository/org/slf4j/jul-to-slf4j/2.0.17/jul-to-slf4j-2.0.17.jar:/Users/puneethsai/.m2/repository/jakarta/annotation/jakarta.annotation-api/3.0.0/jakarta.annotation-api-3.0.0.jar:/Users/puneethsai/.m2/repository/org/yaml/snakeyaml/2.4/snakeyaml-2.4.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-actuator-autoconfigure/4.0.0-M2/spring-boot-actuator-autoconfigure-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-actuator/4.0.0-M2/spring-boot-actuator-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.20.0-rc1/jackson-databind-2.20.0-rc1.jar:/Users/puneethsai/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.20-rc1/jackson-annotations-2.20-rc1.jar:/Users/puneethsai/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.20.0-rc1/jackson-core-2.20.0-rc1.jar:/Users/puneethsai/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.20.0-rc1/jackson-datatype-jsr310-2.20.0-rc1.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-health/4.0.0-M2/spring-boot-health-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-micrometer-metrics/4.0.0-M2/spring-boot-micrometer-metrics-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-micrometer-observation/4.0.0-M2/spring-boot-micrometer-observation-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/io/micrometer/micrometer-core/1.16.0-M2/micrometer-core-1.16.0-M2.jar:/Users/puneethsai/.m2/repository/org/hdrhistogram/HdrHistogram/2.2.2/HdrHistogram-2.2.2.jar:/Users/puneethsai/.m2/repository/org/latencyutils/LatencyUtils/2.0.3/LatencyUtils-2.0.3.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-micrometer-tracing/4.0.0-M2/spring-boot-micrometer-tracing-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/io/micrometer/micrometer-tracing/1.6.0-M2/micrometer-tracing-1.6.0-M2.jar:/Users/puneethsai/.m2/repository/io/micrometer/context-propagation/1.2.0-M1/context-propagation-1.2.0-M1.jar:/Users/puneethsai/.m2/repository/io/micrometer/micrometer-observation/1.16.0-M2/micrometer-observation-1.16.0-M2.jar:/Users/puneethsai/.m2/repository/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar:/Users/puneethsai/.m2/repository/io/micrometer/micrometer-commons/1.16.0-M2/micrometer-commons-1.16.0-M2.jar:/Users/puneethsai/.m2/repository/io/micrometer/micrometer-jakarta9/1.16.0-M2/micrometer-jakarta9-1.16.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-starter-web/4.0.0-M2/spring-boot-starter-web-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-starter-jackson/4.0.0-M2/spring-boot-starter-jackson-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-jackson/4.0.0-M2/spring-boot-jackson-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.20.0-rc1/jackson-datatype-jdk8-2.20.0-rc1.jar:/Users/puneethsai/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.20.0-rc1/jackson-module-parameter-names-2.20.0-rc1.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-starter-tomcat/4.0.0-M2/spring-boot-starter-tomcat-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-tomcat/4.0.0-M2/spring-boot-tomcat-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-web-server/4.0.0-M2/spring-boot-web-server-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/11.0.10/tomcat-embed-core-11.0.10.jar:/Users/puneethsai/.m2/repository/org/apache/tomcat/embed/tomcat-embed-el/11.0.10/tomcat-embed-el-11.0.10.jar:/Users/puneethsai/.m2/repository/org/apache/tomcat/embed/tomcat-embed-websocket/11.0.10/tomcat-embed-websocket-11.0.10.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-http-converter/4.0.0-M2/spring-boot-http-converter-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/spring-web/7.0.0-M8/spring-web-7.0.0-M8.jar:/Users/puneethsai/.m2/repository/org/springframework/spring-beans/7.0.0-M8/spring-beans-7.0.0-M8.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-webmvc/4.0.0-M2/spring-boot-webmvc-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-servlet/4.0.0-M2/spring-boot-servlet-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/spring-webmvc/7.0.0-M8/spring-webmvc-7.0.0-M8.jar:/Users/puneethsai/.m2/repository/org/springframework/spring-aop/7.0.0-M8/spring-aop-7.0.0-M8.jar:/Users/puneethsai/.m2/repository/org/springframework/spring-expression/7.0.0-M8/spring-expression-7.0.0-M8.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-devtools/4.0.0-M2/spring-boot-devtools-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot/4.0.0-M2/spring-boot-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/springframework/spring-context/7.0.0-M8/spring-context-7.0.0-M8.jar:/Users/puneethsai/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/4.0.0-M2/spring-boot-autoconfigure-4.0.0-M2.jar:/Users/puneethsai/.m2/repository/org/slf4j/slf4j-api/2.0.17/slf4j-api-2.0.17.jar:/Users/puneethsai/.m2/repository/org/springframework/spring-core/7.0.0-M8/spring-core-7.0.0-M8.jar:/Users/puneethsai/.m2/repository/commons-logging/commons-logging/1.3.5/commons-logging-1.3.5.jar com.in28minutes.springboot.student_services.StudentServicesApplication . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v4.0.0-M2) 2025-09-06T16:17:54.722+05:30 INFO 13610 --- [student-services] [ restartedMain] [ ] c.i.s.s.StudentServicesApplication : Starting StudentServicesApplication using Java 21.0.7 with PID 13610 (/Users/puneethsai/Downloads/student-services/target/classes started by puneethsai in /Users/puneethsai/Downloads/student-services) 2025-09-06T16:17:54.728+05:30 INFO 13610 --- [student-services] [ restartedMain] [ ] c.i.s.s.StudentServicesApplication : No active profile set, falling back to 1 default profile: "default" 2025-09-06T16:17:54.792+05:30 INFO 13610 --- [student-services] [ restartedMain] [ ] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable 2025-09-06T16:17:54.793+05:30 INFO 13610 --- [student-services] [ restartedMain] [ ] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' 2025-09-06T16:17:55.942+05:30 INFO 13610 --- [student-services] [ restartedMain] [ ] o.s.boot.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http) 2025-09-06T16:17:55.958+05:30 INFO 13610 --- [student-services] [ restartedMain] [ ] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2025-09-06T16:17:55.959+05:30 INFO 13610 --- [student-services] [ restartedMain] [ ] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/11.0.10] 2025-09-06T16:17:55.993+05:30 INFO 13610 --- [student-services] [ restartedMain] [ ] b.w.c.s.WebApplicationContextInitializer : Root WebApplicationContext: initialization completed in 1200 ms 2025-09-06T16:17:56.617+05:30 INFO 13610 --- [student-services] [ restartedMain] [ ] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 2025-09-06T16:17:56.658+05:30 INFO 13610 --- [student-services] [ restartedMain] [ ] o.s.b.a.e.web.EndpointLinksResolver : Exposing 1 endpoint beneath base path '/actuator' 2025-09-06T16:17:56.720+05:30 INFO 13610 --- [student-services] [ restartedMain] [ ] o.s.boot.tomcat.TomcatWebServer : Tomcat started on port 8080 (http) with context path '/' 2025-09-06T16:17:56.729+05:30 INFO 13610 --- [student-services] [ restartedMain] [ ] c.i.s.s.StudentServicesApplication : Started StudentServicesApplication in 2.524 seconds (process running for 3.535) 2025-09-06T16:17:58.404+05:30 INFO 13610 --- [student-services] [on(3)-127.0.0.1] [ ] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' 2025-09-06T16:17:58.405+05:30 INFO 13610 --- [student-services] [on(3)-127.0.0.1] [ ] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' 2025-09-06T16:17:58.407+05:30 INFO 13610 --- [student-services] [on(3)-127.0.0.1] [ ] o.s.web.servlet.DispatcherServlet : Completed initialization in 2 ms ``` ================================================ FILE: _blog/articles/2017-01-28-spring-boot-unit-testing-with-junit-top20.md ================================================ --- layout: post title: Unit Testing Rest Services with Spring Boot and JUnit date: 2025-09-06 12:31:19 summary: It's a piece of cake to set up a basic REST service with Spring Boot. We'll take it a step further and add excellent unit tests to our RESTful Service. categories: SpringBootUnitTesting permalink: /unit-testing-for-spring-boot-rest-services image: /images/unit-test-category.png --- This article will guide you through writing **effective unit tests** for your Spring Boot REST services. To keep things simple and practical, we’ll start by creating a few basic REST endpoints using a sample Spring Boot project. Once the services are ready, we’ll explore how to write **clean, reliable unit tests** for them. ![Image](/images/SpringBootRestService-ProjectStructure.png "Spring Boot Rest Services - Project Structure") ## You will learn - What Unit Testing is and why it matters - How to create a **GET REST Service** to retrieve the courses registered by a student - How to write a **Unit Test** for the GET REST Service - How to create a **POST REST Service** to register a course for a student - How to write a **Unit Test** for the POST REST Service ## Tools you will need - **Maven 3.0+** – Build and dependency management tool - **An IDE of your choice** – Eclipse, IntelliJ IDEA, or any other Java IDE - **JDK 17+** – Java Development Kit to compile and run the application ## Complete Maven Project With Code Examples You can find all the code examples in our GitHub repository: [https://github.com/in28minutes/in28minutes.github.io/tree/master/code-zip-files](https://github.com/in28minutes/in28minutes.github.io/tree/master/code-zip-files) - **REST Services with Unit and Integration Tests** 👉 Download: `Website-springbootrestservices-simplerestserviceswithunitandintegrationtests.zip` ## Unit Testing The following screenshot shows the Eclipse project structure with all the files we will create as part of this tutorial. We will cover: - Writing a simple **GET REST Service** and its **unit test** - Writing a **POST REST Service** and its **unit test** ![Image](/images/SpringBootRestService-ProjectStructure.png "Spring Boot Rest Services - Project Structure") ## Writing Unit Tests for `StudentController` The `StudentController` exposes two service methods — **GET** and **POST**. We will create unit tests for both of these methods. In the unit tests: - The `StudentService` dependency will be **mocked using Mockito**. - We will use the **MockMvc** framework to launch only the `StudentController`. ⚡ Key Principle: A critical aspect of unit testing is **limiting the scope**. Here, we only want to test the logic inside `StudentController`, without involving the actual `StudentService` implementation or other layers. ## Overview In this guide, we will walk through the process of building and testing a simple Spring Boot REST API. The steps we will follow are: 1. **Bootstrap the Project** Use **Spring Initializr** to quickly set up the base project. 2. **Implement the Business Service** Create the `StudentService` class to provide business logic for our API. 3. **Build the REST API** Develop the `StudentController`: - First, implement the **GET endpoints**. - Then, implement the **POST endpoint**. 4. **Write Unit Tests** Use **Mockito** and **MockMvc** to unit test the `StudentController`. ## Bootstrap REST Services Application with Spring Initializr > [Spring Initializr](http://start.spring.io/) is an excellent tool for bootstrapping Spring Boot projects with just a few clicks. With Spring Initializr, you can quickly generate a project structure by selecting: - **Group**: `com.in28minutes.springboot` - **Artifact**: `student-services` - **Dependencies**: - Spring Web - Spring Boot Actuator - Spring Boot DevTools Once generated, download the project, unzip it, and import it into your favorite IDE (Eclipse, IntelliJ, or VS Code). ![Image](/images/Spring-Initializr-Web.png "Web, Actuator and Developer Tools") As shown in the image above, follow these steps to create your project: - Launch **Spring Initializr** and choose the following: - **Group**: `com.in28minutes.springboot` - **Artifact**: `student-services` - **Dependencies**: - Spring Web - Spring Boot Actuator - Spring Boot DevTools - Click **Generate Project** to download the starter project. - Import the project into Eclipse (**File → Import → Existing Maven Project**). - To explore and understand all the files generated by Spring Initializr, you can refer [here](#). ## Adding Business Services to Your Application Every application needs data. In this example, instead of connecting to a real database, we’ll use an `ArrayList` as an in-memory data store. - A **student** can enroll in multiple **courses**. - A **course** has an `id`, `name`, `description`, and a list of `steps` to complete the course. - A **student** has an `id`, `name`, `description`, and a list of registered courses. We’ll implement a `StudentService` that provides the following methods: - `public List retrieveAllStudents()` – Retrieve details for all students - `public Student retrieveStudent(String studentId)` – Retrieve details of a specific student - `public List retrieveCourses(String studentId)` – Retrieve all courses a student is registered for - `public Course retrieveCourse(String studentId, String courseId)` – Retrieve a specific course for a student - `public Course addCourse(String studentId, Course course)` – Add a new course for an existing student You can find the actual implementation of the service and models in these files: - `src/main/java/com/in28minutes/springboot/model/Course.java` - `src/main/java/com/in28minutes/springboot/model/Student.java` - `src/main/java/com/in28minutes/springboot/service/StudentService.java` --- ## Adding a Couple of GET Operations The `StudentController` exposes two GET REST endpoints: ```java private final StudentService studentService; public StudentController(StudentService studentService) { this.studentService = studentService; } ``` - Uses Spring **Dependency Injection** to wire the `StudentService` into the controller. - `@GetMapping("/students/{studentId}/courses")` – Retrieves all courses for a given student (`studentId` is passed as a path variable). - `@GetMapping("/students/{studentId}/courses/{courseId}")` – Retrieves details of a specific course (`courseId`) for a student. - `@PathVariable String studentId` – Maps the value of `studentId` from the URI to this parameter. ```java package com.in28minutes.springboot.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import com.in28minutes.springboot.model.Course; import com.in28minutes.springboot.service.StudentService; @RestController public class StudentController { private final StudentService studentService; public StudentController(StudentService studentService) { this.studentService = studentService; } @GetMapping("/students/{studentId}/courses") public List retrieveCoursesForStudent(@PathVariable String studentId) { return studentService.retrieveCourses(studentId); } @GetMapping("/students/{studentId}/courses/{courseId}") public Course retrieveDetailsForCourse(@PathVariable String studentId, @PathVariable String courseId) { return studentService.retrieveCourse(studentId, courseId); } } ``` ## Executing the Http Get Operation Using Postman We will fire a request to http://localhost:8080/students/Student1/courses/Course1 to test the service. Response is as shown below. ```json { "id": "Course1", "name": "Spring", "description": "10Steps", "steps": [ "Learn Maven", "Import Project", "First Example", "Second Example" ] } ``` Below screenshot demonstrates how to execute this **GET** operation using Postman — a popular tool for testing RESTful services. ![Image](/images/ExecutingGetRestServiceUsingPostman.png "Executing Rest Service From Postman") ## Add spring-security-test for disabling security in unit tests ``` org.springframework.security spring-security-test test ``` ## Unit Testing Http Get Operation ## Unit Testing a Spring MVC Controller When unit testing a REST service, we want to **launch only the relevant controller** and the associated MVC components. The annotation `@WebMvcTest` is used for this purpose. It focuses the test exclusively on Spring MVC components. Using this annotation disables full auto-configuration and loads only the configuration relevant for MVC tests. Key components in our test setup: - `@ExtendWith(SpringExtension.class)` - Registers Spring extensions with JUnit 5. - Integrates the Spring TestContext Framework into JUnit Jupiter. - Supports annotated arguments in constructors, test methods, and lifecycle methods (`@BeforeAll`, `@BeforeEach`, `@AfterAll`, `@AfterEach`). - `@WebMvcTest(value = StudentController.class)` - Used to unit test Spring MVC components. - Launches only `StudentController` for testing. - No other controllers or mappings are started. - `@Autowired private MockMvc mockMvc` - Entry point for server-side Spring MVC test support. - Allows executing HTTP requests against the test context. - `@MockBean private StudentService studentService` - Mocks the `StudentService` and injects it into `StudentController`. - Ensures the unit test only focuses on controller behavior. - `Mockito.when(studentService.retrieveCourse(Mockito.anyString(), Mockito.anyString())).thenReturn(mockCourse)` - Mocks the behavior of `retrieveCourse()` to return a predefined `mockCourse`. - `MockMvcRequestBuilders.get("/students/Student1/courses/Course1").accept(MediaType.APPLICATION_JSON)` - Creates a GET request to the specified URI with an `Accept` header of `application/json`. - `mockMvc.perform(requestBuilder).andReturn()` - Executes the request using `MockMvc` and returns the response. - `JSONAssert.assertEquals(expected, result.getResponse().getContentAsString(), false)` - Uses `org.skyscreamer.jsonassert.JSONAssert` to assert JSON responses. - Passing `strict=false` allows partial checks without requiring all fields to match. ```java package com.in28minutes.springboot.controller; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Arrays; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.skyscreamer.jsonassert.JSONAssert; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.RequestBuilder; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import com.in28minutes.springboot.model.Course; import com.in28minutes.springboot.service.StudentService; @ExtendWith(SpringExtension.class) @WebMvcTest(value = StudentController.class) @WithMockUser public class StudentControllerTest { @Autowired private MockMvc mockMvc; @MockBean private StudentService studentService; Course mockCourse = new Course("Course1", "Spring", "10Steps", Arrays.asList("Learn Maven", "Import Project", "First Example", "Second Example")); String exampleCourseJson = "{\"name\":\"Spring\",\"description\":\"10Steps\",\"steps\":[\"Learn Maven\",\"Import Project\",\"First Example\",\"Second Example\"]}"; @Test public void retrieveDetailsForCourse() throws Exception { Mockito.when(studentService.retrieveCourse(Mockito.anyString(), Mockito.anyString())).thenReturn(mockCourse); RequestBuilder requestBuilder = MockMvcRequestBuilders.get( "/students/Student1/courses/Course1").accept( MediaType.APPLICATION_JSON); MvcResult result = mockMvc.perform(requestBuilder).andReturn(); System.out.println(result.getResponse()); String expected = "{\"id\":\"Course1\",\"name\":\"Spring\",\"description\":\"10 Steps\"}"; // {"id":"Course1","name":"Spring","description":"10 Steps, 25 Examples and 10K Students","steps":["Learn Maven","Import Project","First Example","Second Example"]} JSONAssert.assertEquals(expected, result.getResponse() .getContentAsString(), false); } } ``` ## Adding Http POST Operation ## Implementing a HTTP POST Operation An HTTP POST operation should return a **201 Created** status when the resource is successfully created. Key components of the POST implementation: - `@PostMapping("/students/{studentId}/courses")` Maps the URL to handle POST requests for adding a course to a student. - `@RequestBody Course newCourse` Binds the JSON body of the request to a `Course` object. - `ResponseEntity.created(location).build()` Returns a **201 Created** status and sets the **Location header** pointing to the URI of the newly created resource. Example: When adding a course to `Student1`, the POST request might look like: ```java @PostMapping("/students/{studentId}/courses") public ResponseEntity registerStudentForCourse( @PathVariable String studentId, @RequestBody Course newCourse) { Course course = studentService.addCourse(studentId, newCourse); if (course == null) return ResponseEntity.noContent().build(); URI location = ServletUriComponentsBuilder.fromCurrentRequest().path( "/{id}").buildAndExpand(course.getId()).toUri(); return ResponseEntity.created(location).build(); } ``` ## Executing the Http POST Operation An example request is shown below. It provides all of the information needed to enrol a student for a course. ```json { "name": "Microservices", "description": "10Steps", "steps": [ "Learn How to Break Things Up", "Automate the hell out of everything", "Have fun" ] } ``` ## Executing the HTTP POST Operation Using Postman The image below demonstrates how to perform this POST operation using Postman — my preferred tool for testing REST services. Steps to follow: 1. Go to the **Body** tab in Postman. 2. Select **raw**. 3. From the dropdown menu, choose **JSON**. 4. Copy and paste the JSON request (shown above) into the body. 5. Click **Send** to execute the POST request. If successful, the server will return a **201 Created** status along with the location of the newly created resource in the response headers. The URL we use is http://localhost:8080/students/Student1/courses. ![Image](/images/ExecutingPostRestServiceUsingPostman.png "Executing Post Rest Service From Postman") ## Writing Unit Test for the Http POST Operation ## Unit Testing the HTTP POST Operation In the unit test, we want to send a POST request to `/students/Student1/courses` and validate that: 1. The HTTP status returned is **201 Created**. 2. The **Location** header contains the URI of the newly created resource. Key components in the test: - `MockMvcRequestBuilders.post("/students/Student1/courses").accept(MediaType.APPLICATION_JSON)` Creates a POST request with an `Accept` header set to `application/json`. - `content(exampleCourseJson).contentType(MediaType.APPLICATION_JSON)` Sets the request body to `exampleCourseJson` and specifies the content type as JSON. - `assertEquals(HttpStatus.CREATED.value(), response.getStatus())` Verifies that the response status is **201 Created**. - `response.getHeader(HttpHeaders.LOCATION)` Retrieves the **Location** header from the response. You can then assert that it contains the URI of the newly created course. ```java @Test public void createStudentCourse() throws Exception { var mockCourse = new Course("1", "Smallest Number", "1", Arrays.asList("1", "2", "3", "4")); // studentService.addCourse to respond back with mockCourse Mockito.when(studentService.addCourse(Mockito.anyString(), Mockito.any(Course.class))).thenReturn(mockCourse); // Send course as body to /students/Student1/courses RequestBuilder requestBuilder = MockMvcRequestBuilders .post("/students/Student1/courses") .accept(MediaType.APPLICATION_JSON).content(exampleCourseJson) .contentType(MediaType.APPLICATION_JSON); MvcResult result = mockMvc.perform(requestBuilder).andReturn(); MockHttpServletResponse response = result.getResponse(); assertEquals(HttpStatus.CREATED.value(), response.getStatus()); assertEquals("http://localhost/students/Student1/courses/1", response.getHeader(HttpHeaders.LOCATION)); } ``` ================================================ FILE: _blog/articles/2017-01-29-spring-boot-autoconfiguration-top20.md ================================================ --- layout: post title: What is Spring Boot Auto Configuration? date: 2025-09-06 12:31:19 summary: Auto Configuration is the most important feature in Spring Boot. In this tutorial, we will learn important concepts about Auto Configuration with a couple of examples. categories: SpringBoot permalink: /spring-boot-auto-configuration image: /images/spring-framework-category.png --- ![Image](/images/Spring-Initializr-Web.png "Web, Actuator and Developer Tools") Through examples, this guide will help you understand **Spring Boot Auto Configuration**. We will create a few basic REST services using simple code samples. ![Image](/images/spring-boot-autoconfigure-jar.png "Spring Boot Auto Configure Jar") ## What You Will Learn - Why **Auto Configuration** is needed in Spring Boot - What **Auto Configuration** actually is - Examples of **Spring Boot Auto Configuration** in action - How **Auto Configuration** is implemented under the hood - Techniques to **debug Auto Configuration** ## Tools You Will Need - **Maven 3.0+** – Build tool for your Spring Boot project - **IDE** – Your favorite IDE; we recommend Eclipse or IntelliJ IDEA - **JDK 17+** – Java Development Kit for compiling and running the application ## Complete Maven Project with Code Examples > Our GitHub repository contains all the code examples: [https://github.com/in28minutes/in28minutes.github.io/tree/master/code-zip-files](https://github.com/in28minutes/in28minutes.github.io/tree/master/code-zip-files) - **Restful Web Services Examples** - `Website-springbootrestservices-all-examples.zip` ## Why Do We Need Spring Boot Auto Configuration? Spring-based applications often require extensive configuration. For example, in a typical Spring MVC application, you need to configure: - Component scanning - Dispatcher Servlet - View resolver - WebJars (for serving static content) - And other required beans and settings Spring Boot Auto Configuration helps reduce this boilerplate by automatically configuring many of these components for you. ```xml /WEB-INF/views/ .jsp ``` A typical configuration of a **Dispatcher Servlet** in a Spring web application is shown in the code snippet below. ```xml dispatcher org.springframework.web.servlet.DispatcherServlet contextConfigLocation /WEB-INF/todo-servlet.xml 1 dispatcher / ``` When using Hibernate/JPA, you need to configure a **data source**, an **EntityManagerFactory**, and a **transaction manager**, among other components. ```xml ``` The examples shown here are representative of typical Spring Framework setups or integrations with other frameworks. ## Spring Boot: Can We Think Differently? Spring Boot introduces a new approach to application development, simplifying configuration and reducing boilerplate code. > Can we make this smarter? For example, when a Spring MVC JAR is added to an application, can certain beans be **auto-configured automatically** without explicit setup by the developer? - Automatically configure a **Data Source** if the Hibernate JAR is present on the classpath. - Automatically configure a **Dispatcher Servlet** if the Spring MVC JAR is present on the classpath. There are provisions to **override the default autoconfiguration** when custom behavior is needed. > Spring Boot inspects: 1. The **frameworks present on the classpath** 2. The **current settings of the application** Based on these, Spring Boot provides the **necessary default configurations** to set up the application with the detected frameworks. This process is called **Auto Configuration**. To explore **Auto Configuration** in action, let's bootstrap a simple Spring Boot application using **Spring Initializr**. ## Creating a REST Services Application with Spring Initializr > **Spring Initializr** [http://start.spring.io/](http://start.spring.io/) is a powerful tool to quickly bootstrap your Spring Boot projects. ![Image](/images/Spring-Initializr-Web.png "Web, Actuator and Developer Tools") As shown in the image above, follow these steps to bootstrap your Spring Boot project: 1. Launch **Spring Initializr** and configure the project: - **Group**: `com.in28minutes.springboot` - **Artifact**: `student-services` - **Dependencies**: - Web - Actuator - DevTools 2. Click **Generate Project**. 3. Import the generated project into **Eclipse**. 4. To understand all the files included in this project, refer to the provided documentation. ### Spring Boot Auto Configuration in Action When you run `StudentServicesApplication.java` as a Java application, you will notice several important messages in the log that demonstrate Spring Boot's **auto-configuration** at work. ``` - **Mapping servlet**: `'dispatcherServlet'` is mapped to `/` - **Error mapping**: `{/error}` is mapped to the `BasicErrorController.error()` method - **WebJars mapping**: `/webjars/**` is mapped to the `ResourceHttpRequestHandler` for serving static resources ``` The log statements above are excellent examples of **Spring Boot Auto Configuration** in action. Spring Boot auto-detects that **Spring MVC** is on the classpath when you include **Spring Boot Starter Web** as a dependency. It automatically configures: - `dispatcherServlet` - A default error page - WebJars for serving static resources Similarly, when you add **Spring Boot Data JPA Starter**, Spring Boot Auto Configuration automatically sets up a **DataSource** and an **EntityManager**. ## Where is Spring Boot Auto Configuration Implemented? The JAR `spring-boot-autoconfigure.jar` contains all the autoconfiguration logic. It provides configuration for **MVC, Data, JMS**, and other Spring frameworks in a single place. ![Image](/images/spring-boot-autoconfigure-jar.png "Spring Boot Auto Configure Jar") /META-INF/spring.factories is another crucial file contained within spring-boot-autoconfigure.jar. This file contains a list of all the auto configuration classes that should be imported using the AutoConfigurationImportFilter and AutoConfigurationImportFilter keys, depending on the dependencies found on the classpath. ```properties # Auto Configuration Import Listeners org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\ org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener # Auto Configuration Import Filters org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\ org.springframework.boot.autoconfigure.condition.OnBeanCondition,\ org.springframework.boot.autoconfigure.condition.OnClassCondition,\ org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition ``` ### Example of Auto Configuration Let's take a look at **`DataSourceAutoConfiguration`**. Typically, all autoconfiguration classes check which classes are available on the classpath. If certain classes are present, Spring Boot enables the corresponding configuration automatically. Annotations such as: - `@ConditionalOnClass` - `@ConditionalOnMissingBean` help provide this conditional autoconfiguration behavior. `@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })` : This configuration is enabled only when these classes are available in the classpath. ``` @AutoConfiguration( before = {SqlInitializationAutoConfiguration.class} ) @ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class}) @ConditionalOnMissingBean( type = {"io.r2dbc.spi.ConnectionFactory"} ) @EnableConfigurationProperties({DataSourceProperties.class}) @Import({DataSourcePoolMetadataProvidersConfiguration.class}) public class DataSourceAutoConfiguration { ``` `@ConditionalOnMissingBean` : This bean is configured only if there is no other bean configured with the same name. ```java @Bean @ConditionalOnMissingBean public DataSourceInitializer dataSourceInitializer() { return new DataSourceInitializer(); } ``` An **embedded database** is configured only if no beans of type `DataSource.class` or `XADataSource.class` are already defined in the application context. ```java @Configuration(proxyBeanMethods = false) @Conditional({EmbeddedDatabaseCondition.class}) @ConditionalOnMissingBean({DataSource.class, XADataSource.class}) @Import({EmbeddedDataSourceConfiguration.class}) protected static class EmbeddedDatabaseConfiguration { protected EmbeddedDatabaseConfiguration() { } } ``` ## Debugging Auto Configuration There are two main ways to debug and get more information about Spring Boot auto-configuration: - **Enable debug logging** - **Use Spring Boot Actuator** ### Debug Logging You can enable debug logging by adding a property to `application.properties`. For example, the configuration below turns on **DEBUG** level logging for all classes in the `org.springframework` package and its subpackages: ```properties logging.level.org.springframework=DEBUG ``` When you restart the application, an **autoconfiguration report** will be printed in the logs. The report lists all autoconfiguration classes, separating **positive matches** from **negative matches**. It shows: - Why a particular bean was autoconfigured - Why certain beans were **not** autoconfigured ```log ========================= CONDITIONS EVALUATION REPORT ========================= Positive matches: ----------------- DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched: - @ConditionalOnClass found required class 'jakarta.servlet.ServletRegistration' (OnClassCondition) - Default DispatcherServlet did not find dispatcher servlet beans (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition) Negative matches: ----------------- ArtemisAutoConfiguration: Did not match: - @ConditionalOnClass did not find required class 'jakarta.jms.ConnectionFactory' (OnClassCondition) AopAutoConfiguration.ClassProxyingConfiguration: Did not match: - @ConditionalOnMissingClass found unwanted class 'org.aspectj.weaver.Advice' (OnClassCondition) ``` ### Spring Boot Actuator Another way to debug autoconfiguration is by adding **Spring Boot Actuator** to your project. We can also include **HAL Explorer** to simplify browsing and exploring actuator endpoints. ```xml org.springframework.boot spring-boot-starter-actuator org.springframework.data spring-data-rest-hal-explorer ``` HAL Explorer autoconfiguration [http://localhost:8080/actuator/conditions](http://localhost:8080/actuator/conditions) would show the details of all the beans which are autoconfigured and those which are not. ![Image](/images/spring-boot-auto-configuration-actuator-negative-matches.png "Negative Matches Spring Boot Auto Configuration") ![Image](/images/spring-boot-auto-configuration-actuator-positive-matches.png "Positive Matches Spring Boot Auto Configuration") ================================================ FILE: _blog/articles/2017-01-30-spring-boot-integration-testing.md ================================================ --- layout: post title: Writing Integration Tests for Rest Services with Spring Boot date: 2025-09-06 12:31:19 summary: Setting up a basic REST Service with Spring Boot is a cake walk. We will go one step further and add great integration tests! categories: SpringBootUnitTesting permalink: /integration-testing-for-spring-boot-rest-services image: /images/unit-test-category.png --- ![Image](/images/Spring-Initializr-Web.png "Web, Actuator and Developer Tools") This post will assist you in creating excellent integration tests for your Spring Boot Rest Service. We will create a few of basic rest services using a simple code sample. ## You will learn - What is Integration Testing? - How to create a Get REST Service for retrieving the courses that a student registered for? - How to write a integration test for Get REST Service? - How to create a Post REST Service for registering a course for student? - How to write a integration test for the POST Service? ## Tools you will need - Maven 3.0+ is your build tool - Your favorite IDE. We use Eclipse. - JDK 17 ## Complete Maven Project With Code Examples > Our Github repository has all the code examples - [https://github.com/in28minutes/spring-boot-examples/tree/master/spring-boot-rest-services-with-unit-and-integration-tests](https://github.com/in28minutes/spring-boot-examples/tree/master/spring-boot-rest-services-with-unit-and-integration-tests) ## Integration Testing Following screenshot shows eclipse project with all the files we will create. ![Image](/images/SpringBootRestService-ProjectStructure.png "Spring Boot Rest Services - Project Structure") We want to write an integration test for the 'StudentController' Rest Controller. The 'StudentController' class offers two service methods: Get and Post. Both of these service methods will be subjected to integration testing. In the integration test - `@SpringBootTest` will be used to launch the whole Spring Boot application. - `TestRestTemplate` will be used to call the service methods. - The results will be asserted using a fantastic JSON assert framework - `org.skyscreamer.jsonassert.JSONAssert`. Testing all of the application's levels is an important aspect of integration testing. ## Overview In this guide, we perform everything in the following order: - Spring Initializr may be used to bootstrap a project. - Build a Business Service - StudentService - for our API. - Use StudentController to implement the API. The GET methods are implemented first, followed by the POST methods. - Create API integration tests. ## Using Spring Initializr to Create a REST Services Application > Spring Initializr [http://start.spring.io/](http://start.spring.io/){:target="_blank"} is great tool to bootstrap your Spring Boot projects. ![Image](/images/Spring-Initializr-Web.png "Web, Actuator and Developer Tools") As shown in the image above, following steps have to be done - Launch Spring Initializr and choose the following - Choose `com.in28minutes.springboot` as Group - Choose `student-services` as Artifact - Choose following dependencies - Web - Actuator - DevTools - Click Generate Project. - Import the project into Eclipse. - If you want to understand all the files that are part of this project, you can go here. ## Adding Business Services to Your Application All applications need data. Instead of talking to a real database, we will use an `ArrayList` - kind of an in-memory data store. A student may enrol in many courses. A course contains an id, a name, a description, and a set of actions that must be completed in order to complete the course. A student has an id, a name, a description, and a list of courses for which he or she is presently registered. StudentService is exposing methods to us. - `public List retrieveAllStudents()` - Retrieve details for all students - `public Student retrieveStudent(String studentId)` - Retrieve a specific student details - `public List retrieveCourses(String studentId)` - Retrieve all courses a student is registered for - `public Course retrieveCourse(String studentId, String courseId)` - Retrieve details of a specific course a student is registered for - `public Course addCourse(String studentId, Course course)` - Add a course to an existing student The precise implementation of the Service `StudentService` and the model classes `Course` and 'Student' may be seen at the bottom of this article. - src/main/java/com/in28minutes/springboot/model/Course.java - src/main/java/com/in28minutes/springboot/model/Student.java - src/main/java/com/in28minutes/springboot/service/StudentService.java ## Adding Couple of Http GET Operations The Rest Service `StudentController` exposes couple of get services. - `@Autowired private StudentService studentService` : Spring Autowiring is being used to connect the student service to the StudentController. - `@GetMapping("/students/{studentId}/courses")`: Making a Get Service with studentId available as a route variable - `@GetMapping("/students/{studentId}/courses/{courseId}")`: Introducing a Get Service for fetching a student's individual course. - `@PathVariable String studentId`: This argument will be mapped to the value of studentId from the uri. ```java package com.in28minutes.springboot.controller; import java.net.URI; import java.util.List; import com.in28minutes.springboot.model.Course; import com.in28minutes.springboot.service.StudentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; @RestController public class StudentController { @Autowired private StudentService studentService; @GetMapping("/students/{studentId}/courses") public List retrieveCoursesForStudent(@PathVariable String studentId) { return studentService.retrieveCourses(studentId); } @GetMapping("/students/{studentId}/courses/{courseId}") public Course retrieveDetailsForCourse(@PathVariable String studentId, @PathVariable String courseId) { return studentService.retrieveCourse(studentId, courseId); } @PostMapping("/students/{studentId}/courses") public ResponseEntity registerStudentForCourse(@PathVariable String studentId, @RequestBody Course newCourse) { Course course = studentService.addCourse(studentId, newCourse); if (course == null) return ResponseEntity.noContent().build(); URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(course.getId()).toUri(); return ResponseEntity.created(location).build(); } } ``` ## Executing the Http Get Operation Using Postman We will fire a request to http://localhost:8080/students/Student1/courses/Course1 to test the service. Response is as shown below. ```json { "id": "Course1", "name": "Spring", "description": "10Steps", "steps": [ "Learn Maven", "Import Project", "First Example", "Second Example" ] } ``` Below picture shows how we can execute this Get Service from Postman - my favorite tool to run rest services. ![Image](/images/ExecutingGetRestServiceUsingPostman.png "Executing Rest Service From Postman") ## Integration Testing with the Http Get Operation > When we are writing an integration test for a rest service, we would want to launch the entire spring context. - `@SpringBootTest(classes = StudentServicesApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)` : Launch the entire Spring Boot Application on a Random Port - `@LocalServerPort private int port;`: Autowire the random port into the variable so that we can use it create the url. - `createURLWithPort(String uri)` : Utility method to create the url given an uri. It appends the port. - `HttpEntity entity = new HttpEntity(null, headers);`: We use entity so that we have the flexibility of adding in request headers in future. - `restTemplate.exchange(createURLWithPort("/students/Student1/courses/Course1"),HttpMethod.GET, entity, String.class)`: Fire a GET request to the specify uri and get the response as a String. - `JSONAssert.assertEquals(expected, response.getBody(), false)` : Assert that the response contains expected fields. ```java package com.in28minutes.springboot.controller; import org.json.JSONException; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.skyscreamer.jsonassert.JSONAssert; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit.jupiter.SpringExtension; import com.in28minutes.springboot.StudentServicesApplication; @ExtendWith(SpringExtension.class) @SpringBootTest(classes = StudentServicesApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class StudentControllerIT { @LocalServerPort private int port; TestRestTemplate restTemplate = new TestRestTemplate(); HttpHeaders headers = new HttpHeaders(); @Test public void testRetrieveStudentCourse() throws JSONException { HttpEntity entity = new HttpEntity<>(null, headers); ResponseEntity response = restTemplate.exchange( createURLWithPort("/students/Student1/courses/Course1"), HttpMethod.GET, entity, String.class); String expected = "{\"id\":\"Course1\",\"name\":\"Spring\",\"description\":\"10 Steps\"}"; JSONAssert.assertEquals(expected, response.getBody(), false); } private String createURLWithPort(String uri) { return "http://localhost:" + port + uri; } } ``` ## Adding Http POST Operation > A POST Service should return a status of created (201) when the resource creation is successful. `@PostMapping("/students/{studentId}/courses")`: Mapping a url for the POST Request `@RequestBody Course newCourse`: Using Binding to bind the body of the request to Course object. `ResponseEntity.created(location).build()`: Return a status of created. Also return the location of created resource as a Response Header. ```java @PostMapping("/students/{studentId}/courses") public ResponseEntity registerStudentForCourse(@PathVariable String studentId, @RequestBody Course newCourse) { Course course = studentService.addCourse(studentId, newCourse); if (course == null) return ResponseEntity.noContent().build(); URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(course.getId()).toUri(); return ResponseEntity.created(location).build(); } ``` ## Executing Http POST Operation Example Request is shown below. It contains all the details to register a course to a student. ```json { "name": "Microservices", "description": "10Steps", "steps": [ "Learn How to Break Things Up", "Automate the hell out of everything", "Have fun" ] } ``` Below picture shows how we can execute this Http Post Operation from Postman - my favorite tool to run rest services. Make sure you go to the Body tab and select raw. Select JSON from the dropdown. Copy above request into body. The URL we use is http://localhost:8080/students/Student1/courses. ![Image](/images/ExecutingPostRestServiceUsingPostman.png "Executing Post Rest Service From Postman") ## Writing Integration Test for the Http POST Operation > When writing an integration test for a POST service we would want to check if the location header contains the uri of the created resource. - `String actual = response.getHeaders().get(HttpHeaders.LOCATION).get(0);` : Get the Location header from the response. - `assertTrue(actual.contains("/students/Student1/courses/"))` : Assert that the header contains the uri of the newly created resource. ```java @Test public void addCourse() { Course course = new Course("Course1", "Spring", "10 Steps", List.of("Learn Maven", "Import Project", "First Example", "Second Example")); HttpEntity entity = new HttpEntity(course, headers); ResponseEntity response = restTemplate.exchange( createURLWithPort("/students/Student1/courses"), HttpMethod.POST, entity, String.class); String actual = response.getHeaders() .get(HttpHeaders.LOCATION) .get(0); assertTrue(actual.contains("/students/Student1/courses/")); } ``` ## Complete Code Example ### pom.xml ```xml 4.0.0 com.in28minutes.springboot student-services 0.0.1-SNAPSHOT jar student-services Demo project for Spring Boot org.springframework.boot spring-boot-starter-parent 3.0.2 17 org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-devtools runtime org.springframework.boot spring-boot-starter-test test org.springframework.security spring-security-test test org.springframework.boot spring-boot-maven-plugin spring-milestones Spring Milestones https://repo.spring.io/milestone false spring-milestones Spring Milestones https://repo.spring.io/milestone false ``` --- ### src/main/java/com/in28minutes/springboot/controller/StudentController.java ```java package com.in28minutes.springboot.controller; import java.net.URI; import java.util.List; import com.in28minutes.springboot.model.Course; import com.in28minutes.springboot.service.StudentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; @RestController public class StudentController { @Autowired private StudentService studentService; @GetMapping("/students/{studentId}/courses") public List retrieveCoursesForStudent( @PathVariable String studentId) { return studentService.retrieveCourses(studentId); } @GetMapping("/students/{studentId}/courses/{courseId}") public Course retrieveDetailsForCourse( @PathVariable String studentId, @PathVariable String courseId) { return studentService.retrieveCourse(studentId, courseId); } @PostMapping("/students/{studentId}/courses") public ResponseEntity registerStudentForCourse( @PathVariable String studentId, @RequestBody Course newCourse) { Course course = studentService.addCourse(studentId, newCourse); if (course == null) return ResponseEntity.noContent().build(); URI location = ServletUriComponentsBuilder.fromCurrentRequest() .path("/{id}") .buildAndExpand(course.getId()) .toUri(); return ResponseEntity.created(location).build(); } } ``` --- ### src/main/java/com/in28minutes/springboot/model/Course.java ```java package com.in28minutes.springboot.model; import java.util.List; public class Course { private String id; private String name; private String description; private List steps; // Needed by Caused by: com.fasterxml.jackson.databind.JsonMappingException: // Can not construct instance of com.in28minutes.springboot.model.Course: // no suitable constructor found, can not deserialize from Object value // (missing default constructor or creator, or perhaps need to add/enable // type information?) public Course() { } public Course(String id, String name, String description, List steps) { super(); this.id = id; this.name = name; this.description = description; this.steps = steps; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getDescription() { return description; } public String getName() { return name; } public List getSteps() { return steps; } @Override public String toString() { return String.format( "Course [id=%s, name=%s, description=%s, steps=%s]", id, name, description, steps); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Course other = (Course) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } } ``` --- ### src/main/java/com/in28minutes/springboot/model/Student.java ```java package com.in28minutes.springboot.model; import java.util.List; public class Student { private String id; private String name; private String description; private List courses; public Student(String id, String name, String description, List courses) { super(); this.id = id; this.name = name; this.description = description; this.courses = courses; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public List getCourses() { return courses; } public void setCourses(List courses) { this.courses = courses; } @Override public String toString() { return String.format( "Student [id=%s, name=%s, description=%s, courses=%s]", id, name, description, courses); } } ``` --- ### src/main/java/com/in28minutes/springboot/service/StudentService.java ```java package com.in28minutes.springboot.service; import java.math.BigInteger; import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; import com.in28minutes.springboot.model.Course; import com.in28minutes.springboot.model.Student; import org.springframework.stereotype.Service; @Service public class StudentService { private static final List students = new ArrayList<>(); private final SecureRandom random = new SecureRandom(); static { //Initialize Data Course courseOne = new Course("Course1", "Spring", "10 Steps", List.of("Learn Maven", "Import Project", "First Example", "Second Example")); Course courseTwo = new Course("Course2", "Spring MVC", "10 Examples", List.of("Learn Maven", "Import Project", "First Example", "Second Example")); Course courseThree = new Course("Course3", "Spring Boot", "6K Students", List.of("Learn Maven", "Learn Spring", "Learn Spring MVC", "First Example", "Second Example")); Course courseFour = new Course("Course4", "Maven", "Most popular maven course on internet!", List.of("Pom.xml", "Build Life Cycle", "Parent POM", "Importing into Eclipse")); Student ranga = new Student("Student1", "Ranga Karanam", "Hiker, Programmer and Architect", new ArrayList<>(List.of(courseOne, courseTwo, courseThree, courseFour))); Student satish = new Student("Student2", "Satish T", "Hiker, Programmer and Architect", new ArrayList<>(List.of(courseOne, courseTwo, courseThree, courseFour))); students.add(ranga); students.add(satish); } public List retrieveAllStudents() { return students; } public Student retrieveStudent(String studentId) { for (Student student : students) { if (student.getId().equals(studentId)) { return student; } } return null; } public List retrieveCourses(String studentId) { Student student = retrieveStudent(studentId); return student == null ? null : student.getCourses(); } public Course retrieveCourse(String studentId, String courseId) { Student student = retrieveStudent(studentId); if (student == null) { return null; } for (Course course : student.getCourses()) { if (course.getId().equals(courseId)) { return course; } } return null; } public Course addCourse(String studentId, Course course) { Student student = retrieveStudent(studentId); if (student == null) { return null; } String randomId = new BigInteger(130, random).toString(32); course.setId(randomId); student.getCourses().add(course); return course; } } ``` --- ### src/main/java/com/in28minutes/springboot/StudentServicesApplication.java ```java package com.in28minutes.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class StudentServicesApplication { public static void main(String[] args) { SpringApplication.run(StudentServicesApplication.class, args); } } ``` --- ### src/main/resources/application.properties ``` ``` --- ### src/test/java/com/in28minutes/springboot/controller/StudentControllerIT.java ```java package com.in28minutes.springboot.controller; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; import com.in28minutes.springboot.StudentServicesApplication; import com.in28minutes.springboot.model.Course; import org.json.JSONException; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.skyscreamer.jsonassert.JSONAssert; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit.jupiter.SpringExtension; @ExtendWith(SpringExtension.class) @SpringBootTest(classes = StudentServicesApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class StudentControllerIT { @LocalServerPort private int port; TestRestTemplate restTemplate = new TestRestTemplate(); HttpHeaders headers = new HttpHeaders(); @Test public void testRetrieveStudentCourse() throws JSONException { HttpEntity entity = new HttpEntity<>(null, headers); ResponseEntity response = restTemplate.exchange( createURLWithPort("/students/Student1/courses/Course1"), HttpMethod.GET, entity, String.class); String expected = "{\"id\":\"Course1\",\"name\":\"Spring\",\"description\":\"10 Steps\"}"; JSONAssert.assertEquals(expected, response.getBody(), false); } @Test public void addCourse() { Course course = new Course("Course1", "Spring", "10Steps", List.of("Learn Maven", "Import Project", "First Example", "Second Example")); HttpEntity entity = new HttpEntity<>(course, headers); ResponseEntity response = restTemplate.exchange( createURLWithPort("/students/Student1/courses"), HttpMethod.POST, entity, String.class); String actual = response.getHeaders().get(HttpHeaders.LOCATION).get(0); assertTrue(actual.contains("/students/Student1/courses/")); } private String createURLWithPort(String uri) { return "http://localhost:" + port + uri; } } ``` --- ================================================ FILE: _blog/articles/2017-01-30-spring-boot-starter-parent.md ================================================ --- layout: post title: Introduction to Spring Boot Starter Parent date: 2025-09-07 02:31:19 summary: Key goal of Spring Boot is to enable a quick start to developing production ready applications. Spring Boot Starter Parent plays a key role in managing dependency versions and having the right plug-ins configured. categories: SpringBoot permalink: /spring-boot-starter-parent image: /images/spring-boot-feature.png --- ![Image](/images/Spring-Initializr-Web.png "Web, Actuator and Developer Tools") This guide will help you understand how the Spring Boot Starter Parent simplifies project setup by managing dependency versions, defining the Java version, and providing default configurations for commonly used plugins. ![Image](/images/SpringBootStarterWeb-Dependencies.png "Spring Boot Starter Web - Dependencies") ## You will learn - What is the Spring Boot Starter Parent? - What are its key features? - When should you use it? ## Tools you will need - Maven 3.1+ as your build tool - Your favorite IDE (Eclipse or IntelliJ IDEA) - JDK 17+ ## What is Spring Boot Starter Parent? In a typical **pom.xml**, most Spring Boot projects use **spring-boot-starter-parent** as the parent POM. It provides sensible defaults for dependency versions, plugin management, and build configuration, so you don’t have to configure them manually. ```xml org.springframework.boot spring-boot-starter-parent 4.0.0-M2 ``` Parent POMs let you handle the following for several child projects and modules: - **Configuration** – Java version and other project-wide properties - **Dependency Management** – Centralized version management for dependencies - **Default Plugin Configuration** – Predefined settings for common Maven plugins ## What is inside Spring Boot Starter Parent? - The **Spring Boot Starter Parent POM** defines `spring-boot-dependencies`. - It inherits the dependency management from `spring-boot-dependencies`. - This ensures consistent and compatible versions for all Spring Boot modules and third-party libraries. - More details are covered in the next section. ```xml org.springframework.boot spring-boot-dependencies 4.0.0-M2 ../../spring-boot-dependencies ``` Default java version is 1.6. A project can override this by specifying a property `17 3.1.1` in the project pom. A few other settings related to encoding and source, target version are also set in the parent pom. ```xml 17 @ ${java.version} UTF-8 UTF-8 ${start-class} ``` Spring Boot Starter Parent specifies the default configuration for a host of plugins, including: - `maven-compiler-plugin` - `maven-failsafe-plugin` - `maven-jar-plugin` - `maven-war-plugin` - and many more... ```xml org.apache.maven.plugins maven-compiler-plugin true org.apache.maven.plugins maven-failsafe-plugin integration-test verify ${project.build.outputDirectory} org.apache.maven.plugins maven-jar-plugin ${start-class} true org.apache.maven.plugins maven-war-plugin ${start-class} true ``` ## What does Spring Boot Starter Parent inherit from spring-boot-dependencies? Spring Boot Dependencies defines the Spring Boot project's default **dependency management**. If we want to use a different version of a specific dependency, we can override it by adding a new property in the project `pom.xml`. The following extract demonstrates some of the key dependencies managed by the Spring Boot Dependencies parent POM. Spring Boot Starter Parent inherits all of these properties from `spring-boot-dependencies`. ```xml 6.1.7 2.0.3 2.42.0 1.9.24 3.27.3 4.3.0 3.5.1 6.3.0 3.6.1 1.17.6 2.6.1.Final 3.2.2 4.19.0 1.7.0 1.19.0 2.13.0 3.18.0 1.3.5 1.6 2.12.1 3.8.2 1.5.0 2.9.1 12.1.2.0 1.1.7 10.16.1.1 3.10.8 9.0.3 11.10.3 2.3.34 9.0.2 4.0.5 3.0.1 24.1 4.0.28 2.13.1 2.3.232 3.0 5.5.0 7.0.7.Final 9.0.1.Final 6.3.1 2.7.3 4.13.0 4.1.5 5.5 4.4.16 5.3.4 15.2.5.Final 2.25 2.19.2 2.1.3 3.0.0 2.0.1 3.1.0 2.1.3 3.0.1 2.1.3 1.1.4 3.2.0 6.1.0 3.0.2 2.0.1 3.1.1 2.2.0 4.0.0 4.0.2 3.0.2 4.0.2 3.1.12 1.1.1 1.1 2.0.0 6.0.2 3.6.1.Final 2.0.6.1 6.0.0 4.0.0-M2 4.0.10 12.0.23 1.16 3.19.24 2.9.0 2.5.2 1.5.3 1.3.1 4.13.2 5.13.4 4.0.0 2.2.0 1.10.2 1.9.0 6.7.1.RELEASE 4.33.0 2.24.3 1.5.18 1.18.38 3.5.4 3.1.0 3.7.1 3.5.0 3.14.0 3.8.1 3.1.4 3.6.1 3.5.3 3.5.1 3.1.4 3.9.1 3.4.2 3.11.2 3.3.1 3.6.0 3.3.1 3.5.3 3.4.0 1.16.0-M1 1.6.0-M1 5.18.0 5.5.1 12.10.1.jre11 9.3.0 0.10.6 1.9.22 5.28.9 4.2.3.Final 1.52.0 23.8.0.25.04 1.3.0 3.1.7 42.7.7 1.3.10 0.16.0 4.0.5 0.7.0 2.5.0 5.1.0 1.0.0.RELEASE 1.3.0 1.0.2.RELEASE 1.4.1 1.0.2.RELEASE 1.0.7.RELEASE 1.1.6.RELEASE 1.0.0.RELEASE 5.26.0 0.23.0 1.0.4 2025.0.0-M5 5.5.5 1.1.5 3.1.11 3.0.4 4.34.0 4.33.0 4.10.3 2.0.17 2.4 4.0.0-M3 2.0.0-M1 6.0.0-M1 2025.1.0-M4 7.0.0-M7 2.0.0-M1 3.0.0-M3 7.0.0-M1 4.0.0-M3 4.0.0-M1 2.0.0-M1 4.0.0-M1 2.0.12 7.0.0-M1 4.0.0-M1 5.0.0-M1 3.50.3.0 1.21.3 2.2.4 3.1.3.RELEASE 2.0.1 3.1.3.RELEASE 3.4.0 11.0.9 7.0.3 2.3.18.Final 2.18.0 26.0 0.59 1.1.0 1.6.3 1.1.0 2.10.3 3.0.4 ``` Defines Maven 3.14.0 as the minimum version needed. ```xml 3.14.0 ``` ================================================ FILE: _blog/articles/2017-01-30-spring-boot-starter-projects.md ================================================ --- layout: post title: Initializing Projects with Spring Boot Starters - Web and JPA date: 2025-09-07 12:31:19 summary: Key goal of Spring Boot is to enable a quick start to developing production ready applications. Most important components behind the features of Spring Boot are the Spring Boot Starter Projects. categories: SpringBoot permalink: /spring-boot-starter-projects image: /images/spring-boot-feature.png --- ![Image](/images/Spring-Initializr-Web.png "Web, Actuator and Developer Tools") # Spring Boot Starter Projects This guide will help you understand how **Spring Boot Starter Projects** enable the key goal of Spring Boot — *a quick start to developing production-ready applications*. ![Image](/images/SpringBootStarterWeb-Dependencies.png "Spring Boot Starter Web - Dependencies") ## You will learn - What features are provided by Spring Boot Starter Projects? - Example of a Starter Project - Introduction to Spring Boot Starter Web - Overview of different Starter Projects provided by Spring Boot ## Tools you will need - Maven 3.0+ as your build tool - Your favorite IDE (Eclipse or IntelliJ IDEA recommended) - JDK 17+ ## Why do we need Spring Boot Starter Projects? To understand the value of starter projects, let’s first imagine a project **without them**. ### What if we do not have starter projects? Suppose we want to build a **Spring MVC web application**. - First, we need to decide **which frameworks** to use. - Then, we need to figure out **compatible versions** of those frameworks. - Finally, we have to manage linking and configuration manually. Some of the dependencies we typically use in a Spring MVC project are: - **Spring MVC** – Core web framework - **Jackson Databind** – For JSON data binding - **Hibernate Validator** – For server-side validation using Java Validation API - **Log4j** – For logging 👉 The challenge: We must carefully select versions that are compatible with each other, which adds complexity and slows down development. ```xml org.springframework spring-webmvc 7.0.0-M7 com.fasterxml.jackson.core jackson-databind 2.19.2 compile org.hibernate.validator hibernate-validator 9.0.1.Final org.apache.logging.log4j log4j-bom 2.25.1 pom import ``` To get everything working together, we also had to add **manual configurations**, such as: - Dispatcher Servlet - View Resolver - Error Page - Web Jars (for serving static content) - And other supporting settings 👉 As you can see, without starter projects, setting up even a simple Spring MVC application involves a lot of **boilerplate configuration**. ```xml /WEB-INF/views/ .jsp dispatcher org.springframework.web.servlet.DispatcherServlet contextConfigLocation /WEB-INF/todo-servlet.xml 1 dispatcher / ``` We would need to do **similar setup tasks when using JPA**. - Provide the required JPA and Hibernate jars - Configure the **DataSource** - Configure the **EntityManagerFactory** - Configure the **TransactionManager** - Add other related settings manually 👉 As with Spring MVC, this becomes **time-consuming and error-prone**. ```xml ``` ## Spring Boot Starter Projects Here’s how the official Spring Boot documentation defines starters: > **Starters are a set of convenient dependency descriptors that you can include in your application.** > You get a one-stop shop for all the Spring and related technologies you need, without having to hunt through sample code or copy-paste loads of dependency descriptors. > For example, if you want to get started using Spring and JPA for database access, just include the `spring-boot-starter-data-jpa` dependency in your project, and you are good to go. ### Example: Spring Boot Starter Web If you want to: - Build a **web application** - Or expose **RESTful services** 👉 `spring-boot-starter-web` is the starter you should pick. Let’s create a simple project with **Spring Boot Starter Web** using **Spring Initializr**. --- # Creating REST Services Applications with Spring Initializr ## What is Spring Initializr? [Spring Initializr](https://start.spring.io/) is an invaluable web-based tool designed to **bootstrap your Spring Boot projects quickly and efficiently**. It eliminates the complexity of manual project setup by providing an intuitive interface for generating production-ready Spring Boot applications. ## Key Configuration Options When creating your REST services project, you can customize several essential parameters: ### Project Configuration - **Project Type**: Choose your preferred build automation tool - **Maven** - XML-based configuration, widely adopted - **Gradle** - Groovy/Kotlin DSL, modern build system - **Programming Language**: Select the language that fits your team's expertise - **Java** - Industry standard, extensive ecosystem - **Kotlin** - Concise syntax, 100% Java interoperability - **Groovy** - Dynamic language with Java compatibility - **Spring Boot Version**: Pick the appropriate framework version - Latest stable release (recommended for new projects) - LTS versions for enterprise applications - Snapshot versions for bleeding-edge features This saves a lot of time by generating a ready-to-use project structure. ![Image](/images/Spring-Initializr-Web.png "Web, Actuator and Developer Tools") ### Steps to Create a Spring Boot Starter Web Project As shown in the image above, follow these steps: 1. **Launch Spring Initializr** and choose the following options: - **Group:** `com.in28minutes.springboot` - **Artifact:** `student-services` - **Dependencies:** - Web - Actuator - DevTools 2. **Click "Generate Project"** to download the project as a `.zip` file. 3. **Import the project into Eclipse** (or your preferred IDE). - In Eclipse, use: `File > Import > Existing Maven Projects` 4. If you want to **understand all the files** that are part of this generated project, you can check the detailed explanation [here](#) _(link to explanation or documentation)_. ## Spring Boot Starter Web Spring Boot Starter Web has two crucial features: - **Compatible Dependencies** that are needed to develop web applications - **Auto Configuration** to automatically set up common configurations (DispatcherServlet, Jackson, Validation, Embedded Tomcat, etc.) ### Dependency for Spring Boot Starter Web If you are using **Maven**, add this to your `pom.xml`: ```xml org.springframework.boot spring-boot-starter-web ``` If you are using Gradle, add this to your `build.gradle`: ```gradle implementation 'org.springframework.boot:spring-boot-starter-web' ``` ### Dependencies Following screenshot shows the different dependencies that are added in to our application ![Image](/images/SpringBootStarterWeb-Dependencies.png "Spring Boot Starter Web - Dependencies") Dependencies can be classified into: - Spring - core, beans, context, aop - Web MVC - (Spring MVC) - Jackson - for JSON Binding - Validation - Hibernate Validator, Validation API - Embedded Servlet Container - Tomcat - Logging - logback, slf4j All of these requirements would be used by any regular web application. Spring Boot Starter Site already has them. As a developer, I would not have to be concerned about their dependencies or their compatible version ### Auto Configuration Spring Boot Starter Web automatically configures the essentials. To explore the functionality added by Spring Boot Starter Web, run StudentServicesApplication.java as a Java Application and examine the log. ``` Mapping servlet: 'dispatcherServlet' to [/] Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] ``` Spring Boot Starter Web auto-configures - Dispatcher Servlet - Error Page - Web Jars to manage your static dependencies - Embedded Servlet Container - Tomcat is the default The image below shows the different things that might be auto configured by Spring Boot Starter Web ![Image](/images/SpringBootStarterWeb-AutoConfiguration.png "Spring Boot Starter Web - Auto Configuration") ## Spring Boot Starter Project Options As we can see from **Spring Boot Starter Web**, starter projects allow us to get started quickly with designing various types of applications. ### Application Starters - `spring-boot-starter-web-services` - SOAP Web Services - `spring-boot-starter-web` - Web & RESTful applications - `spring-boot-starter-test` - Unit testing and Integration Testing - `spring-boot-starter-jdbc` - Traditional JDBC - `spring-boot-starter-hateoas` - Add HATEOAS features to your services - `spring-boot-starter-security` - Authentication and Authorization using Spring Security - `spring-boot-starter-data-jpa` - Spring Data JPA with Hibernate - `spring-boot-starter-cache` - Enabling Spring Framework’s caching support - `spring-boot-starter-data-rest` - Expose Simple REST Services using Spring Data REST ### Technical Starters - `spring-boot-starter-actuator` - Advanced features like monitoring & tracing out of the box - `spring-boot-starter-undertow`, `spring-boot-starter-jetty`, `spring-boot-starter-tomcat` - Choose your specific Embedded Servlet Container - `spring-boot-starter-logging` - Logging using Logback - `spring-boot-starter-log4j2` - Logging using Log4j2 ================================================ FILE: _blog/articles/2017-01-30-spring-boot-starter-security.md ================================================ --- layout: post title: Secure Rest Services and Web Applications with Spring Boot Security Starter date: 2025-09-13 12:31:19 summary: Spring Boot Starter Security is the recommended starter for enabling security on web application - including REST services. categories: SpringBoot permalink: /securing-rest-services-with-spring-boot-starter-security image: /images/spring-boot-feature.png --- ![Image](/images/Spring-Initializr-Web.png "Web, Actuator and Developer Tools") # Spring Boot Starter Security This guide will help you understand the different features that **Spring Boot Starter Security** brings in, using two examples: - **A REST Service** - **A Simple Web Application Page** Spring Boot Starter Security makes it very easy to secure your applications by providing: - Default authentication and authorization - Integration with common security standards (basic auth, form login, OAuth2, JWT, etc.) - Auto-configuration that works out-of-the-box, but can be customized as needed. ![Image](/images/SpringBootSecuritySecurity-WebApplication.png "Spring Security - Web Application") ## You will learn - What is **Spring Boot Starter Security**? - What features are provided by **Spring Boot Starter Security**? - How do you enable Spring Security on a **web application**? - How do you enable Spring Security on a **REST Web Service**? - How do you invoke a REST Service using **Basic Authentication**? - Example: securing a simple **Web Application** - Example: securing a **REST Service** with Basic Authentication ## Tools you will need - **Maven 3.0+** as your build tool - Your favorite **IDE** (Eclipse or IntelliJ IDEA recommended) - **JDK 17+** ## Complete Maven Project With Code Examples > Our GitHub repository has all the code > examples - [https://github.com/in28minutes/in28minutes.github.io/tree/master/code-zip-files](https://github.com/in28minutes/in28minutes.github.io/tree/master/code-zip-files) - **Spring Security Example** - `Website-SpringSecurityStarterWebApplication_Final.zip` --- ## Bootstrapping Web Application with Spring Initializr Using **Spring Initializr** to create a Web application is very simple. For both the **web page** and the **REST service**, we will use **Spring Web MVC** as our web framework. > Spring Initializr: [http://start.spring.io/](http://start.spring.io/) is a great tool to bootstrap your Spring Boot > projects. ![Image](/images/Spring-Initializr-Web.png "Web, Actuator and Developer Tools") As shown in the image above, following steps have to be done ### Steps to Launch Spring Initializr - Launch **Spring Initializr** and choose the following: - Group: `com.in28minutes.springboot` - Artifact: `student-services` - Dependencies: - Web - Click **Generate Project**. - Import the project into **Eclipse** or **IntelliJ IDEA** (or your favorite IDE). - If you want to understand all the files that are part of this project, you can go [here](https://github.com/in28minutes/in28minutes.github.io/tree/master/code-zip-files){:target="_blank"}. ## Setting up a Simple Web Application Let's rapidly secure a basic web application with **Spring Security**. We’ll create a simple Controller that redirects to the welcome view – just a basic JSP. ### JSP Support As the view, we intend to use **JSP**. Since **Tomcat** is the default embedded servlet container for **Spring Boot Starter Web**, we need to add a dependency on `tomcat-embed-jasper` to enable JSP support. ```xml org.apache.tomcat.embed tomcat-embed-jasper provided // default for IntelliJ IDE ``` ### Adding Login Controller We will create a **LoginController** to handle the root URL `/`. - The `showLoginPage()` function will be mapped to `/`. - The `Model` will be pre-populated with a hardcoded name. - It will return a view with the name `"welcome"`, which maps to `welcome.jsp`. ```java package com.in28minutes.springboot.web.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class LoginController { @RequestMapping(value = "/", method = RequestMethod.GET) public String showLoginPage(ModelMap model) { model.put("name", "in28Minutes"); return "welcome"; } } ``` ### Adding welcome.jsp `welcome.jsp` is a simple JSP page that displays a welcome message to the user. ```html
Welcome ${name}!!
``` ### Configure a View Resolver `welcome.jsp` is placed under `src/main/webapp/WEB-INF/jsp/`. To map the view name (like `"welcome"`) returned from the controller to the actual JSP file, we configure a **view resolver** in `application.properties`. ```properties spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp ``` ### Run the Web Application Start the `StudentServicesApplication.java` program as a **Spring Boot Application**. Once started, the application will run on the default port `8080`. You can access it at: [http://localhost:8080](http://localhost:8080) At this point, the `LoginController` will redirect you to the `welcome.jsp` page, displaying the welcome message. ![Image](/images/SpringBootSecuritySecurity-WebApplication.png "Spring Security - Web Application") ## Add a Simple REST Service Let's also provide a basic REST Service. We will include: - **Model Objects**: `Course` and `Student`. - A student may enroll in many courses. - **Business Service**: `StudentService` - Handles the business logic. - Uses hardcoded data stored in a static `ArrayList`. - **REST Controller**: `StudentController` - Exposes one REST endpoint to fetch the list of courses for which a student is registered. ### REST Endpoint Example - `@GetMapping("/students/{studentId}/courses")` Retrieves all courses a given student is enrolled in. ## Model and Business Logic The following excerpts are taken from the model objects **Course** and **Student**. - A **Course** represents a subject with details such as `id`, `name`, and `description`. - A **Student** represents a learner and includes information along with the list of courses they are enrolled in. The **business logic** is handled by the `StudentService` class. - It uses a static `ArrayList` to store student data. - The data is hardcoded for simplicity. - Its primary function is to retrieve the list of courses for a specific student. ```java public class Course { private String id; private String name; private String description; private List steps; } ``` ```java public class Student { private String id; private String name; private String description; private List courses; } ``` StudentService provides a method `public List retrieveCourses(String studentId)` to retrieve the courses a student registered for. ```java @Component public class StudentService { private static List students = new ArrayList<>(); static { // Initialize Data Course course1 = new Course("Course1", "Spring", "10 Steps", List.of("Learn Maven", "Import Project", "First Example", "Second Example")); Course course2 = new Course("Course2", "Spring MVC", "10 Examples", List.of("Learn Maven", "Import Project", "First Example", "Second Example")); Student ranga = new Student("Student1", "Ranga Karanam", "Hiker, Programmer and Architect", new ArrayList<>( List.of(course1, course2))); students.add(ranga); } public Student retrieveStudent(String studentId) { for (Student student : students) { if (student.getId().equals(studentId)) { return student; } } return null; } public List retrieveCourses(String studentId) { Student student = retrieveStudent(studentId); return student == null > null :student.getCourses(); } } ``` ### Creating REST Service Rest Service `StudentController` exposes a simple Get service at URI mapping "/students/{studentId}/courses". The `StudentService` is auto-wired in. ```java package com.in28minutes.springboot.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import com.in28minutes.springboot.model.Course; import com.in28minutes.springboot.service.StudentService; @RestController public class StudentController { @Autowired private StudentService studentService; @GetMapping("/students/{studentId}/courses") public List retrieveCoursesForStudent(@PathVariable String studentId) { return studentService.retrieveCourses(studentId); } } ``` ### Executing REST Service Running the REST Service is simple. Open the URL `http://localhost:8080/students/Student1/courses` in your browser or use your favorite REST client (e.g., Postman). ![Image](/images/SpringBootSecuritySecurity-RestService.png "Spring Security - Rest Service") ## Add Spring Boot Starter Security Next, let’s add the **Spring Boot Starter Security** dependency to our project. This will enable authentication and authorization features for both our web application and REST services. ```xml org.springframework.boot spring-boot-starter-security ``` ### New Dependencies The screenshot below shows the additional dependencies that are included when we add **spring-boot-starter-security**. These libraries provide the core functionality required for securing web applications and REST services. ![Image](/images/SpringBootSecuritySecurity-Depedencies.png "Dependencies of Spring Boot Security Starter") ### Auto Configuration After restarting the application, you will notice the following statements printed in the logs. These messages indicate that Spring Boot has automatically configured Spring Security for your application. ```logs Mapping filter: 'springSecurityFilterChain' to: [/*] Using default security password: 25e07e82-720d-4109-ba8d-25177c6347e6 Creating filter chain: ... ... ``` All this magic happens because of **Spring Boot Auto-Configuration**: - `Mapping filter: 'springSecurityFilterChain' to: [/*]` - Spring Security is automatically enabled for **all URLs** in the application. - **Basic Authentication** is applied by default. - `Using default security password: 25e07e82-720d-4109-ba8d-25177c6347e6` - The default username is **user**. - The default password is randomly generated and printed in the startup log. - In this example, the password is `25e07e82-720d-4109-ba8d-25177c6347e6`. - Several **filter chains** are auto-configured to enforce security. ### Executing the REST Service When we execute the REST service at `http://localhost:8080/students/Student1/courses`, it now returns an * *authentication failure**. - The **HTTP status** is `401 Unauthorized`. - The response message is `"Bad credentials"`. - This happens because the service is now **protected by Spring Security**. ```json { "timestamp": 1485768623632, "status": 401, "error": "Unauthorized", "message": "Bad credentials", "path": "/students/Student1/courses" } ``` - Make sure to provide the correct username and password, as the service is now secured with Spring Security. ![Image](/images/SpringBootSecuritySecurity-RestService-WithoutAuthentication.png "Spring Boot Security Starter - Executing Protected Rest Service without Authentication") ### Executing REST Service with Basic Authentication Retrieve the password from the application log by looking for `Using default security password:`. The default username is `user`. Use this username and password combination to access the service using Basic Authentication, as illustrated in the screenshot below. ![Image](/images/SpringBootSecuritySecurity-RestService-Authentication.png "Spring Boot Security Starter - Executing Rest Service with Basic Authentication") ### Running the Web Application When you open the URL `http://localhost:8080` in your browser, a popup will appear requesting a username and password. Enter the same credentials that you used for the REST Service. ![Image](/images/SpringBootSecuritySecurity-WebApplication-Authentication.png "Spring Boot Security Starter - Providing authentication details for Web application") That's quite a bit of functionality we enabled just by adding the simple dependency `Spring Boot Starter Security`. ## Configuring Custom Users and Roles Now let's configure custom users and roles: - We will define two roles: **Admin** and **User**. - The **Admin** role will have access to the web application. - The **User** role will have access to execute REST services. - We will create one user for the **Admin** role with credentials: `admin1 / secret1`. - We will create one user for the **User** role with credentials: `user1 / secret1`. ```java package com.in28minutes.springboot.security; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests( auth -> auth.requestMatchers("/students/**") .permitAll().anyRequest().authenticated()); http.httpBasic(withDefaults()); http.csrf().disable(); return http.build(); } @Bean public AuthenticationManager authenticationManager(UserDetailsService userDetailsService) { var authenticationProvider = new DaoAuthenticationProvider(); authenticationProvider.setUserDetailsService(userDetailsService); return new ProviderManager(authenticationProvider); } @Bean public UserDetailsService userDetailsService() { UserDetails user = User.withUsername("user1") .password("{noop}secret1") .authorities("read") .roles("USER") .build(); UserDetails userOne = User.withUsername("admin1") .password("{noop}secret1") .authorities("read") .roles("ADMIN") .build(); return new InMemoryUserDetailsManager(user, userOne); } } ``` ### Executing REST Services Now you can use the `user1 / secret1` credentials to access the REST service. ### Launching the Web Application Use the `admin1 / secret1` credentials in the authentication popup to access the web application. ================================================ FILE: _blog/articles/2017-01-30-spring-boot-web-application-top20.md ================================================ --- layout: post title: Creating a Web Application with Spring Boot with JSP date: 2025-09-13 12:31:19 summary: Setting up a basic web application with Spring Boot is a cake walk. We will create a simple web application using Spring Initializr and add JSP features to it. categories: SpringBoot permalink: /creating-web-application-with-spring-boot image: /images/spring-boot-application.png --- This guide will help you create a simple web application with Spring Boot. We will develop an application that includes login functionality and the ability to display a list of todos. The application will follow the MVC pattern, using JSP as the view. ![Image](/images/SpringBootWebApplication-AllFiles.png "Spring Boot Web Application - All Files") ## You will learn - How to bootstrap a simple Spring Boot project using Spring Initializr. - How to initialize a basic web application with Spring Boot. - How to add JSP pages to your web application. - How to implement basic login functionality. - How to display a list of todos. - How to auto-wire components using the Spring Framework. - Next steps if you want to explore further. ## Tools You Will Need - Maven 3.0+ as your build tool - Your preferred IDE (Eclipse or IntelliJ IDEA recommended) - JDK 17 or higher ## Overview of the Web Application We will build a simple **To-Do list page** (unformatted) with a basic **login feature**. ### Project Files The screenshot below shows the Eclipse project with all the files we will create. ![Image](/images/SpringBootWebApplication-AllFiles.png "Spring Boot Web Application - All Files") ## Brief Overview of All Files - `LoginService` and `TodoService` Contain the business logic. `LoginService` provides simple hardcoded validation for user ID and password. `TodoService` contains a method to retrieve a list of todos. - `login.jsp`, `welcome.jsp`, `list-todos.jsp` The names clearly indicate the content of each view. - `LoginController` and `TodoController` Act as controllers in the MVC pattern. `LoginController` handles login flow: if the user enters a valid ID and password, they are redirected to the welcome page; otherwise, the login page is shown with an error message. - `pom.xml` Contains important dependencies such as Spring Boot Starter Web and `tomcat-embed-jasper`. - `application.properties` Typically used to configure frameworks in Spring Boot. In this example, it is used to configure the view resolver. ### Screenshots of the application Login Page ![Image](/images/SpringBootWebApplication-LoginPage.png "Spring Boot Web Application - Login Page") Login Page if user enters invalid userid and password ![Image](/images/SpringBootWebApplication-LoginPage-InvalidCredentials.png "Spring Boot Web Application - Login Page with Invalid Credentials") Welcome Page ![Image](/images/SpringBootWebApplication-WelcomePage.png "Spring Boot Web Application - Welcome Page") List Todos Page ![Image](/images/SpringBootWebApplication-TodoPage.png "Spring Boot Web Application - Todo Page") ## Bootstrapping a Web Application with Spring Initializr Creating a web application with Spring Initializr is a cakewalk. We will use Spring Web MVC as our web framework. > Spring Initializr [http://start.spring.io/](http://start.spring.io/) is a great tool to bootstrap your Spring Boot projects. ![Image](/images/Spring-Initializr-Web.png "Web, Actuator and Developer Tools") As shown in the image above, follow these steps: - Launch Spring Initializr and choose the following: - **Group**: `com.in28minutes.springboot` - **Artifact**: `student-services` - **Dependencies**: - Web - Actuator - DevTools - Click **Generate Project**. - Import the project into **Eclipse** or **IntelliJ IDEA**. - To understand all the files included in this project, you can refer [here](#). ## Project Dependencies Spring Boot Starter Web provides all the necessary dependencies and auto-configuration required to develop web applications. This is the first dependency we will use in our project. ```xml org.springframework.boot spring-boot-starter-web ``` We want to use JSP as the view. The default embedded servlet container for Spring Boot Starter Web is Tomcat. To enable JSP support, we need to add a dependency on `tomcat-embed-jasper`. ```xml org.apache.tomcat.embed tomcat-embed-jasper provided // default for IntelliJ IDE ``` ### Spring Boot Starter Web Dependencies The following screenshot shows the dependencies that are automatically added to our application by including Spring Boot Starter Web. ![Image](/images/SpringBootStarterWeb-Dependencies.png "Spring Boot Starter Web - Dependencies") Dependencies can be categorized as follows: - **Spring** – core, beans, context, AOP - **Web MVC** – Spring MVC - **Jackson** – for JSON binding - **Validation** – Hibernate Validator, Validation API - **Embedded Servlet Container** – Tomcat - **Logging** – Logback, SLF4J Any typical web application would use all these dependencies. Spring Boot Starter Web comes pre-packaged with them. As a developer, you don’t need to worry about these dependencies or their compatible versions. ### Auto Configuration Spring Boot Starter Web also auto-configures the basic components required for a web application. To see the features it provides, run `StudentServicesApplication.java` as a Java application and review the log. ```logs Mapping servlet: 'dispatcherServlet' to [/] Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] ``` Spring Boot Starter Web auto-configures the following components: - **Dispatcher Servlet** - **Error Page** - **Web Jars** to manage static dependencies - **Embedded Servlet Container** – Tomcat is used by default ## Configuring a View Resolver Our JSP files will be located in `/WEB-INF/jsp/`. We need to configure a view resolver with the appropriate **prefix** and **suffix** to map view names to these JSP files. ```properties spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp ``` ## Login Controller - `public String showLoginPage(ModelMap model)`: Mapped to the `\login` GET method; displays the login page. - `@Autowired LoginService service`: Injects `LoginService`, which contains the validation logic. - `showWelcomePage(ModelMap model, @RequestParam String name, @RequestParam String password)`: Mapped to the `\login` POST method; validates the user ID and password, and redirects to the welcome page if login is successful. ```java package com.in28minutes.springboot.web.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.SessionAttributes; import com.in28minutes.springboot.web.service.LoginService; @Controller @SessionAttributes("name") public class LoginController { @Autowired LoginService service; @RequestMapping(value="/login", method = RequestMethod.GET) public String showLoginPage(ModelMap model){ return "login"; } @RequestMapping(value="/login", method = RequestMethod.POST) public String showWelcomePage(ModelMap model, @RequestParam String name, @RequestParam String password){ boolean isValidUser = service.validateUser(name, password); if (!isValidUser) { model.put("errorMessage", "Invalid Credentials"); return "login"; } model.put("name", name); model.put("password", password); return "welcome"; } } ``` ## Login Service Contains the basic authentication logic. Uses hardcoded credentials for simplicity. ```java package com.in28minutes.springboot.web.service; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; @Service public class LoginService { public boolean validateUser(String userid, String password) { // in28minutes, dummy return userid.equalsIgnoreCase("in28minutes") && password.equalsIgnoreCase("dummy"); } } ``` ## Login View - JSP A simple login page with fields for `userid` and `password`. If an error message is set in the model, `${errorMessage}` will display the authentication failure message. ```html First Web Application ${errorMessage}
Name : Password :
``` ## Welcome-View - JSP This page is displayed upon successful authentication. It shows the name of the logged-in user and provides a link to manage the todo list. ```html First Web Application Welcome ${name}!! Click here to manage your todo's. ``` ## Todo Model and Business Service The `Todo` model contains the following fields: `id`, `user`, `description`, and `targetDate`. The `TodoService` provides basic business logic to manage and retrieve todo items. ```java package com.in28minutes.springboot.web.model; import java.util.Date; public class Todo { private int id; private String user; private String desc; private Date targetDate; private boolean isDone; //Getters, Setters, Constructors, toString, equals and hash code } ``` `TodoService` uses a simple `ArrayList` to store todos in memory. It provides a method to retrieve the list of todos. ```java package com.in28minutes.springboot.web.service; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import org.springframework.stereotype.Service; import com.in28minutes.springboot.web.model.Todo; @Service public class TodoService { private static List todos = new ArrayList<>(); private static int todoCount = 3; static { todos.add(new Todo(1, "in28Minutes", "Learn Spring MVC", new Date(), false)); todos.add(new Todo(2, "in28Minutes", "Learn Struts", new Date(), false)); todos.add(new Todo(3, "in28Minutes", "Learn Hibernate", new Date(), false)); } public List retrieveTodos(String user) { List filteredTodos = new ArrayList<>(); for (Todo todo : todos) { if (todo.getUser().equals(user)) { filteredTodos.add(todo); } } return filteredTodos; } } ``` ## List Todos JSP The List Todos page displays all the todos. This page is currently unformatted. In subsequent steps of the course, we will enhance this page by styling it and adding functionality to add, delete, and update todos. ```jsp First Web Application Here are the list of your todos: ${todos}
Your Name is : ${name} ``` ## Todo Controller The TodoController has a simple method that retrieves the list of todos and adds them to the model. It then redirects to the `list-todos` view. ```java package com.in28minutes.springboot.web.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.SessionAttributes; import com.in28minutes.springboot.web.service.LoginService; import com.in28minutes.springboot.web.service.TodoService; @Controller @SessionAttributes("name") public class TodoController { @Autowired TodoService service; @RequestMapping(value="/list-todos", method = RequestMethod.GET) public String showTodos(ModelMap model){ String name = (String) model.get("name"); model.put("todos", service.retrieveTodos(name)); return "list-todos"; } } ``` ## Running the Application We use a Spring Boot application class to launch our web application. ```java package com.in28minutes.springboot.web; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; @SpringBootApplication @ComponentScan("com.in28minutes.springboot.web") public class SpringBootFirstWebApplication { static void main(String[] args) { SpringApplication.run(SpringBootFirstWebApplication.class, args); } } ``` Complete code is available on the GitHub repository: [https://github.com/in28minutes/SpringBootWebApplicationStepByStep](https://github.com/in28minutes/SpringBootWebApplicationStepByStep). You can download `Step12.zip` and import it as a Maven project to run it. Run the application as a simple Java application. Upon startup, you will see the application initializing in the logs. All request mappings will be properly configured. You can access the application at [http://localhost:8080/login](http://localhost:8080/login) and log in using the credentials: - **UserID**: in28Minutes - **Password**: dummy ``` . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v4.0.0-M2) 2017-01-30 10:02:01.775 INFO 6070 --- [ restartedMain] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http) 2017-01-30 10:02:01.798 INFO 6070 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service Tomcat 2017-01-30 10:02:01.800 INFO 6070 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.5.6 2017-01-30 10:02:02.498 INFO 6070 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2017-01-30 10:02:02.498 INFO 6070 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 3747 ms 2017-01-30 10:02:02.803 INFO 6070 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] 2017-01-30 10:02:03.557 INFO 6070 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/login],methods=[GET]}" onto public java.lang.String com.in28minutes.springboot.web.controller.LoginController.showLoginPage(org.springframework.ui.ModelMap) 2017-01-30 10:02:03.559 INFO 6070 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/login],methods=[POST]}" onto public java.lang.String com.in28minutes.springboot.web.controller.LoginController.showWelcomePage(org.springframework.ui.ModelMap,java.lang.String,java.lang.String) 2017-01-30 10:02:03.559 INFO 6070 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/list-todos],methods=[GET]}" onto public java.lang.String com.in28minutes.springboot.web.controller.TodoController.showTodos(org.springframework.ui.ModelMap) 2017-01-30 10:02:03.564 INFO 6070 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) 2017-01-30 10:02:03.565 INFO 6070 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) 2017-01-30 10:02:03.615 INFO 6070 --- [ restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2017-01-30 10:02:03.616 INFO 6070 --- [ restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2017-01-30 10:02:03.682 INFO 6070 --- [ restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2017-01-30 10:02:04.108 INFO 6070 --- [ restartedMain] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2017-01-30 10:02:04.288 INFO 6070 --- [ restartedMain] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) 2017-01-30 10:02:04.307 INFO 6070 --- [ restartedMain] c.i.s.web.SpringBootFirstWebApplication : Started SpringBootFirstWebApplication in 7.204 seconds (JVM running for 9.191) ``` Complete code is available on the GitHub repository: [https://github.com/in28minutes/SpringBootWebApplicationStepByStep](https://github.com/in28minutes/SpringBootWebApplicationStepByStep). You can download `Step12.zip` and import it as a Maven project to run the application. ================================================ FILE: _blog/articles/2017-02-02-spring-boot-vs-spring-mvc-vs-spring.md ================================================ --- layout: post title: Spring Boot vs Spring MVC vs Spring - How do they compare? date: 2025-09-13 12:31:19 summary: How does Spring Boot compare with Spring MVC and Spring? What is Spring Boot? What is Spring MVC? What is Spring Framework? What are their goals? How do they compare? categories: SpringBoot permalink: /spring-boot-vs-spring-mvc-vs-spring image: /images/spring-boot-category.png --- What is Spring Boot, Spring MVC, and the Spring Framework? What are their respective goals, and how do they compare to one another? ![Image](/images/SpringBootStarterWeb-Dependencies.png "Spring Boot Starter Web - Dependencies") ## You Will Learn - An overview of the **Spring Framework** - The key problems the **Spring Framework** addresses - An overview of the **Spring MVC Framework** - The key problems the **Spring MVC Framework** addresses - An overview of the **Spring Boot Framework** - The key problems that **Spring Boot** solves - A comparison: **Spring vs. Spring MVC vs. Spring Boot** - Most importantly: **Spring, Spring MVC, and Spring Boot are not competitors.** They each solve different problems—and they solve them very well. # A Complete Maven Project With Code Examples > Our GitHub repository contains all the code examples: > https://github.com/in28minutes/in28minutes.github.io/tree/master/code-zip-files - `Website-springbootrestservices-simplerestserviceswithunitandintegrationtests.zip` — Rest services with unit & integration tests - `Website-SpringSecurityStarterWebApplication_Final.zip` — Spring Security example - `Website-springbootrestservices-all-examples.zip` — Other RESTful web services examples # What is the core problem that the Spring Framework solves? Think about the core problem: **how objects get their dependencies**. Spring's answer is **Dependency Injection (DI)**, also known as **Inversion of Control (IoC)**. > The most important feature of the Spring Framework is **Dependency Injection**. At the core of all Spring modules is DI / IoC. **Why this matters** - Enables **loose coupling** between components. - Makes code **easy to unit test** (you can inject mocks). - Simplifies **swapping implementations** and managing object lifecycles. # Example — without Dependency Injection ```java @RestController public class WelcomeController { private WelcomeService service = new WelcomeService(); @RequestMapping("/welcome") public String welcome() { return service.retrieveWelcomeMessage(); } } ``` ### Same Example with Dependency Injection With **Dependency Injection (DI)**, life becomes much easier. Instead of manually wiring dependencies, you let the **Spring Framework** handle the heavy lifting. This is achieved using two simple annotations: - `@Service` — Tells Spring: *"This is a bean. Please create and manage its lifecycle."* - `@Autowired` — Tells Spring: *"Find a matching bean of this type and inject it here."* In the example below, Spring automatically creates a bean for `WelcomeService` and injects it into `WelcomeController`. ```java @Service public class WelcomeService { //Bla Bla Bla } @RestController public class WelcomeController { @Autowired private WelcomeService service; @RequestMapping("/welcome") public String welcome() { return service.retrieveWelcomeMessage(); } } ``` ## What else does the Spring Framework solve? ### Problem 1: Boilerplate and Plumbing Code Does the Spring Framework stop with Dependency Injection? **No.** It builds on DI with a number of modules, such as: - Spring JDBC - Spring MVC - Spring AOP - Spring ORM - Spring JMS - Spring Test Take **Spring JDBC** and **Spring JMS** as examples. Do these modules provide brand-new functionality? **Not really.** Everything can already be done with J2EE/JEE. So, what do they add? They provide **simplified abstractions** that: - Reduce boilerplate and duplication - Promote decoupling and improve unit testability For instance, using Spring’s templates (like `JdbcTemplate` or `JmsTemplate`) requires far less code compared to traditional JDBC or JMS approaches. --- ### Problem 2: Seamless Integration with Other Frameworks Another strength of Spring is that it doesn’t reinvent the wheel. Instead, it integrates smoothly with popular, proven frameworks, such as: - **Hibernate** for ORM - **iBatis** for object mapping - **JUnit & Mockito** for testing --- ## What is the core problem that the Spring MVC Framework solves? The **Spring MVC Framework** offers a **decoupled way to build web applications**. By introducing simple yet powerful concepts like the **Dispatcher Servlet**, **ModelAndView**, and **View Resolver**, it makes web application development cleaner, more modular, and easier to manage. --- ## Why do we need Spring Boot? While Spring is powerful, **Spring-based applications traditionally require a lot of configuration**. For example, when using Spring MVC, you typically need to configure: - Component scanning - The Dispatcher Servlet - A View Resolver - WebJars (for serving static content) - And more... Spring Boot was created to **remove this heavy setup burden** by providing sensible defaults, auto-configuration, and embedded servers — making it much faster to build and run Spring applications. ```xml /WEB-INF/views/ .jsp ``` The below code snippet shows the typical configuration of a dispatcher servlet in a web application. ```xml dispatcher org.springframework.web.servlet.DispatcherServlet contextConfigLocation /WEB-INF/todo-servlet.xml 1 dispatcher / ``` When we use Hibernate/JPA, we would need to configure a datasource, an entity manager factory, and a transaction manager, among a host of other things. ```xml ``` ## Problem #1: Spring Boot Auto-Configuration — A New Way of Thinking Spring Boot introduced a fresh perspective: **Can configuration be made smarter and more automatic?** > For example: > - If a **Hibernate** JAR is on the classpath, can Spring Boot auto-configure a **DataSource**? > - If a **Spring MVC** JAR is on the classpath, can it auto-configure a **DispatcherServlet**? The answer is **yes**. Spring Boot automatically provides sensible defaults by analyzing: 1. The **frameworks available on the classpath** 2. The **existing configuration** in the application Based on this, it sets up the basic configuration required to run the application. This intelligent setup is known as **Auto-Configuration**. And of course, developers can **override** the defaults when needed. --- ## Problem #2: Spring Boot Starter Projects — Simplifying Dependencies When developing a web application, we usually need to: - Identify which frameworks to use - Choose the correct versions of those frameworks - Ensure all dependencies are compatible and work together This can be tedious and error-prone. Most web applications share common dependencies. For example, in our Spring MVC course we used: - **Spring MVC** - **Jackson Databind** (for JSON data binding) - **Hibernate Validator** (for server-side validation with JSR-303/380) - **Log4j** (for logging) Manually selecting and managing versions of all these libraries was a challenge. Spring Boot solved this with **Starter Projects** — curated dependency descriptors that bring in a set of compatible libraries for common application needs (like `spring-boot-starter-web` for web apps). This removes guesswork and ensures consistent, stable builds. ```xml org.springframework spring-webmvc 6.0.0-M4 com.fasterxml.jackson.core jackson-databind 2.13.3 org.hibernate hibernate-validator 7.0.4.Final log4j log4j 1.2.17 ``` Here’s how the official Spring Boot documentation describes **Starters**: > **Starters** are a convenient set of dependency descriptors that you can include in your application. They act as a one-stop shop for all the Spring and related technologies you need—without having to search through sample code or copy-paste multiple dependency entries. > For example, if you want to start using **Spring + JPA** for database access, simply include the `spring-boot-starter-data-jpa` dependency in your project, and you’re good to go. --- ### Example: Spring Boot Starter Web If you want to: - Develop a **web application**, or - Expose **RESTful services**, then **`spring-boot-starter-web`** is the right starter to use. Let’s create a simple project with **Spring Boot Starter Web** using **Spring Initializr**. --- ### Dependency for Spring Boot Starter Web ```xml org.springframework.boot spring-boot-starter-web ``` The screenshot below shows the dependencies added to our application by the `spring-boot-starter-web` starter. ![Image](/images/SpringBootStarterWeb-Dependencies.png "Spring Boot Starter Web - Dependencies") ## Dependencies in Spring Boot Starter Web Dependencies in a typical web application can be grouped as follows: - **Spring** – core, beans, context, aop - **Web MVC** – Spring MVC - **Jackson** – for JSON binding - **Validation** – Hibernate Validator, Validation API - **Embedded Servlet Container** – Tomcat - **Logging** – Logback, SLF4J Any typical web application would use all of these. The **Spring Boot Starter Web** bundles them together, so as a developer you don’t need to worry about choosing or managing compatible versions. --- ## Spring Boot Starter Project Options Starter projects make it easy to get started with specific types of applications. Examples include: - **spring-boot-starter-web-services** – SOAP Web Services - **spring-boot-starter-web** – Web & RESTful applications - **spring-boot-starter-test** – Unit and integration testing - **spring-boot-starter-jdbc** – Traditional JDBC access - **spring-boot-starter-hateoas** – Add HATEOAS features to services - **spring-boot-starter-security** – Authentication & authorization with Spring Security - **spring-boot-starter-data-jpa** – Spring Data JPA with Hibernate - **spring-boot-starter-cache** – Enable Spring Framework’s caching support - **spring-boot-starter-data-rest** – Expose REST services using Spring Data REST --- ## Other Goals of Spring Boot In addition to application-specific starters, there are also starters for technical concerns: - **spring-boot-starter-actuator** – Advanced monitoring and tracing out of the box - **spring-boot-starter-undertow**, **spring-boot-starter-jetty**, **spring-boot-starter-tomcat** – Choose your embedded servlet container - **spring-boot-starter-logging** – Logging with Logback - **spring-boot-starter-log4j2** – Logging with Log4j2 Spring Boot’s broader goals include enabling **production-ready applications quickly** by providing: - **Actuator** – Built-in monitoring, health checks, and tracing - **Embedded server integration** – No need for an external application server; everything runs inside the application - **Default error handling** – Sensible defaults for error responses ================================================ FILE: _blog/articles/2017-07-05-introduction-to-jpa-with-spring-boot.md ================================================ --- layout: post title: JPA and Hibernate Tutorial using Spring Boot Data JPA date: 2025-09-13 12:31:19 summary: Complete journey starting from JDBC to JPA to Spring Data JPA using an example with Spring Boot Data JPA starter project. We use Hibernate as the JPA Implementation. categories: SpringBootJPA permalink: /introduction-to-jpa-with-spring-boot-data-jpa image: /images/spring-data-category.png --- ![Image](/images/JPA_02_Architecture.png "JPA Architecuture") This guide introduces **JPA** and walks you through setting up a simple example in **Spring Boot**. ![Image](/images/JPA_01_Introduction.png "JPA Introduction") ## You Will Learn - **What is JPA?** - **The problem JPA solves** – Object-Relational Impedance Mismatch - **Alternatives to JPA** - **What is Hibernate, and how does it relate to JPA?** - **What is Spring Data JPA?** - **How to create a simple JPA project** using the Spring Boot Data JPA Starter ## You Will Need the Following Tools - **Maven 3.0+** – Build and dependency management tool - **An IDE of your choice** – for example, Eclipse or IntelliJ IDEA - **JDK 17+** – Java Development Kit - **H2 Database** – In-memory database for quick setup and testing ## What is Object Relational Impedance Mismatch? ![Image](/images/JPA_01_Introduction.png "JPA Introduction") Java is an object-oriented programming language, where all data is represented and managed through objects. In most applications, data is stored in relational databases (although NoSQL databases are also gaining popularity, we will not focus on them here). Relational databases store data in tables. However, the way we design objects in Java is very different from how relational databases are structured, leading to what is known as an *impedance mismatch*. - **Object-oriented programming** uses concepts like encapsulation, inheritance, interfaces, and polymorphism. - **Relational databases** organize data into tables and follow principles such as normalization. ### Examples of Object-Relational Impedance Mismatch Let’s take a simple example involving **Employees** and **Tasks**. - Each `Employee` can be assigned multiple tasks. - Each `Task` can be shared by multiple employees. This creates a **many-to-many relationship** between `Employee` and `Task`. Now, let’s look at some examples of impedance mismatch. #### Example 1: Column Naming Differences Suppose the `Task` class in Java has fields like `taskId` and `taskDescription`. In the database, the corresponding table might use column names such as `id` and `description`. Even though they represent the same data, the mismatch in naming conventions between objects and database tables creates friction in mapping. ```java public class Task { private int id; private String desc; private Date targetDate; private boolean isDone; private List employees; } ``` ```sql CREATE TABLE task ( id INTEGER GENERATED BY DEFAULT AS IDENTITY, description VARCHAR(255), is_done BOOLEAN, target_date TIMESTAMP, PRIMARY KEY (id) ) ``` #### Example 2: Differences in Representing Relationships In Java, relationships between objects are expressed differently than relationships between tables in a database. For example: - Each `Employee` object can have multiple `Task` objects. - Each `Task` object can be associated with multiple `Employee` objects. This creates a **many-to-many relationship**. In a relational database, representing this relationship typically requires a **join table**, which adds an extra layer of complexity when mapping objects to tables. ```java public class Employee { //Some other code private List tasks; } public class Task { //Some other code private List employees; } ``` ```sql CREATE TABLE employee ( id BIGINT NOT NULL, OTHER_COLUMNS ) CREATE TABLE employee_tasks ( employees_id BIGINT NOT NULL, tasks_id INTEGER NOT NULL ) CREATE TABLE task ( id INTEGER GENERATED BY DEFAULT AS IDENTITY, OTHER_COLUMNS ) ``` #### Example 3: Sometimes multiple classes are mapped to a single table and vice versa. Objects ```java public class Employee { //Other Employee Attributes } public class FullTimeEmployee extends Employee { protected Integer salary; } public class PartTimeEmployee extends Employee { protected Float hourlyWage; } ``` Tables ```sql CREATE TABLE employee ( employee_type VARCHAR(31) NOT NULL, id BIGINT NOT NULL, city VARCHAR(255), state VARCHAR(255), street VARCHAR(255), zip VARCHAR(255), hourly_wage FLOAT, --PartTimeEmployee salary INTEGER, --FullTimeEmployee PRIMARY KEY (id) ) ``` ## Other Approaches Before JPA — JDBC, Spring JDBC & MyBatis Before JPA, most approaches focused on **writing queries** and **mapping query results to objects**. Typically, any query-based approach involves two main tasks: - **Setting query parameters** – reading values from objects and assigning them as parameters to the query. - **Mapping query results** – converting the results returned by the query into Java objects (beans). ### JDBC - JDBC stands for Java Database Connectivity. - It used concepts like Statement, PreparedStatement, and ResultSet. - In the example below, the query used is ```Update todo set user=?, desc=?, target_date=?, is_done=? where id=?``` - The values required to execute the query are set using various `set` methods on the **PreparedStatement**. - The results returned by the query are stored in a **ResultSet**, and we must manually map these results into Java objects. #### Update Todo ```java Connection connection = datasource.getConnection(); PreparedStatement st = connection.prepareStatement("Update todo set user=?, desc=?, target_date=?, is_done=? where id=?"); st.setString(1,todo.getUser()); st.setString(2,todo.getDesc()); st.setTimestamp(3,new Timestamp(todo.getTargetDate().getTime())); st.setBoolean(4,todo.isDone()); st.setInt(5,todo.getId()); st.execute(); st.close(); connection.close(); ``` #### Retrieved by Todo ```java Connection connection = datasource.getConnection(); PreparedStatement st = connection.prepareStatement( "SELECT * FROM TODO where id=?"); st.setInt(1,id); ResultSet resultSet = st.executeQuery(); if(resultSet.next()) { Todo todo = new Todo(); todo.setId(resultSet.getInt("id")); todo.setUser(resultSet.getString("user")); todo.setDesc(resultSet.getString("desc")); todo.setTargetDate(resultSet.getTimestamp("target_date")); return todo; } st.close(); connection.close(); return null; ``` ### Spring JDBC - **Spring JDBC** provides a higher-level abstraction over standard JDBC. - It introduces concepts like **JdbcTemplate**. - Typically, requires fewer lines of code compared to plain JDBC, because it simplifies: - Mapping parameters to queries - Converting (mapping) result sets into Java objects (beans) #### Update Todo ```java jdbcTemplate.update("Update todo set user=?, desc=?, target_date=?, is_done=? where id=?", todo.getUser(), todo.getDesc(), new Timestamp(todo.getTargetDate().getTime()), todo.isDone(), todo.getId()); ``` #### Retrieve a Todo ```java @Override public Todo retrieveTodo(int id) { return jdbcTemplate.queryForObject( "SELECT * FROM TODO where id=?", new Object[]{id}, new TodoMapper()); } ``` Reusable Row Mapper ```java // new BeanPropertyRowMapper(TodoMapper.class) class TodoMapper implements RowMapper { @Override public Todo mapRow(ResultSet rs, int rowNum) throws SQLException { Todo todo = new Todo(); todo.setId(rs.getInt("id")); todo.setUser(rs.getString("user")); todo.setDesc(rs.getString("desc")); todo.setTargetDate(rs.getTimestamp("target_date")); todo.setDone(rs.getBoolean("is_done")); return todo; } } ``` ### MyBatis **MyBatis** eliminates the need to manually write code for setting query parameters and mapping results. It provides a simple **XML- or annotation-based configuration** to map Java POJOs to database tables. Below, we compare the approaches used to write queries in different frameworks. - **JDBC or Spring JDBC** ```sql UPDATE todo SET user=?, desc=?, target_date=?, is_done=? WHERE id=? ``` - **MyBatis** ```sql UPDATE todo SET user=#{user}, desc=#{desc}, target_date=#{targetDate}, is_done=#{isDone} WHERE id=#{id} ``` #### Todo Update and Todo Retrieve ```java @Mapper public interface TodoMybatisService extends TodoDataService { @Override @Update("Update todo set user=#{user}, desc=#{desc}, target_date=#{targetDate}, is_done=#{isDone} where id=#{id}") void updateTodo(Todo todo) throws SQLException; @Override @Select("SELECT * FROM TODO WHERE id = #{id}") Todo retrieveTodo(int id) throws SQLException; } public class Todo { private int id; private String user; private String desc; private Date targetDate; private boolean isDone; } ``` ### Common Features of JDBC, Spring JDBC, and MyBatis - All three approaches—**JDBC**, **Spring JDBC**, and **MyBatis**—require writing SQL queries. - In large applications, queries can become complex, especially when retrieving data from multiple tables. - This complexity creates problems whenever the **database structure changes**, requiring updates to all affected queries. --- ## How Does JPA Work? **JPA** was designed with a different approach: instead of focusing on queries, it maps **Java objects directly to database tables**. Key concepts include: - **Entities** – Java classes that represent database tables - **Attributes** – Fields in the class that correspond to table columns - **Relationships** – Associations between entities, such as one-to-many or many-to-many This process is known as **Object-Relational Mapping (ORM)**. Before JPA, the term ORM was commonly used to describe frameworks like **Hibernate**, which is why Hibernate is often referred to as an ORM framework. ## Important Concepts in JPA ![Image](/images/JPA_02_Architecture.png "JPA Architecuture") **JPA** allows you to map application classes directly to database tables. - **Entity Manager** – Once mappings are defined, the Entity Manager manages your entities and handles all interactions with the database. - **JPQL (Java Persistence Query Language)** – Provides a way to write queries against entities. Unlike SQL, JPQL understands the mappings between entities and tables, allowing you to add conditions as needed. - **Criteria API** – Offers a Java-based API to build and execute queries programmatically against the database. ## JPA vs Hibernate **Hibernate** is one of the most popular **ORM frameworks**. **JPA** defines the **specification** and provides an **API**, answering key questions like: - How do you define entities? - How do you map attributes? - How do you map relationships between entities? - Who manages the entities? **Hibernate** is a widely used implementation of JPA: - It understands the mappings defined between objects and database tables, ensuring that data is stored and retrieved correctly. - Hibernate also offers additional features beyond JPA. However, relying on these features creates a **vendor lock-in**, making it difficult to switch to other JPA implementations such as TopLink. ## Examples of JPA Mappings Let’s look at a few examples to understand how **JPA** can be used to map objects to database tables. #### Example 1 Suppose we have a `Task` class that we want to map to a `Task` table. There may be differences in column names between the class and the table. JPA provides annotations to handle this mapping: - `@Table(name = "Task")` – Maps the class to the database table. - `@Id` – Marks the primary key of the entity. - `@GeneratedValue` – Specifies that the primary key value will be generated automatically. - `@Column(name = "description")` – Maps the class attribute to a specific column in the table. ```java import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.ManyToMany; import jakarta.persistence.Table; @Entity @Table(name = "Task") public class Task { @Id @GeneratedValue private int id; @Column(name = "description") private String desc; @Column(name = "target_date") private Date targetDate; @Column(name = "is_done") private boolean isDone; } ``` ```sql CREATE TABLE task ( id INTEGER GENERATED BY DEFAULT AS IDENTITY, description VARCHAR(255), is_done BOOLEAN, target_date TIMESTAMP, PRIMARY KEY (id) ) ``` #### Example 2 Relationships between objects are expressed differently than relationships between database tables. For example: - Each `Employee` can have multiple `Tasks`. - Each `Task` can be associated with multiple `Employees`. This creates a **many-to-many relationship**, which can be mapped in JPA using the `@ManyToMany` annotation. ```java public class Employee { //Some other code @ManyToMany private List tasks; } public class Task { //Some other code @ManyToMany(mappedBy = "tasks") private List employees; } ``` ```sql CREATE TABLE employee ( id BIGINT NOT NULL, OTHER_COLUMNS ) CREATE TABLE employee_tasks ( employees_id BIGINT NOT NULL, tasks_id INTEGER NOT NULL ) CREATE TABLE task ( id INTEGER GENERATED BY DEFAULT AS IDENTITY, OTHER_COLUMNS ) ``` #### Example 3 Sometimes, multiple classes need to be mapped to a single table, or a single class needs to be mapped across multiple tables. In such cases, we define an **inheritance strategy**. For example, the strategy `InheritanceType.SINGLE_TABLE` maps an entire class hierarchy to a **single database table**. ```java @Entity @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "EMPLOYEE_TYPE") public class Employee { //Other Employee Attributes } public class FullTimeEmployee extends Employee { protected Integer salary; } public class PartTimeEmployee extends Employee { protected Float hourlyWage; } ``` Tables ```sql CREATE TABLE employee ( employee_type VARCHAR(31) NOT NULL, id BIGINT NOT NULL, city VARCHAR(255), state VARCHAR(255), street VARCHAR(255), zip VARCHAR(255), hourly_wage FLOAT, --PartTimeEmployee salary INTEGER, --FullTimeEmployee PRIMARY KEY (id) ) ``` ## Step-by-Step Code Example ### Bootstrapping a Web application with Spring Initializr Creating a JPA application with Spring Initializr is very simple. ![Image](/images/Spring-Initializr-Web.png "Web, Actuator and Developer Tools") As shown in the image above, follow these steps to create your Spring Boot project: - Launch **Spring Initializr**: [http://start.spring.io/](http://start.spring.io/){:target="_blank"} - Set **Group** to `com.in28minutes.springboot` - Set **Artifact** to `H2InMemoryDbDemo` - Add the following **dependencies**: - **Web** - **JPA** - **H2** – an in-memory database used for this example - Click the **Generate** button at the bottom of the page. - Import the generated project into **Eclipse**. #### Project Structure - **H2InMemoryDbDemoApplication.java** – Spring Boot launcher that initializes Auto Configuration and the Application Context. - **application.properties** – Application configuration file. - **H2InMemoryDbDemoApplicationTests.java** – Simple launcher for unit testing. - **pom.xml** – Includes dependencies for Spring Boot Starter Web and Data JPA, and uses Spring Boot Starter Parent as the parent POM. Important dependencies are listed below. ```xml org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa com.h2database h2 runtime org.springframework.boot spring-boot-h2console 4.0.0-M1 // you can it in if you're creating a Spring Boot application ``` ### User Entity Let's define a bean user and add the appropriate JPA annotations. ```java package com.example.h2.user; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.NamedQuery; @Entity @NamedQuery(query = "select u from User u", name = "query_find_all_users") public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name;// Not perfect!! Should be a proper object! private String role;// Not perfect!! An enum should be a better choice! protected User() { } public User(String name, String role) { super(); this.name = name; this.role = role; } } ``` ### Important Annotations and Concepts - `@Entity` – Specifies that the class is a JPA entity. Apply this annotation to the entity class. - `@NamedQuery` – Defines a static, named query in **Java Persistence Query Language (JPQL)**. - `@Id` – Marks the primary key of an entity. - `@GeneratedValue` – Specifies how the primary key value should be automatically generated. - `protected User()` – Default constructor required by JPA to instantiate the entity. ## User Service to Interact with the Entity Manager With JPA, it is common to create a **service layer** to interact with the **Entity Manager**. In this example, we create a `UserService` to manage the persistence operations for the `User` entity. ```java @Repository @Transactional public class UserService { @PersistenceContext private EntityManager entityManager; public long insert(User user) { entityManager.persist(user); return user.getId(); } public User find(long id) { return entityManager.find(User.class, id); } public List findAll() { Query query = entityManager.createNamedQuery( "query_find_all_users", User.class); return query.getResultList(); } } ``` ### Important Annotations and Concepts - `@Repository` – A Spring annotation indicating that this component is responsible for **data access** and interacting with a data store. - `@Transactional` – A Spring annotation that simplifies **transaction management**. - `@PersistenceContext` – Injects a **persistence context**, which manages a set of entities and tracks their states (e.g., managed, detached) in relation to the underlying database. - `EntityManager` – The interface used to interact with the **persistence context**. - `entityManager.persist(user)` – Makes the `user` entity **managed and persistent**, i.e., saves it to the database. - `entityManager.createNamedQuery` – Creates a **TypedQuery** to execute a JPQL **named query**. The second parameter specifies the expected result type. > An **EntityManager** instance is associated with a **persistence context**. > A persistence context is a set of entity instances in which each persistent entity identity corresponds to a unique entity instance. > Within this context, the lifecycle of entities is managed. The **EntityManager API** is used to create and remove persistent entities, find entities by their primary key, and execute queries over entities. > The set of entities managed by an EntityManager is defined by a **persistence unit**. > A persistence unit specifies all classes related or grouped by the application that must be mapped to a single database. --- ## CommandLineRunner for User Entity Manager The **CommandLineRunner** interface is used to indicate that a Spring bean should run **as soon as the application context is initialized**. In this example, we execute a few simple methods on the `UserService` to demonstrate entity persistence and queries. ```java @Component public class UserEntityManagerCommandLineRunner implements CommandLineRunner { private static final Logger log = LoggerFactory.getLogger(UserEntityManagerCommandLineRunner.class); @Autowired private UserService userService; @Override public void run(String... args) { log.info("-------------------------------"); log.info("Adding Tom as Admin"); log.info("-------------------------------"); User tom = new User("Tom", "Admin"); userService.insert(tom); log.info("Inserted Tom" + tom); log.info("-------------------------------"); log.info("Finding user with id 1"); log.info("-------------------------------"); User user = userService.find(1L); log.info(user.toString()); log.info("-------------------------------"); log.info("Finding all users"); log.info("-------------------------------"); log.info(userService.findAll().toString()); } } ``` ### Important Things to Note - `@Autowired private UserService userService` – The `UserService` is automatically injected by Spring. - The remaining setup and configuration are straightforward. --- ## Spring Data JPA **Spring Data JPA** provides a consistent and simplified model for accessing data from different types of data stores. The `UserService` we created earlier contains some redundant code that can be generalized. **Spring Data JPA** helps reduce boilerplate code and simplifies data access. ```java @Repository @Transactional public class UserService { @PersistenceContext private EntityManager entityManager; public long insert(User user) { entityManager.persist(user); return user.getId(); } public User find(long id) { return entityManager.find(User.class, id); } public List findAll() { Query query = entityManager.createNamedQuery( "query_find_all_users", User.class); return query.getResultList(); } } ``` As far as **JPA** is concerned, there are two key **Spring Data** modules to know: - **Spring Data Commons** – Defines concepts that are shared across all Spring Data modules. - **Spring Data JPA** – Provides easy integration with **JPA repositories**. --- ### CrudRepository **CrudRepository** is a core repository interface provided by **Spring Data Commons**. It enables basic CRUD operations on a repository. Some important methods include: ```java public interface CrudRepository extends Repository { S save(S entity); T findOne(ID primaryKey); Iterable findAll(); Long count(); void delete(T entity); boolean exists(ID primaryKey); // … more functionality omitted. } ``` ### JpaRepository **JpaRepository**, provided by **Spring Data JPA**, is a JPA-specific repository interface that extends `CrudRepository`. It offers additional JPA-related methods, such as flushing changes to the database and batch operations, while retaining all CRUD functionalities. ```java public interface JpaRepository extends PagingAndSortingRepository, QueryByExampleExecutor { ``` We will now use **JpaRepository** to manage the `User` entity. The key idea is to create a **UserRepository** that manages `User` entities, where the primary key is of type `Long`. The snippet below highlights the important details for defining this repository. ```java package com.example.h2.user; import org.springframework.data.jpa.repository.JpaRepository; public interface UserRepository extends JpaRepository { } ``` ### User Repository: CommandLineRunner The following code is straightforward. The **CommandLineRunner** interface indicates that this bean should run **as soon as the Spring application context is initialized**. In this example, we execute a few simple methods on the **UserRepository** to demonstrate basic CRUD operations. ```java package com.example.h2; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import com.example.h2.user.User; import com.example.h2.user.UserRepository; @Component public class UserRepositoryCommandLineRunner implements CommandLineRunner { private static final Logger log = LoggerFactory.getLogger(UserRepositoryCommandLineRunner.class); @Autowired private UserRepository userRepository; @Override public void run(String... args) { User harry = new User("Harry", "Admin"); userRepository.save(harry); log.info("-------------------------------"); log.info("Finding all users"); log.info("-------------------------------"); for (User user : userRepository.findAll()) { log.info(user.toString()); } } } ``` ### Important Things to Note - `@Autowired private UserRepository userRepository` – The `UserRepository` is automatically injected by Spring. - The rest of the setup is straightforward. --- ### H2 Console Enable the H2 console in `/src/main/resources/application.properties`: ```properties spring.h2.console.enabled=true ``` Start the application by running H2InMemoryDbDemoApplication as a Java application. The H2-Console can also be accessed via the web browser. - http://localhost:8080/h2-console - Use db url jdbc:h2:mem:testdb ### Questions - **Where was the database created?** - In memory, using H2. - **What schema is used to create the tables?** - Tables are created automatically based on the entity definitions. - **Where are the tables created?** - In memory, using H2, based on the entity definitions. - **Can I see the data in the database?** - http://localhost:8080/h2-console - Use db url jdbc:h2:mem:testdb - **Where is Hibernate coming from?** - Provided by the **Spring Data JPA Starter**. - **How is a data source created?** - Automatically configured through **Spring Boot Auto Configuration**. ### Spring Boot's Magic with In-Memory Databases - No project setup or additional infrastructure required. - Zero configuration. - Minimal maintenance. - Easy to use for learning and unit testing. - Simple to switch to a real database with minimal configuration. --- ### Restrictions of Using In-Memory Databases - Data is **not persisted** between application restarts. ## Complete Code Example ### /pom.xml ```xml 4.0.0 com.example jpa-in-10-steps 0.0.1-SNAPSHOT jar jpa-with-in-memory-db-in-10-steps Demo project for in memory database H2 org.springframework.boot spring-boot-starter-parent 4.0.0-M2 21 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa com.h2database h2 runtime org.springframework.boot spring-boot-h2console org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin ``` --- ### /src/main/java/com/example/h2/H2InMemoryDbDemoApplication.java ```java package com.example.h2; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class H2InMemoryDbDemoApplication { static void main(String[] args) { SpringApplication.run(H2InMemoryDbDemoApplication.class, args); } } ``` --- ### /src/main/java/com/example/h2/user/User.java ```java package com.example.h2.user; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.NamedQuery; @Entity @NamedQuery(query = "select u from User u", name = "query_find_all_users") public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name;// Not perfect!! Should be a proper object! private String role;// Not perfect!! An enum should be a better choice! protected User() { } public User(String name, String role) { super(); this.name = name; this.role = role; } public Long getId() { return id; } public String getName() { return name; } public String getRole() { return role; } @Override public String toString() { return String.format("User [id=%s, name=%s, role=%s]", id, name, role); } } ``` --- ### /src/main/java/com/example/h2/user/UserRepository.java ```java package com.example.h2.user; import org.springframework.data.jpa.repository.JpaRepository; public interface UserRepository extends JpaRepository { } ``` --- ### /src/main/java/com/example/h2/user/UserService.java ```java package com.example.h2.user; import java.util.List; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.persistence.Query; import jakarta.transaction.Transactional; import org.springframework.stereotype.Repository; @Repository @Transactional public class UserService { @PersistenceContext private EntityManager entityManager; public long insert(User user) { entityManager.persist(user); return user.getId(); } public User find(long id) { return entityManager.find(User.class, id); } public List findAll() { Query query = entityManager.createNamedQuery( "query_find_all_users", User.class); return query.getResultList(); } } ``` --- ### /src/main/java/com/example/h2/UserEntityManagerCommandLineRunner.java ```java package com.example.h2; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import com.example.h2.user.User; import com.example.h2.user.UserService; @Component public class UserEntityManagerCommandLineRunner implements CommandLineRunner { private static final Logger log = LoggerFactory.getLogger(UserEntityManagerCommandLineRunner.class); @Autowired private UserService userService; @Override public void run(String... args) { log.info("-------------------------------"); log.info("Adding Tom as Admin"); log.info("-------------------------------"); User tom = new User("Tom", "Admin"); userService.insert(tom); log.info("Inserted Tom" + tom); log.info("-------------------------------"); log.info("Finding user with id 1"); log.info("-------------------------------"); User user = userService.find(1L); log.info(user.toString()); log.info("-------------------------------"); log.info("Finding all users"); log.info("-------------------------------"); log.info(userService.findAll().toString()); } } ``` --- ### /src/main/java/com/example/h2/UserRepositoryCommandLineRunner.java ```java package com.example.h2; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; import com.example.h2.user.User; import com.example.h2.user.UserRepository; @Component public class UserRepositoryCommandLineRunner implements CommandLineRunner { private static final Logger log = LoggerFactory.getLogger(UserRepositoryCommandLineRunner.class); @Autowired private UserRepository userRepository; @Override public void run(String... args) { User harry = new User("Harry", "Admin"); userRepository.save(harry); log.info("-------------------------------"); log.info("Finding all users"); log.info("-------------------------------"); for (User user : userRepository.findAll()) { log.info(user.toString()); } } } ``` --- ### /src/main/resources/application.properties ```properties spring.h2.console.enabled=true #logging.level.org.hibernate=debug spring.jpa.show-sql=true spring.datasource.url=jdbc:h2:mem:testdb;NON_KEYWORDS=USER spring.data.jpa.repositories.bootstrap-mode=default spring.jpa.defer-datasource-initialization=true ``` --- ### /src/main/resources/data.sql ```sql insert into user (id, name, role) values (101, 'Ranga', 'Admin'); insert into user (id, name, role) values (102, 'Ravi', 'User'); insert into user (id, name, role) values (103, 'Satish', 'Admin'); ``` --- ### /src/test/java/com/example/h2/H2InMemoryDbDemoApplicationTests.java ```java package com.example.h2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit.jupiter.SpringExtension; @ExtendWith(SpringExtension.class) @SpringBootTest public class H2InMemoryDbDemoApplicationTests { @Test public void contextLoads() { } } ``` --- ### /src/test/java/com/example/h2/user/UserRepositoryTest.java ```java package com.example.h2.user; import static org.junit.Assert.assertEquals; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; import org.springframework.test.context.junit.jupiter.SpringExtension; import com.example.h2.user.UserRepository; @DataJpaTest @ExtendWith(SpringExtension.class) public class UserRepositoryTest { @Autowired UserRepository userRepository; @Autowired TestEntityManager entityManager; @Test public void check_todo_count() { assertEquals(3, userRepository.count()); } } ``` --- ================================================ FILE: _blog/articles/2017-07-06-introduction-to-web-services-restful-and-soap.md ================================================ --- layout: post title: Introduction to Web Services - Restful and SOAP date: 2025-09-16 12:31:19 summary: Introduction to Web Services - Restful and SOAP, This tutorial will help you understand the basics of web services and the different kinds of web services - REST and SOAP. categories: SwArchitecture permalink: /introduction-to-web-services-with-soap-and-rest image: /images/spring-boot-application.png --- In this tutorial, you’ll learn the fundamentals of web services and explore the two primary types—REST and SOAP. ## You will learn - What web services are - The advantages of using web services - The main types of web services - An introduction to RESTful web services - An introduction to SOAP web services ## You will require the following tools: - **Maven 3.0+** as the build tool - **JDK 17+** for running Java applications - **An IDE of your choice** (e.g., Eclipse or IntelliJ IDEA) # What is a Web Service? > **Service delivered over the web** Is this really a complete definition? Does everything delivered over the web qualify as a *web service*? For example, consider a web application we developed in our Spring MVC course to manage to-dos. ![Image](/images/Web_Services_Web_Application_To_Manage_Todos.png) ## Is this application a web service? > Nope. The answer is no. This is a **web application**, not a web service. So, we are back to square one: - What is a web service? - How is it different from a web application? --- ## Understanding the difference Let’s consider an example: Mark Zuckerberg likes the **To-Do application** we developed in our Spring MVC course. He believes it’s a perfect fit to integrate into Facebook so users can manage their tasks directly inside Facebook. Can we use the existing application for this integration? **No.** ### Why not? Because the current application is designed for **humans**. - Its output is **HTML**, which is rendered by the browser. - It is not designed for other **applications** to consume. --- ## Thinking differently What if I wanted to design the To-Do application so that **other applications** could interact with it? > I would need to produce the output in a format that other systems could understand. Then, Facebook could call my web > service and integrate with it. --- ## W3C Definition of a Web Service > **A software system designed to support interoperable machine-to-machine interaction over a network.** --- ## Key Takeaways - Web services are designed for **machine-to-machine (or application-to-application)** interaction. - They are **interoperable**, meaning not tied to a single platform or technology. - They enable **communication over a network**. --- ## Web Service Data Exchange Formats Now, let’s revisit our example: Facebook wants to talk to the To-Do application. - Facebook uses multiple technologies: PHP (frontend), Erlang (chat), Java and C++ (backend). - The To-Do application is built with **Java (Spring MVC)**. Even though these systems use **different technologies**, we still want them to communicate. That’s where **standard data exchange formats** come in—allowing seamless interaction between diverse platforms. ![Image](/images/Web_Service_Basic_Interaction.png) ## Requests and Responses Both applications must be able to understand the **request** and the **response**. So, what formats should we use? > They should be **standard formats** so that they can work across different platforms. > JSON and XML are the most popular data exchange formats. --- ## Types of Web Services This is more of a **broad classification** rather than strict types: - **SOAP** - **REST** These are not always mutually exclusive. Some SOAP services can also be RESTful. So the key question is: > When does a web service become a SOAP web service or a RESTful web service? --- ### SOAP SOAP originally stood for **Simple Object Access Protocol**. - SOAP requests and responses are always in **XML format**. - But not every XML is valid SOAP. SOAP defines its own standard XML structure. - WSDL (Web Service Definition Language) is used to describe the format of the request and response. If Facebook wanted to call the **To-Do service**, what would we give their developers? We would provide the **WSDL file**, which explains: - The different operations (services) exposed by the server - The endpoint (URL) to use for each operation - The structure of the request XML - The structure of the response XML #### SOAP Message Structure A SOAP message is wrapped inside a **SOAP-Envelope**: - **SOAP-Header** (optional): Metadata such as authentication, authorization, or encryption info - **SOAP-Body**: The actual request/response content - **SOAP-Fault**: Error messages returned in case of failure --- ### REST Unlike SOAP, **REST does not define a standard message format**. - REST services can use **XML** or **JSON** (JSON is more popular). So, what exactly is REST? > REST is an **architectural style** for distributed systems, based on the idea of **resources**. #### Key Concepts - **Resource**: Anything that can be identified—e.g., a todo item, a Facebook user - **Resource URI**: Identifies a resource - `/user/Ranga/todos/1` - `/person/Ranga` - **Resource Representation**: Describes the resource’s current state (XML, JSON, HTML) When a resource is requested, its **representation** is returned. --- #### REST and HTTP REST is built on top of **HTTP (the language of the web)**. **HTTP Methods (Verbs):** - **POST** – Create a new resource - **GET** – Read a resource - **PUT** – Update an existing resource - **DELETE** – Delete a resource **HTTP Response Codes:** - `200` – SUCCESS - `201` – CREATED - `400` – BAD REQUEST - `401` – UNAUTHORIZED - `404` – RESOURCE NOT FOUND - `415` – UNSUPPORTED TYPE - `500` – SERVER ERROR --- #### REST Constraints - **Client-Server**: Clear separation of consumer and provider - **Uniform Interface**: Resources exposed through consistent URIs (nouns, not actions) - **Stateless**: Each request is independent, no session data stored on the server - **Cacheable**: Responses can be cached (e.g., HTTP cache) - **Layered System**: Clients should not assume a direct connection to the server; intermediaries may exist --- ### Richardson Maturity Model The **Richardson Maturity Model** defines the maturity of REST services: - **Level 0**: Use REST endpoints but keep action-based URIs (e.g., `/getPosts`, `/deletePosts`) - **Level 1**: Use resources with proper URIs (`/accounts`, `/accounts/10`) but ignore HTTP methods - **Level 2**: Use proper URIs **and** HTTP methods (`PUT /accounts/1`, `POST /accounts`) - **Level 3**: HATEOAS (Hypermedia as the Engine of Application State) – responses include links to possible next actions --- ### Designing RESTful APIs When designing REST APIs, keep these points in mind: - Focus on the **API consumer**: Does the request/response format make sense for them? - Use **nouns (resources)** in URIs, not verbs. Prefer plurals. - Use **hierarchical and self-descriptive URIs**. - Always use the correct **HTTP methods**: - **GET** – Read (idempotent, multiple calls = same result) - **POST** – Create (returns `201 Created`, often with link to new resource) - **PUT** – Update (returns `200 OK`) - **DELETE** – Remove (returns `200 OK` or `204 No Content`) --- ## REST vs SOAP - **REST** is an **architectural style**. - **SOAP** is a **protocol/message format**. **Typical implementations:** - RESTful services: JSON over HTTP - SOAP services: XML over SOAP over HTTP **Key Comparisons:** - REST is **simpler** to implement and consume. - REST offers better **performance and scalability** (caching supported). - REST supports multiple formats (JSON, XML, etc.); SOAP only uses XML. - SOAP has **strict standards** (WSDL, WS-Security, WS-ReliableMessaging). REST documentation is evolving ( Swagger/OpenAPI). --- ## Advantages of Web Services - **Reuse**: Facebook doesn’t need to build its own To-Do app—just reuse ours. - **Modularity**: Applications can be broken into smaller, independent services. - **Language Neutrality**: Services can be consumed across different languages and platforms. Web services are the foundation of **SOA (Service-Oriented Architecture)** and **Microservices architectures**. ## SOAP Service Examples ### Request ```xml Course1 ``` ### Response ```xml Course1 Spring 10 Steps ``` ### Fault ```xml SOAP-ENV:Server java.lang.NullPointerException ``` ### WSDL - view-source:http://localhost:8080/ws/courses.wsdl ```xml ``` ================================================ FILE: _blog/articles/2017-10-11-spring-boot-master-class.md ================================================ --- layout: post title: Spring Boot For Beginners in 100 Steps date: 2025-09-18 12:31:19 summary: Understand and love the power of Spring Boot - All its features are illustrated developing a web application managing todos and a basic API for survey questionnaire. Also covers unit testing, mocking and integration testing. categories: SpringBoot permalink: /spring-boot-for-beginners-and-experts image: /images/generic-category.png --- Spring Boot has a lot of **magic** going for it. Developing applications with Spring Boot is both **cool** and **fun**. It makes it easy to create **stand-alone, production-grade Spring applications** that you can *just run*. Most Spring Boot applications require **minimal configuration**, letting you focus on business logic rather than boilerplate setup. > You will explore the key concepts of Spring Boot and discover how Starter projects simplify application development. [![Image](/images/Course-Learn-Spring-Boot-in-100-Steps---Beginner-to-Expert.png "Learn Spring Boot in 100 Steps - Beginner to Expert")](https://links.in28minutes.com/MISC-SPRING-BOOT) ## What you will learn You will build: - A web application to manage your to-dos - A basic REST service to manage survey questions This course is a perfect first step into Spring Boot. > You will learn Spring Boot step by step — in more than **90** hands-on steps. You will work with: - REST services - Spring (dependency management) - Spring MVC - Spring Boot and Spring Boot Starter projects - Spring Security (authentication & authorization) - Bootstrap (UI styling) - Maven (dependency management) - Eclipse (IDE) and embedded Tomcat (web server) We’ll help you set up each of these. ### Topics covered - Basics of Spring Boot - Auto-configuration and Spring Boot "magic" - Spring Boot Starter projects and Spring Initializr - DispatcherServlet and request flow - Todo management application with login/logout - Models, Controllers, ViewResolver, and Filters - Forms: data binding and validation - Annotation-based handling: `@RequestParam`, `@ModelAttribute`, `@SessionAttributes`, etc. - Using Bootstrap to style pages - Building REST APIs with Spring Boot Starter Web - Content negotiation (JSON and XML) - Embedded servlet containers: Tomcat, Jetty, Undertow - Unit and integration testing with Spring Boot Starter Test - Profiles and dynamic configuration - Spring Data JPA - Spring Boot Actuator - Spring Security essentials and configuration - Developer tools and LiveReload ## Getting Started ### Installing Tools - **Installation Resources** - 🎥 [Video Playlist](https://www.youtube.com/playlist?list=PLBBog2r6uMCSmMVTW_QmDLyASBvovyAO3) - 📄 [PDF Guide](https://github.com/in28minutes/SpringIn28Minutes/blob/master/InstallationGuide-JavaEclipseAndMaven_v2.pdf) - 📚 [More Details](https://github.com/in28minutes/getting-started-in-5-steps) - **Troubleshooting** - 🛠️ [Troubleshooting Guide (50 pages, 200+ errors and FAQs answered)](https://github.com/in28minutes/in28minutes-initiatives/blob/master/The-in28Minutes-TroubleshootingGuide-And-FAQ) ### Running Examples 1. Download the ZIP file or clone the Git repository. 2. Unzip the ZIP file (if you downloaded one). 3. Open **Command Prompt/Terminal** and navigate (`cd`) to the folder containing `pom.xml`. 4. Open **Eclipse**: - Go to **File → Import → Existing Maven Project** - Navigate to the folder where you unzipped the project - Select the correct project 5. Locate the Spring Boot Application file (look for the class annotated with `@SpringBootApplication`). 6. Right-click the file → **Run As → Java Application**. 7. ✅ You’re all set! 8. For help: [Installation Guide (Video Playlist)](https://www.youtube.com/playlist?list=PLBBog2r6uMCSmMVTW_QmDLyASBvovyAO3) --- ## Spring Level 1 to Level 6 — Section Overview Here’s a quick overview of the different sections of the course: - **Level 1**: Introduction to Spring in 10 Steps - **Level 2**: Develop a Todo Management Web Application in 30 Steps - **Level 3**: Introduction to Unit Testing with JUnit in 5 Steps - **Level 4**: Introduction to Mocking with Mockito in 5 Steps - **Level 5**: Advanced Features of Spring Boot in 25 Steps - Build a simple API for managing a survey questionnaire - **Level 6**: Introduction to JPA in 10 Steps - **Level 7**: Connect the Todo Management Web Application to JPA | Title | Category | Github | |------------------------------------|:----------------:|--------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Spring Framework in 10 Steps | Spring - Level 1 | [Project Folder on Github](https://github.com/in28minutes/spring-master-class/tree/master/01-spring-in-depth) | | Spring in Depth | Spring - Level 2 | [Project Folder on Github](https://github.com/in28minutes/spring-master-class/tree/master/01-spring-in-depth) | | Unit Testing with Spring Framework | Spring - Level 3 | [Project Folder on Github](https://github.com/in28minutes/spring-master-class/tree/master/01-spring-in-depth) | | Spring Boot in 10 Steps | Spring - Level 4 | [Project Folder on Github](https://github.com/in28minutes/spring-master-class/tree/master/00-framework-tool-introductions/05.Spring-Boot-Introduction-In-10-Steps) | | Spring AOP | Spring - Level 5 | [Project Folder on Github](https://github.com/in28minutes/spring-master-class/tree/master/03-spring-aop) | | Spring JDBC and JPA | Spring - Level 6 | [Project Folder on Github](https://github.com/in28minutes/spring-master-class/tree/master/04-spring-jdbc-to-jpa) | ## 5 Bonus Sections - Introduction to Tools and Frameworks | Title | Category | Github | |---------------------------------------|:------------:|---------------------------------------------------------------------------------------------------------------------------------------------------------------| | Eclipse in 5 Steps | Introduction | [Project Folder on Github](https://github.com/in28minutes/spring-master-class/tree/master/00-framework-tool-introductions/01.Eclipse-Introduction-in-5-steps) | | Maven in 5 Steps | Introduction | [Project Folder on Github](https://github.com/in28minutes/spring-master-class/tree/master/00-framework-tool-introductions/02.Maven-Introduction-In-5-Steps) | | JUnit in 5 Steps | Introduction | [Project Folder on Github](https://github.com/in28minutes/spring-master-class/tree/master/00-framework-tool-introductions/03.JUnit-Introduction-In-5-Steps) | | Mockito in 5 Steps | Introduction | [Project Folder on Github](https://github.com/in28minutes/spring-master-class/tree/master/00-framework-tool-introductions/04.Mockito-Introduction-In-5-Steps) | | Basic Web Application with Spring MVC | Introduction | [Project Folder on Github]() | # Step-by-Step Details ### Introductory Modules > **Note:** These introductory modules are organized across the course to enable JIT (Just-In-Time) learning. If you are > new to Spring, don't forget to check the *Introduction to Spring* module in the appendix. - Introduction to JUnit — 5 steps - Introduction to Mockito — 5 steps - Introduction to JPA — 10 steps - Introduction to Spring — 10 steps --- ### Web Application with Spring Boot - **Step 01 — Part 1:** Basic Spring Boot web application setup - **Step 01 — Part 2:** `pom.xml`, Spring Boot application, and `application.properties` - **Step 02 — Part 1:** First Spring MVC controller — `@ResponseBody` vs `@Controller` - **Step 02 — Part 2:** Understanding HTTP request flow - **Step 03:** Demystifying some of the Spring Boot "magic" - **Step 04:** Redirect to Login JSP — `@ResponseBody` and view resolver - **Step 05:** Show user id and password on welcome page — `ModelMap` and `@RequestParam` - **Step 06:** `DispatcherServlet` and Spring MVC flow - **Step 07:** Your first HTML form - **Step 08:** Add hard-coded validation of user id and password - **Step 09:** More Spring "magic" - **Step 10:** Create `TodoController` and `list-todos` view. Make `TodoService` a `@Service` - **Step 11:** Architecture of web applications - **Step 12:** Session vs Model vs Request — `@SessionAttributes` - **Step 13:** Add new to-do - **Step 14:** Display to-dos in a table using JSTL tags - **Step 15:** Bootstrap for page formatting using webjars - **Step 16:** Delete a to-do - **Step 17:** Format "Add Todo" page and add basic HTML5 form validation - **Step 18 — Part 1:** Validations with Hibernate Validator — using command bean - **Step 18 — Part 2:** Using JSR 349 (Bean Validation) - **Step 19:** Updating a to-do - **Step 20:** Add a target date for to-do — use `initBinder` to handle date fields - **Step 21:** JSP fragments and navigation bar - **Step 22:** Preparing for Spring Security - **Step 23:** Initial Spring Security setup - **Step 24:** Refactor and add logout functionality using Spring Security - **Step 25:** Exception handling --- ### Connecting Web Application with JPA > **Note:** Ensure you complete the *Introduction to JPA* module before starting this section. - **Step 26:** Add dependencies for JPA and H2 - **Step 27:** Configure H2 console - **Step 28:** Create `Todo` entity and JPA repository - **Step 29:** Insert `Todo` using JPA repository - **Step 30:** Update, delete, and retrieve to-dos using JPA repository - **Step 31:** Data initialization with `data.sql` - **Step 32:** Connecting JPA to other databases - **Step 33:** Upgrading to Spring Boot 2 and Spring 5 --- ### Spring Boot Deep Dive — Simple API - **Step 01:** Setup and launch Spring Boot application with Maven and Eclipse - **Step 02:** Create your first `@RestController` - **Step 03:** Understanding Spring Boot magic: `spring-boot-starter-web` - **Step 04:** Understanding Spring Boot magic: `spring-boot-starter-parent` - **Step 05:** Spring Boot vs Spring framework - **Step 06:** Create services for survey and questions - **Step 07:** What is REST? Create REST service with `@GetMapping` and `@PathVariable` - **Step 08:** Second REST service to retrieve a specific question - **Step 09:** Spring Boot Developer Tools and LiveReload — develop faster! - **Step 10:** Create a REST service to add a new question: `@PostMapping`, Postman - **Step 11:** Content negotiation — deliver XML responses from REST services - **Step 12:** Spring Initializr — create Spring Boot projects on the fly - **Step 13:** Spring Boot Actuator — monitor your application - **Step 14:** Embedded servlet containers — switch to Jetty or Undertow - **Step 15:** Add dynamic configuration: YAML & more - **Step 16:** Basics of profiles - **Step 17:** Advanced configuration with type-safe `@ConfigurationProperties` - **Step 18:** Spring Data JPA with `CommandLineRunner` - **Step 19:** H2 console and add a custom JPA repository method - **Step 20:** Introduction to Spring Data REST - **Step 21:** Spring Boot integration tests - **Step 22:** Add integration test for POST requests - **Step 23:** Small refactor to organize code - **Step 24:** Unit tests with Spring Boot and Mockito - **Step 25:** Unit test for `createTodo` - **Step 26:** Secure services with Basic Authentication using Spring Security - **Step 27:** Configure Spring Security roles for survey and other services - **Step 28:** Deep dive into Spring Boot auto-configuration --- ## Step-by-Step Notes and Code Examples ### 02. Spring-Boot-Web-Application #### Step01.md ##### What you will learn in this step - Let's create a simple web application using Spring Boot. - How to run the Spring Boot application. - An overview of the "magic" that Spring Boot provides (deep dive in Step 03). ##### Files list - *(Add list of files for this step — e.g., `pom.xml`, `src/main/java/...`, `src/main/resources/application.properties`, `src/main/resources/templates/*`)* pom.xml ```xml 4.0.0 com.in28minutes.springboot.web spring-boot-first-web-application 0.0.1-SNAPSHOT jar spring-boot-first-web-application Demo project for Spring Boot org.springframework.boot spring-boot-starter-parent 4.0.0-M2 UTF-8 UTF-8 21 3.1.1 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-devtools runtime org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin ``` --- src/main/java/com/in28minutes/springboot/web/SpringBootFirstWebApplication.java ```java package com.in28minutes.springboot.web; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class SpringBootFirstWebApplication { public static void main(String[] args) { SpringApplication.run(SpringBootFirstWebApplication.class, args); } } ``` --- src/main/resources/application.properties ``` ``` --- src/test/java/com/in28minutes/springboot/web/SpringBootFirstWebApplicationTests.java ```java package com.in28minutes.springboot.web; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest public class SpringBootFirstWebApplicationTests { @Test public void contextLoads() { } } ``` --- ## Step02.md #### What You Will Learn during this Step: - Using `@RequestMapping(value = "/login", method = RequestMethod.GET)` - Accessing endpoint: `http://localhost:8080/login` - Why use `@ResponseBody`? - Importance of the `@RequestMapping` method - How web applications work — Request and Response cycle: - Browser sends **HTTP Request** to the web server - Code in the web server executes - **Input:** `HttpRequest` - **Output:** `HttpResponse` - Web server responds with an **HTTP Response** src/main/java/com/in28minutes/springboot/web/controller/LoginController.java New ```java package com.in28minutes.springboot.web.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class LoginController { @RequestMapping("/login") public String loginMessage() { return "Hello World"; } } ``` --- src/main/resources/application.properties Modified New Lines ``` logging.level.org.springframework.web: DEBUG ``` ## Step03.md #### What You Will Learn during this Step: - Demystifying some of the Spring Boot magic: - **Spring Boot Starter Parent** - **Spring Boot Starter Web** - **Embedded Tomcat** - **Spring Boot DevTools** --- ## Step04.md #### What You Will Learn during this Step: - Creating your **first JSP** - (Note: A bit of setup is required before this step!) - Introduction to **ViewResolver** #### Useful Snippets and References - First Snippet: `/src/main/webapp/WEB-INF/jsp/login.jsp` ```html Yahoo!! My First JSP!!! ``` Second Snippet - /src/main/resources/application.properties ``` spring.mvc.view.prefix: /WEB-INF/jsp/ spring.mvc.view.suffix: .jsp logging.level.: DEBUG ``` Third Snippet : To enable jsp support in embedded tomcat server! ```xml org.apache.tomcat.embed tomcat-embed-jasper provided//default for IntelliJ IDEA ``` #### Exercises - Create a new jsp and a new controller method to redirect to it! - Play around! #### Files List pom.xml Modified New Lines ```xml org.apache.tomcat.embed tomcat-embed-jasper provided //default for IntelliJ IDEA ``` src/main/java/com/in28minutes/springboot/web/controller/LoginController.java Modified ```java package com.in28minutes.springboot.web.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class LoginController { @RequestMapping("/login") public String loginMessage() { return "login"; } } ``` --- src/main/resources/application.properties Modified New Lines ``` spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp logging.level.org.springframework.web=DEBUG ``` src/main/webapp/WEB-INF/jsp/login.jsp New ```html First Web Application My First JSP!! ``` ## Step05.md #### What You Will Learn during this Step: - You first GET Parameter - Problem with using GET src/main/java/com/in28minutes/springboot/web/controller/LoginController.java Modified ```java @Controller public class LoginController { @RequestMapping("/login") public String loginMessage(@RequestParam String name, ModelMap model) { model.put("name", name); return "login"; } } ``` --- src/main/webapp/WEB-INF/jsp/login.jsp Modified New Lines ``` My First JSP!! Welcome ${name}! ``` ## Step06.md #### What You Will Learn during this Step: - Importance of the **DispatcherServlet** in Spring MVC. --- #### Spring MVC Request Flow 1. **DispatcherServlet** receives the HTTP Request. 2. **DispatcherServlet** identifies the correct Controller based on the URL. - The Controller executes business logic. - The Controller returns: a) **Model** b) **View Name** back to DispatcherServlet. 3. **DispatcherServlet** uses a **ViewResolver** to identify the correct view. 4. **DispatcherServlet** makes the Model available to the View and executes it. 5. **DispatcherServlet** sends the final HTTP Response back to the client. 📌 Reference Flow Diagram: [Spring MVC Request Flow](http://docs.spring.io/spring-framework/docs/2.0.8/reference/images/mvc.png) ## Step07.md #### What You Will Learn during this Step: - Lets get the name from the user in a form #### Useful Snippets and References First Snippet ```java @RequestMapping(value = "/login", method = RequestMethod.GET) public String showLoginPage(ModelMap model, @RequestParam String name) { return "login"; } @RequestMapping(value = "/login", method = RequestMethod.POST) public String handleLogin(ModelMap model, @RequestParam String name) { model.put("name", name); return "welcome"; } ``` Second Snippet ```html
Name :
``` #### Files List src/main/java/com/in28minutes/springboot/web/controller/LoginController.java Modified ```java package com.in28minutes.springboot.web.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @Controller public class LoginController { @RequestMapping(value = "/login", method = RequestMethod.GET) public String showLoginPage(ModelMap model) { return "login"; } @RequestMapping(value = "/login", method = RequestMethod.POST) public String showWelcomePage(ModelMap model, @RequestParam String name) { model.put("name", name); return "welcome"; } } ``` --- src/main/webapp/WEB-INF/jsp/login.jsp Modified New Lines ```
Name : Password :
``` src/main/webapp/WEB-INF/jsp/welcome.jsp New ```html First Web Application Welcome ${name}!! ``` --- ## Step08.md #### What You Will Learn during this Step: - Add validation for **userid** and **password**. - Understand the concept of **hard-coded validation** (checking credentials against fixed values). - Show appropriate **error messages** when invalid credentials are entered. - Learn the flow of form submission: - User submits login form. - Application checks credentials against hard-coded values. - On success → Redirect to welcome page. - On failure → Stay on login page and display error message. --- ✅ This step introduces **basic login validation**, preparing the ground for more flexible and secure authentication approaches later in the course. #### Files List src/main/java/com/in28minutes/springboot/web/controller/LoginController.java Modified ```java @Controller public class LoginController { @Autowired LoginService service; @RequestMapping(value = "/login", method = RequestMethod.GET) public String showLoginPage(ModelMap model) { return "login"; } @RequestMapping(value = "/login", method = RequestMethod.POST) public String showWelcomePage(ModelMap model, @RequestParam String name, @RequestParam String password) { boolean isValidUser = service.validateUser(name, password); if (!isValidUser) { model.put("errorMessage", "Invalid Credentials"); return "login"; } model.put("name", name); model.put("password", password); return "welcome"; } } ``` --- src/main/java/com/in28minutes/springboot/web/service/LoginService.java New ```java package com.in28minutes.springboot.web.service; import org.springframework.stereotype.Component; @Component public class LoginService { public boolean validateUser(String userid, String password) { // in28minutes, dummy return userid.equalsIgnoreCase("in28minutes") && password.equalsIgnoreCase("dummy"); } } ``` --- src/main/webapp/WEB-INF/jsp/login.jsp Modified New Lines ``` ${errorMessage} ``` ## Step09.md #### What You Will Learn during this Step: - Understand the **magic of Spring**. - Learn about **Spring Auto-wiring** and **Dependency Injection**. - Key concepts: `@Autowired`, `@Component`. - How Spring manages dependencies automatically to reduce boilerplate code. --- ## Step10.md #### What You Will Do: - Create `TodoController` and the `list-todos.jsp` page. - Implement `TodoService` as a Spring `@Service` and inject it into the controller. #### Pending for Next Step: - The variable `${name}` is not yet available in `list-todos.jsp`. - The username "in28Minutes" is still hardcoded in `TodoController`. #### Notes: - In this step, you will see **controller-service interaction** in action. - Prepare for dynamic data handling and model binding in the next step. ```java package com.in28minutes.springboot.web.model; import java.util.Date; public class Todo { private int id; private String user; private String desc; private Date targetDate; private boolean isDone; public Todo(int id, String user, String desc, Date targetDate, boolean isDone) { super(); this.id = id; this.user = user; this.desc = desc; this.targetDate = targetDate; this.isDone = isDone; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUser() { return user; } public void setUser(String user) { this.user = user; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public Date getTargetDate() { return targetDate; } public void setTargetDate(Date targetDate) { this.targetDate = targetDate; } public boolean isDone() { return isDone; } public void setDone(boolean isDone) { this.isDone = isDone; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + id; return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } Todo other = (Todo) obj; if (id != other.id) { return false; } return true; } @Override public String toString() { return String.format( "Todo [id=%s, user=%s, desc=%s, targetDate=%s, isDone=%s]", id, user, desc, targetDate, isDone); } } ``` Snippet - /src/main/java/com/in28minutes/springboot/web/service/TodoService.java ```java package com.in28minutes.springboot.web.service; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import org.springframework.stereotype.Service; import com.in28minutes.springboot.web.model.Todo; @Service public class TodoService { private static List todos = new ArrayList<>(); private static int todoCount = 3; static { todos.add(new Todo(1, "in28Minutes", "Learn Spring MVC", new Date(), false)); todos.add(new Todo(2, "in28Minutes", "Learn Struts", new Date(), false)); todos.add(new Todo(3, "in28Minutes", "Learn Hibernate", new Date(), false)); } public List retrieveTodos(String user) { List filteredTodos = new ArrayList<>(); for (Todo todo : todos) { if (todo.getUser().equals(user)) { filteredTodos.add(todo); } } return filteredTodos; } public void addTodo(String name, String desc, Date targetDate, boolean isDone) { todos.add(new Todo(++todoCount, name, desc, targetDate, isDone)); } public void deleteTodo(int id) { todos.removeIf(todo -> todo.getId() == id); } } ``` ## Step11.md #### What You Will Do: - Discuss the **architecture of web applications**. - Understand how different layers (Controller, Service, View) interact. - Learn about the responsibilities of each layer and how they contribute to **separation of concerns**. --- ## Step12.md #### What You Will Learn during this Step: - Differences between **Session**, **Model**, and **Request** scopes. - Best practices for using **Session** data — avoid storing unnecessary information. - How `@SessionAttributes("name")` works to store model attributes in the session. - Why **Model** is preferred over adding elements directly to `HttpServletRequest`: - Ensures **view-agnostic design**. - Allows the use of different view technologies not tied to `HttpServletRequest`. - Understanding Spring documentation on `@SessionAttributes`: - Lists model attribute names to be **transparently stored** in session or conversational storage. #### Notes: - This step is crucial for handling user-specific data across multiple requests. - Helps prepare for form handling, login sessions, and dynamic content rendering. First Snippet ```java @SessionAttributes("name") ``` #### Files List src/main/java/com/in28minutes/springboot/web/SpringBootFirstWebApplication.java Modified New Lines ```java import org.springframework.context.annotation.ComponentScan; @ComponentScan("com.in28minutes.springboot.web") ``` --- src/main/java/com/in28minutes/springboot/web/controller/LoginController.java Modified ```java @Controller @SessionAttributes("name") public class LoginController { ``` --- src/main/java/com/in28minutes/springboot/web/controller/TodoController.java New ```java package com.in28minutes.springboot.web.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.SessionAttributes; import com.in28minutes.springboot.web.service.LoginService; import com.in28minutes.springboot.web.service.TodoService; @Controller @SessionAttributes("name") public class TodoController { @Autowired TodoService service; @RequestMapping(value = "/list-todos", method = RequestMethod.GET) public String showTodos(ModelMap model) { String name = (String) model.get("name"); model.put("todos", service.retrieveTodos(name)); return "list-todos"; } } ``` --- src/main/java/com/in28minutes/springboot/web/model/Todo.java New ```java package com.in28minutes.springboot.web.model; import java.util.Date; public class Todo { private int id; private String user; private String desc; private Date targetDate; private boolean isDone; public Todo(int id, String user, String desc, Date targetDate, boolean isDone) { super(); this.id = id; this.user = user; this.desc = desc; this.targetDate = targetDate; this.isDone = isDone; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUser() { return user; } public void setUser(String user) { this.user = user; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public Date getTargetDate() { return targetDate; } public void setTargetDate(Date targetDate) { this.targetDate = targetDate; } public boolean isDone() { return isDone; } public void setDone(boolean isDone) { this.isDone = isDone; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + id; return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } Todo other = (Todo) obj; return id == other.id; } @Override public String toString() { return String.format( "Todo [id=%s, user=%s, desc=%s, targetDate=%s, isDone=%s]", id, user, desc, targetDate, isDone); } } ``` --- src/main/java/com/in28minutes/springboot/web/service/LoginService.java Modified ```java @Service public class LoginService { ``` --- src/main/java/com/in28minutes/springboot/web/service/TodoService.java New ```java package com.in28minutes.springboot.web.service; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import org.springframework.stereotype.Service; import com.in28minutes.springboot.web.model.Todo; @Service public class TodoService { private static List todos = new ArrayList<>(); private static int todoCount = 3; static { todos.add(new Todo(1, "in28Minutes", "Learn Spring MVC", new Date(), false)); todos.add(new Todo(2, "in28Minutes", "Learn Struts", new Date(), false)); todos.add(new Todo(3, "in28Minutes", "Learn Hibernate", new Date(), false)); } public List retrieveTodos(String user) { List filteredTodos = new ArrayList<>(); for (Todo todo : todos) { if (todo.getUser().equals(user)) { filteredTodos.add(todo); } } return filteredTodos; } public void addTodo(String name, String desc, Date targetDate, boolean isDone) { todos.add(new Todo(++todoCount, name, desc, targetDate, isDone)); } public void deleteTodo(int id) { todos.removeIf(todo -> todo.getId() == id); } } ``` --- src/main/webapp/WEB-INF/jsp/list-todos.jsp New ```html First Web Application Here are the list of your todos: ${todos}
Your Name is : ${name} ``` --- src/main/webapp/WEB-INF/jsp/welcome.jsp Modified New Lines ``` Welcome ${name}!! Click here to manage your todo's. ``` ## Step13.md #### What You Will Do: - Add functionality to **create a new Todo**. - Work with the **todo.jsp** page for adding todos. - Learn the importance of using **redirect:/list-todos** after form submission: - Prevents duplicate form submissions on page refresh. - Updates the list view to show the newly added todo. #### Notes: - Controller handles the form submission and redirects to the list view. - Model and view interaction ensures the new todo is displayed correctly. #### Files Modified: - `src/main/java/com/in28minutes/springboot/web/controller/TodoController.java` ```java @RequestMapping(value = "/add-todo", method = RequestMethod.GET) public String showAddTodoPage(ModelMap model) { return "todo"; } @RequestMapping(value = "/add-todo", method = RequestMethod.POST) public String addTodo(ModelMap model, @RequestParam String desc) { service.addTodo((String) model.get("name"), desc, new Date(), false); return "redirect:/list-todos"; } ``` --- src/main/webapp/WEB-INF/jsp/list-todos.jsp Modified New Lines ```html Here are the list of ${name}'s todos: ${todos}. Add a Todo ``` src/main/webapp/WEB-INF/jsp/todo.jsp New ```html First Web Application ADD Todo Page for ${name}
Description :
``` ## Step14.md #### What You Will Do: - Display the list of **Todos in a table** using **JSTL tags**. - Use the JSTL core tag library: - `<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>` - Add the necessary **JSTL dependency** to your project. #### Notes: - JSTL tags make it easier to **iterate over collections**, conditionally display content, and reduce scriptlets in JSP. - This step focuses on **dynamic content rendering** using standard JSP techniques. #### Files Modified: - `list-todos.jsp` (to use JSTL tags for displaying todos) ```xml jakarta.servlet.jsp.jstl jakarta.servlet.jsp.jstl-api ``` ## Step15.md #### What You Will Do: - Add **Bootstrap** to give basic styling and formatting to pages. - Use Bootstrap classes like `container`, `table`, and `table-striped`. - Use **WebJars** to manage Bootstrap dependencies. - Leverage **Spring Boot auto-configuration** for WebJars: - `SimpleUrlHandlerMapping` automatically maps `/webjars/**` URLs to the appropriate resource handler. #### Notes: - WebJars allow you to include client-side libraries (like Bootstrap) via Maven. - This step improves **UI presentation** without manual setup of static resources. #### Useful Snippets ``` org.webjars bootstrap 3.3.6 org.webjars jquery 1.9.1 ``` #### Files List pom.xml Modified New Lines ```xml org.webjars bootstrap 5.1.3 org.webjars jquery 3.6.0 org.apache.tomcat.embed tomcat-embed-jasper provided jakarta.servlet.jsp.jstl jakarta.servlet.jsp.jstl-api ``` src/main/resources/application.properties Modified New Lines ``` logging.level.org.springframework.web=INFO ``` src/main/webapp/WEB-INF/jsp/list-todos.jsp Modified New Lines ```html <%@ taglib prefix="c" uri="jakarta.tags.core" %> Todo's for ${name}
Your todos are
Description Target Date Is it Done?
${todo.desc} ${todo.targetDate} ${todo.done}
``` ## Step16.md #### What we will do: - Add functionality to delete a todo #### Useful Snippets ```html Delete ``` #### Files List src/main/java/com/in28minutes/springboot/web/controller/TodoController.java Modified New Lines ```java @RequestMapping(value = "/delete-todo", method = RequestMethod.GET) public String deleteTodo(@RequestParam int id) { service.deleteTodo(id); } ``` --- src/main/webapp/WEB-INF/jsp/list-todos.jsp Modified New Lines ``` Delete ``` ## Step17.md ## Step17.md #### What You Will Do: - Format the **Add Todo** page for better presentation. - Add **HTML5 form validations** to ensure proper input from the user. - Examples: required fields, date format checks, and text length constraints. #### Notes: - HTML5 validations provide **basic client-side checks** before the form is submitted. - Improves user experience by preventing invalid data entry. #### Useful Snippets: - Form fields with HTML5 validation attributes (`required`, `type="date"`, etc.). ```html
``` #### Files List src/main/webapp/WEB-INF/jsp/list-todos.jsp Modified Snippets ```html Delete ``` src/main/webapp/WEB-INF/jsp/todo.jsp Modified New Lines ```html
``` ## Step18.md #### What we will do: - Lets use a command bean for Todo - Add Validations - The JSR 303 and JSR 349 defines specification for the Bean Validation API (version 1.0 and 1.1, respectively), and Hibernate Validator is the reference implementation. - org.hibernate:hibernate-validator #### Useful Snippets ```html <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
Description
@Size(min = 10, message = "Enter atleast 10 Characters.") @Valid Todo todo, BindingResult result if (result.hasErrors()) return "todo"; ``` #### Files List src/main/java/com/in28minutes/springboot/web/controller/TodoController.java Modified ```java @Controller @SessionAttributes("name") public class TodoController { @Autowired TodoService service; @RequestMapping(value = "/list-todos", method = RequestMethod.GET) public String showTodos(ModelMap model) { String name = (String) model.get("name"); model.put("todos", service.retrieveTodos(name)); return "list-todos"; } @RequestMapping(value = "/add-todo", method = RequestMethod.GET) public String showAddTodoPage(ModelMap model) { model.addAttribute("todo", new Todo(0, (String) model.get("name"), "Default Desc", new Date(), false)); return "todo"; } @RequestMapping(value = "/delete-todo", method = RequestMethod.GET) public String deleteTodo(@RequestParam int id) { service.deleteTodo(id); return "redirect:/list-todos"; } @RequestMapping(value = "/add-todo", method = RequestMethod.POST) public String addTodo(ModelMap model, @Valid Todo todo, BindingResult result) { if (result.hasErrors()) { return "todo"; } service.addTodo((String) model.get("name"), todo.getDesc(), new Date(), false); return "redirect:/list-todos"; } } ``` --- src/main/java/com/in28minutes/springboot/web/model/Todo.java Modified New Lines ```java public Todo() { super(); } @Size(min = 10, message = "Enter at least 10 Characters...") private String desc; ``` --- src/main/webapp/WEB-INF/jsp/todo.jsp Modified New Lines ```html <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> Description ``` ## Step19.md #### What You Will Do: - Add **update functionality** for existing todos. - Reuse the **same JSP page** used for adding todos to handle updates. #### Notes: - Updating a todo involves **pre-populating the form** with existing data. - This step demonstrates **reusing views** and keeping the UI consistent. - Controller logic will differentiate between **add** and **update** operations based on the presence of an existing todo. #### Useful Snippets ```java public Todo retrieveTodo(int id) { for (Todo todo : todos) { if (todo.getId() == id) return todo; } return null; } public void updateTodo(Todo todo) { todos.remove(todo); todos.add(todo); } todo. setUser("in28Minutes"); //TODO:Remove Hardcoding Later service. updateTodo(todo);