├── .gitignore ├── 01.Spring-Boot-Introduction-In-10-Steps-V2 ├── HELP.md ├── notes.txt ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── in28minutes │ │ │ └── springboot │ │ │ └── learnspringboot │ │ │ ├── Course.java │ │ │ ├── CourseController.java │ │ │ ├── CurrencyConfigurationController.java │ │ │ ├── CurrencyServiceConfiguration.java │ │ │ └── LearnSpringBootApplication.java │ └── resources │ │ ├── application-dev.properties │ │ ├── application-prod.properties │ │ └── application.properties │ └── test │ └── java │ └── com │ └── in28minutes │ └── springboot │ └── learnspringboot │ └── LearnSpringBootApplicationTests.java ├── 01.Spring-Boot-Introduction-In-10-Steps ├── 1.md ├── 2.md ├── HELP.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── in28minutes │ │ │ └── learnspringboot │ │ │ ├── LearnSpringBootApplication.java │ │ │ └── courses │ │ │ ├── bean │ │ │ └── Course.java │ │ │ ├── controller │ │ │ └── CourseController.java │ │ │ └── repository │ │ │ └── CourseRepository.java │ └── resources │ │ ├── application.properties │ │ └── data.sql │ └── test │ └── java │ └── com │ └── in28minutes │ └── learnspringboot │ └── LearnSpringBootApplicationTests.java ├── 02.Spring-Boot-Web-Application-V2 ├── 99-step-by-step-changes.md ├── HELP.md ├── README.md ├── Step01.md ├── Step01.zip ├── Step03.md ├── Step03.zip ├── Step04.md ├── Step04.zip ├── Step05.md ├── Step05.zip ├── Step06.md ├── Step06.zip ├── Step08.md ├── Step08.zip ├── Step11.md ├── Step11.zip ├── Step13.md ├── Step13.zip ├── Step17.md ├── Step17.zip ├── Step19.md ├── Step19.zip ├── Step20.md ├── Step20.zip ├── Step25.md ├── Step25.zip ├── Step26.md ├── Step26.zip ├── Step27.md ├── Step27.zip ├── Step28.md ├── Step28.zip ├── Step29.md ├── Step29.zip ├── Step31.md ├── Step31.zip ├── Step33.md ├── Step33.zip ├── Step35.md ├── Step35.zip ├── Step36.md ├── Step36.zip ├── Step38.md ├── Step38.zip ├── Step41.md ├── Step41.zip ├── pom.xml ├── recording │ ├── 02-todo-basic-22-june.md │ ├── 03-code-prep-23-june.md │ ├── 04-code-2-24-june.md │ ├── 05-code-final-prep.md │ ├── 99.step-by-step-changes.md │ └── code-2-24-june.md └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── in28minutes │ │ │ └── springboot │ │ │ └── myfirstwebapp │ │ │ ├── MyfirstwebappApplication.java │ │ │ ├── hello │ │ │ └── SayHelloController.java │ │ │ ├── login │ │ │ └── WelcomeController.java │ │ │ ├── security │ │ │ └── SpringSecurityConfiguration.java │ │ │ └── todo │ │ │ ├── Todo.java │ │ │ ├── TodoController.java │ │ │ ├── TodoControllerJpa.java │ │ │ ├── TodoRepository.java │ │ │ └── TodoService.java │ └── resources │ │ ├── META-INF │ │ └── resources │ │ │ └── WEB-INF │ │ │ └── jsp │ │ │ ├── common │ │ │ ├── footer.jspf │ │ │ ├── header.jspf │ │ │ └── navigation.jspf │ │ │ ├── listTodos.jsp │ │ │ ├── sayHello.jsp │ │ │ ├── todo.jsp │ │ │ └── welcome.jsp │ │ ├── application.properties │ │ └── data.sql │ └── test │ └── java │ └── com │ └── in28minutes │ └── springboot │ └── myfirstwebapp │ └── MyfirstwebappApplicationTests.java ├── 02.Spring-Boot-Web-Application ├── 2-3-1-upgrade.md ├── 99.step-by-step-changes.md ├── README.md ├── Step01.md ├── Step02.md ├── Step03.md ├── Step04.md ├── Step05.md ├── Step06.md ├── Step07.md ├── Step07.zip ├── Step08.md ├── Step08.zip ├── Step09.md ├── Step10.md ├── Step11.md ├── Step12.md ├── Step12.zip ├── Step13.md ├── Step13.zip ├── Step14.md ├── Step15.md ├── Step15.zip ├── Step16.md ├── Step16.zip ├── Step17.md ├── Step18.md ├── Step18.zip ├── Step19.md ├── Step19.zip ├── Step20.md ├── Step20.zip ├── Step21.md ├── Step21.zip ├── Step22.md ├── Step22.zip ├── Step23.md ├── Step23.zip ├── Step24.md ├── Step25.md ├── Step25.zip ├── StepReference.md ├── notes.md ├── pom.xml ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── in28minutes │ │ │ │ └── springboot │ │ │ │ └── web │ │ │ │ ├── SpringBootFirstWebApplication.java │ │ │ │ ├── controller │ │ │ │ ├── ErrorController.java │ │ │ │ ├── LogoutController.java │ │ │ │ ├── TodoController.java │ │ │ │ └── WelcomeController.java │ │ │ │ ├── model │ │ │ │ └── Todo.java │ │ │ │ ├── security │ │ │ │ └── SecurityConfiguration.java │ │ │ │ └── service │ │ │ │ ├── TodoRepository.java │ │ │ │ └── TodoService.java │ │ └── resources │ │ │ ├── META-INF │ │ │ └── resources │ │ │ │ └── WEB-INF │ │ │ │ └── jsp │ │ │ │ ├── common │ │ │ │ ├── footer.jspf │ │ │ │ ├── header.jspf │ │ │ │ └── navigation.jspf │ │ │ │ ├── error.jsp │ │ │ │ ├── list-todos.jsp │ │ │ │ ├── todo.jsp │ │ │ │ └── welcome.jsp │ │ │ ├── application.properties │ │ │ └── data.sql │ └── test │ │ └── java │ │ └── com │ │ └── in28minutes │ │ └── springboot │ │ └── web │ │ └── SpringBootFirstWebApplicationTests.java ├── step32.md ├── step32.zip ├── step33-Upgrade-To-Sprint-Boot-2-M3.md └── step33-Upgrade-To-Sprint-Boot-2-M3.zip ├── 03.JUnit-Introduction-In-5-Steps-V2 ├── prep.md ├── readme.md ├── src │ └── com │ │ └── in28minutes │ │ └── junit │ │ └── MyMath.java └── test │ └── com │ └── in28minutes │ └── junit │ ├── MyAssertTest.java │ ├── MyBeforeAfterTest.java │ └── MyMathTest.java ├── 03.JUnit-Introduction-In-5-Steps ├── .gitignore ├── code-21July2017.zip ├── readme.md ├── src │ └── com │ │ └── in28minutes │ │ └── junit │ │ └── MyMath.java ├── step22.md ├── step22.zip ├── step25.md ├── step25.zip └── test │ └── com │ └── in28minutes │ └── junit │ ├── AssertTest.java │ └── MyMathTest.java ├── 04.Mockito-Introduction-In-5-Steps-V2 ├── HELP.md ├── Step5.md ├── Step5.zip ├── old_code.md ├── pom.xml ├── readme.md └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── in28minutes │ │ │ └── mockito │ │ │ └── mockitodemo │ │ │ ├── MockitoDemoApplication.java │ │ │ └── business │ │ │ └── SomeBusinessImpl.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── in28minutes │ └── mockito │ └── mockitodemo │ ├── MockitoDemoApplicationTests.java │ ├── business │ ├── SomeBusinessImplMockTest.java │ └── SomeBusinessImplStubTest.java │ └── list │ └── ListTest.java ├── 04.Mockito-Introduction-In-5-Steps ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── code-21July2017.zip ├── mvnw ├── mvnw.cmd ├── pom.xml ├── readme.md └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── in28minutes │ │ │ └── mockito │ │ │ └── mockitodemo │ │ │ ├── DataService.java │ │ │ ├── MockitoDemoApplication.java │ │ │ └── SomeBusinessImpl.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── in28minutes │ └── mockito │ └── mockitodemo │ ├── ListTest.java │ ├── MockitoDemoApplicationTests.java │ ├── SomeBusinessMockAnnotationsTest.java │ ├── SomeBusinessMockTest.java │ └── SomeBusinessStubTest.java ├── 05.Spring-Boot-Advanced-V2 ├── 99.step-by-step-code-changes.md ├── README.md ├── Step01.md ├── Step01.zip ├── Step05.md ├── Step05.zip ├── Step06.md ├── Step06.zip ├── Step07.md ├── Step07.zip ├── Step08.md ├── Step10.md ├── Step11.md ├── Step12.md ├── Step13.md ├── Step14.md ├── Step14.zip ├── Step16.md ├── Step19.md ├── Step19.zip ├── Step21.md ├── Step23.md ├── Step23.zip ├── Step26.md ├── Step28.md ├── Step29.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── in28minutes │ │ │ └── springboot │ │ │ └── firstrestapi │ │ │ ├── FirstRestApiApplication.java │ │ │ ├── helloworld │ │ │ ├── HelloWorldBean.java │ │ │ └── HelloWorldResource.java │ │ │ ├── security │ │ │ └── SpringSecurityConfiguration.java │ │ │ ├── survey │ │ │ ├── Question.java │ │ │ ├── Survey.java │ │ │ ├── SurveyResource.java │ │ │ └── SurveyService.java │ │ │ └── user │ │ │ ├── UserDetails.java │ │ │ ├── UserDetailsCommandLineRunner.java │ │ │ ├── UserDetailsRepository.java │ │ │ └── UserDetailsRestRepository.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── in28minutes │ └── springboot │ └── firstrestapi │ ├── FirstRestApiApplicationTests.java │ └── survey │ ├── JsonAssertTest.java │ ├── SurveyResourceIT.java │ └── SurveyResourceTest.java ├── 05.Spring-Boot-Advanced ├── 2-3-1-upgrade.md ├── 99.step-by-step-changes.md ├── README.md ├── Step01.md ├── Step01.zip ├── Step02.md ├── Step02.zip ├── Step03.md ├── Step04.md ├── Step05.md ├── Step06.md ├── Step06.zip ├── Step07.md ├── Step08.md ├── Step08.zip ├── Step09.md ├── Step10.md ├── Step10.zip ├── Step11.md ├── Step12.md ├── Step13.md ├── Step13.zip ├── Step14.md ├── Step14.zip ├── Step15.md ├── Step15.zip ├── Step16.md ├── Step16.zip ├── Step17.md ├── Step17.zip ├── Step18.md ├── Step18.zip ├── Step19.md ├── Step19.zip ├── Step20.md ├── Step20.zip ├── Step21.md ├── Step21.zip ├── Step22.md ├── Step22.zip ├── Step23.md ├── Step23.zip ├── Step24.md ├── Step25.md ├── Step25.zip ├── Step26.md ├── Step27.md ├── Step27.zip ├── Step28.md ├── Step28.zip ├── StepReference.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── in28minutes │ │ │ └── springboot │ │ │ ├── Application.java │ │ │ ├── WelcomeController.java │ │ │ ├── WelcomeService.java │ │ │ ├── configuration │ │ │ └── BasicConfiguration.java │ │ │ ├── controller │ │ │ └── SurveyController.java │ │ │ ├── jpa │ │ │ ├── User.java │ │ │ ├── UserCommandLineRunner.java │ │ │ ├── UserRepository.java │ │ │ └── UserRestRepository.java │ │ │ ├── model │ │ │ ├── Question.java │ │ │ └── Survey.java │ │ │ ├── security │ │ │ └── SecurityConfig.java │ │ │ └── service │ │ │ └── SurveyService.java │ └── resources │ │ ├── application-dev.properties │ │ ├── application-prod.properties │ │ └── application.properties │ └── test │ └── java │ └── com │ └── in28minutes │ └── springboot │ └── controller │ ├── SurveyControllerIT.java │ └── SurveyControllerTest.java ├── 06.JPA-Introduction-In-10-Steps ├── .gitignore ├── .mvn │ └── wrapper │ │ ├── maven-wrapper.jar │ │ └── maven-wrapper.properties ├── code-21July2017.zip ├── jpa-in-10-steps-all-code.md ├── mvnw ├── mvnw.cmd ├── notes.txt ├── pom.xml ├── readme.md ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── in28minutes │ │ │ │ └── learning │ │ │ │ └── jpa │ │ │ │ └── jpain10steps │ │ │ │ ├── JpaIn10StepsApplication.java │ │ │ │ ├── UserDaoServiceCommandLineRunner.java │ │ │ │ ├── UserRepositoryCommandLineRunner.java │ │ │ │ ├── entity │ │ │ │ └── User.java │ │ │ │ └── service │ │ │ │ ├── UserDAOService.java │ │ │ │ └── UserRepository.java │ │ └── resources │ │ │ └── application.properties │ └── test │ │ └── java │ │ └── com │ │ └── in28minutes │ │ └── learning │ │ └── jpa │ │ └── jpain10steps │ │ └── JpaIn10StepsApplicationTests.java ├── step-completed.sh ├── step21.md ├── step21.zip ├── step22.md ├── step22.zip ├── step23.md ├── step23.zip └── take-step-backup.sh ├── 09.Spring-Introduction-In-10-Steps ├── 1.md ├── 2.md ├── 3.md ├── 4.md ├── 5.md ├── 6.md ├── HELP.md ├── old.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── in28minutes │ │ │ └── learnspringframework │ │ │ ├── LearnSpringFrameworkApplication.java │ │ │ ├── game │ │ │ ├── GameRunner.java │ │ │ ├── GamingConsole.java │ │ │ ├── MarioGame.java │ │ │ ├── PacManGame.java │ │ │ └── SuperContraGame.java │ │ │ └── sample │ │ │ └── enterprise │ │ │ └── flow │ │ │ ├── business │ │ │ └── BusinessService.java │ │ │ ├── data │ │ │ └── DataService.java │ │ │ └── web │ │ │ └── Controller.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── in28minutes │ └── learnspringframework │ └── LearnSpringFrameworkApplicationTests.java ├── README.md ├── announcements.md ├── lectures.md └── spring-boot-3.2.x-changes.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.ear 17 | *.zip 18 | *.tar.gz 19 | *.rar 20 | *.cmd 21 | *.classpath 22 | *.settings 23 | *.project 24 | *.mvn 25 | mvnw 26 | target 27 | *.DS_Store 28 | .idea 29 | 01.Spring-Boot-Introduction-In-10-Steps/*.iml 30 | 02.Spring-Boot-Web-Application/*.iml 31 | 05.Spring-Boot-Advanced/*.iml 32 | 09.Spring-Introduction-In-10-Steps/*.iml 33 | 34 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 35 | hs_err_pid* 36 | 01.Spring-Boot-Introduction-In-10-Steps-V2/learn-spring-boot.iml 37 | 02.Spring-Boot-Web-Application-V2/myfirstwebapp.iml 38 | 04.Mockito-Introduction-In-5-Steps-V2/mockito-demo.iml 39 | 05.Spring-Boot-Advanced-V2/first-rest-api.iml 40 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps-V2/HELP.md: -------------------------------------------------------------------------------- 1 | # Read Me First 2 | The following was discovered as part of building this project: 3 | 4 | * The original package name 'com.in28minutes.springboot.learn-spring-boot' is invalid and this project uses 'com.in28minutes.springboot.learnspringboot' instead. 5 | 6 | # Getting Started 7 | 8 | ### Reference Documentation 9 | For further reference, please consider the following sections: 10 | 11 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html) 12 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/3.0.0-M3/maven-plugin/reference/html/) 13 | * [Create an OCI image](https://docs.spring.io/spring-boot/docs/3.0.0-M3/maven-plugin/reference/html/#build-image) 14 | * [Spring Web](https://docs.spring.io/spring-boot/docs/3.0.0-M3/reference/htmlsingle/#web) 15 | 16 | ### Guides 17 | The following guides illustrate how to use some features concretely: 18 | 19 | * [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/) 20 | * [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/) 21 | * [Building REST services with Spring](https://spring.io/guides/tutorials/rest/) 22 | 23 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps-V2/notes.txt: -------------------------------------------------------------------------------- 1 | 2 | dev 3 | ~~~~ 4 | logging.level.org.springframework=trace 5 | 6 | prod 7 | ~~~~ 8 | logging.level.org.springframework=info 9 | 10 | 11 | trace 12 | debug 13 | info 14 | warning 15 | error 16 | 17 | off 18 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps-V2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 3.3.4 9 | 10 | 11 | com.in28minutes.springboot 12 | learn-spring-boot 13 | 0.0.1-SNAPSHOT 14 | learn-spring-boot 15 | Demo project for Spring Boot 16 | 17 | 21 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-web 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-actuator 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-devtools 34 | 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-test 39 | test 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-maven-plugin 49 | 50 | 51 | 52 | 53 | 54 | spring-milestones 55 | Spring Milestones 56 | https://repo.spring.io/milestone 57 | 58 | false 59 | 60 | 61 | 62 | 63 | 64 | spring-milestones 65 | Spring Milestones 66 | https://repo.spring.io/milestone 67 | 68 | false 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps-V2/src/main/java/com/in28minutes/springboot/learnspringboot/Course.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.learnspringboot; 2 | 3 | public class Course { 4 | private long id; 5 | private String name; 6 | private String author; 7 | 8 | public Course(long id, String name, String author) { 9 | super(); 10 | this.id = id; 11 | this.name = name; 12 | this.author = author; 13 | } 14 | 15 | public long getId() { 16 | return id; 17 | } 18 | 19 | public String getName() { 20 | return name; 21 | } 22 | 23 | public String getAuthor() { 24 | return author; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return "Course [id=" + id + ", name=" + name + ", author=" + author + "]"; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps-V2/src/main/java/com/in28minutes/springboot/learnspringboot/CourseController.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.learnspringboot; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | @RestController 9 | public class CourseController { 10 | 11 | @RequestMapping("/courses") 12 | public List retrieveAllCourses() { 13 | return List.of( 14 | new Course(1, "Learn AWS", "in28minutes"), 15 | new Course(2, "Learn DevOps", "in28minutes"), 16 | new Course(3, "Learn Azure", "in28minutes"), 17 | new Course(4, "Learn GCP", "in28minutes") 18 | ); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps-V2/src/main/java/com/in28minutes/springboot/learnspringboot/CurrencyConfigurationController.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.learnspringboot; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | @RestController 8 | public class CurrencyConfigurationController { 9 | 10 | @Autowired 11 | private CurrencyServiceConfiguration configuration; 12 | 13 | @RequestMapping("/currency-configuration") 14 | public CurrencyServiceConfiguration retrieveAllCourses() { 15 | return configuration; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps-V2/src/main/java/com/in28minutes/springboot/learnspringboot/CurrencyServiceConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.learnspringboot; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.stereotype.Component; 5 | 6 | //currency-service.url= 7 | //currency-service.username= 8 | //currency-service.key= 9 | 10 | @ConfigurationProperties(prefix = "currency-service") 11 | @Component 12 | public class CurrencyServiceConfiguration { 13 | 14 | private String url; 15 | private String username; 16 | private String key; 17 | 18 | public String getUrl() { 19 | return url; 20 | } 21 | 22 | public void setUrl(String url) { 23 | this.url = url; 24 | } 25 | 26 | public String getUsername() { 27 | return username; 28 | } 29 | 30 | public void setUsername(String username) { 31 | this.username = username; 32 | } 33 | 34 | public String getKey() { 35 | return key; 36 | } 37 | 38 | public void setKey(String key) { 39 | this.key = key; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps-V2/src/main/java/com/in28minutes/springboot/learnspringboot/LearnSpringBootApplication.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.learnspringboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class LearnSpringBootApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(LearnSpringBootApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps-V2/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | logging.level.org.springframework=trace 2 | 3 | currency-service.url=http://dev.in28minutes.com 4 | currency-service.username=devusername 5 | currency-service.key=devkey 6 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps-V2/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | logging.level.org.springframework=info 2 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps-V2/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | logging.level.org.springframework=debug 2 | spring.profiles.active=dev 3 | 4 | 5 | currency-service.url=http://default1.in28minutes.com 6 | currency-service.username=defaultusername 7 | currency-service.key=defaultkey 8 | 9 | management.endpoints.web.exposure.include=health,metrics -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps-V2/src/test/java/com/in28minutes/springboot/learnspringboot/LearnSpringBootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.learnspringboot; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class LearnSpringBootApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps/HELP.md: -------------------------------------------------------------------------------- 1 | # Read Me First 2 | The following was discovered as part of building this project: 3 | 4 | * The original package name 'com.in28minutes.learn-spring-boot' is invalid and this project uses 'com.in28minutes.learnspringboot' instead. 5 | 6 | # Getting Started 7 | 8 | ### Reference Documentation 9 | For further reference, please consider the following sections: 10 | 11 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html) 12 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.4.4/maven-plugin/reference/html/) 13 | * [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.4.4/maven-plugin/reference/html/#build-image) 14 | * [Spring Web](https://docs.spring.io/spring-boot/docs/2.4.4/reference/htmlsingle/#boot-features-developing-web-applications) 15 | 16 | ### Guides 17 | The following guides illustrate how to use some features concretely: 18 | 19 | * [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/) 20 | * [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/) 21 | * [Building REST services with Spring](https://spring.io/guides/tutorials/bookmarks/) 22 | 23 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.7.0 9 | 10 | 11 | com.in28minutes 12 | learn-spring-boot 13 | 0.0.1-SNAPSHOT 14 | learn-spring-boot 15 | Demo project for Spring Boot 16 | 17 | 17 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-web 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-data-jpa 29 | 30 | 31 | 37 | 38 | 39 | mysql 40 | mysql-connector-java 41 | 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-actuator 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-devtools 51 | runtime 52 | 53 | 54 | 55 | 56 | org.springframework.boot 57 | spring-boot-starter-test 58 | test 59 | 60 | 61 | 62 | 63 | 64 | 65 | org.springframework.boot 66 | spring-boot-maven-plugin 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps/src/main/java/com/in28minutes/learnspringboot/LearnSpringBootApplication.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learnspringboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | //@SpringBootConfiguration 8 | //@EnableAutoConfiguration 9 | //@ComponentScan 10 | public class LearnSpringBootApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(LearnSpringBootApplication.class, args); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps/src/main/java/com/in28minutes/learnspringboot/courses/bean/Course.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learnspringboot.courses.bean; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.Id; 6 | 7 | @Entity 8 | public class Course { 9 | 10 | @Id 11 | @GeneratedValue 12 | private long id; 13 | 14 | //@Column(name="course_name") 15 | private String name; 16 | 17 | private String author; 18 | 19 | public Course() { 20 | } 21 | 22 | public Course(long id, String name, String author) { 23 | super(); 24 | this.id = id; 25 | this.name = name; 26 | this.author = author; 27 | } 28 | 29 | public long getId() { 30 | return id; 31 | } 32 | 33 | public String getName() { 34 | return name; 35 | } 36 | 37 | public String getAuthor() { 38 | return author; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "Course [id=" + id + ", name=" + name + ", author=" + author + "]"; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps/src/main/java/com/in28minutes/learnspringboot/courses/controller/CourseController.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learnspringboot.courses.controller; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.DeleteMapping; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.PathVariable; 10 | import org.springframework.web.bind.annotation.PostMapping; 11 | import org.springframework.web.bind.annotation.PutMapping; 12 | import org.springframework.web.bind.annotation.RequestBody; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | import com.in28minutes.learnspringboot.courses.bean.Course; 16 | import com.in28minutes.learnspringboot.courses.repository.CourseRepository; 17 | 18 | @RestController 19 | public class CourseController { 20 | 21 | @Autowired 22 | private CourseRepository repository; 23 | 24 | // http://localhost:8080/courses 25 | @GetMapping("/courses") 26 | public List getAllCourses() { 27 | return repository.findAll(); 28 | } 29 | 30 | //// http://localhost:8080/courses/1 31 | @GetMapping("/courses/{id}") 32 | public Course getCourseDetails(@PathVariable long id) { 33 | 34 | Optional course = repository.findById(id); 35 | 36 | if(course.isEmpty()) { 37 | throw new RuntimeException("Course not found with id " + id); 38 | } 39 | 40 | return course.get(); 41 | } 42 | 43 | /* 44 | POST http://localhost:8080/courses 45 | { 46 | "name": "Learn DevOps", 47 | "author": "in28minutes" 48 | }*/ 49 | 50 | //POST - Create a new resource (/courses) 51 | @PostMapping("/courses") 52 | public void createCourse(@RequestBody Course course){ 53 | repository.save(course); 54 | } 55 | 56 | /* 57 | PUT - http://localhost:8080/courses/100001 58 | { 59 | "id": 100001, 60 | "name": "Learn Microservices 2", 61 | "author": "in28minutes" 62 | } 63 | */ 64 | 65 | //PUT - Update/Replace a resource (/courses/1) 66 | @PutMapping("/courses/{id}") 67 | public void updateCourse(@PathVariable long id, @RequestBody Course course){ 68 | repository.save(course); 69 | } 70 | 71 | 72 | //DELETE - Delete a resource (/courses/1) 73 | @DeleteMapping("/courses/{id}") 74 | public void deleteCourse(@PathVariable long id){ 75 | repository.deleteById(id); 76 | } 77 | 78 | 79 | // docker run --detach 80 | // --env MYSQL_ROOT_PASSWORD=dummypassword 81 | // --env MYSQL_USER=courses-user 82 | // --env MYSQL_PASSWORD=dummycourses 83 | // --env MYSQL_DATABASE=courses 84 | // --name mysql 85 | // --publish 3306:3306 mysql:5.7 86 | } 87 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps/src/main/java/com/in28minutes/learnspringboot/courses/repository/CourseRepository.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learnspringboot.courses.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import com.in28minutes.learnspringboot.courses.bean.Course; 6 | 7 | public interface CourseRepository extends JpaRepository { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #logging.level.org.springframework=DEBUG 2 | #management.endpoints.web.exposure.include=* 3 | management.endpoints.web.exposure.include=health,metrics 4 | #spring.datasource.url=jdbc:h2:mem:testdb 5 | 6 | spring.jpa.hibernate.ddl-auto=update 7 | spring.datasource.url=jdbc:mysql://localhost:3306/courses 8 | spring.datasource.username=courses-user 9 | spring.datasource.password=dummycourses 10 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect 11 | spring.jpa.defer-datasource-initialization=true 12 | 13 | #courses-user@localhost:3306 -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps/src/main/resources/data.sql: -------------------------------------------------------------------------------- 1 | insert into COURSE (ID, AUTHOR, NAME) 2 | values (100001, 'in28minutes', 'Learn Microservices'); 3 | insert into COURSE (ID, AUTHOR, NAME) 4 | values (100002, 'in28minutes', 'Learn FullStack with React and Angular'); 5 | insert into COURSE (ID, AUTHOR, NAME) 6 | values (100003, 'in28minutes', 'Learn AWS, GCP and Azure'); -------------------------------------------------------------------------------- /01.Spring-Boot-Introduction-In-10-Steps/src/test/java/com/in28minutes/learnspringboot/LearnSpringBootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learnspringboot; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class LearnSpringBootApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/HELP.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | 4 | ## HTML 5 | 6 | ``` 7 | 8 | 9 | My first HTML Page 10 | 11 | 12 | My first html page with body 13 | 14 | 15 | ``` 16 | 17 | ## JSP 18 | 19 | /src/main/resources/META-INF/resources/WEB-INF/jsp/sayHello.jsp 20 | 21 | /say-hello-jsp => SayHelloController - sayHelloJsp method => sayHello 22 | 23 | /WEB-INF/jsp/sayHello.jsp 24 | 25 | 26 | ## Login JSP 27 | 28 | /login => com.in28minutes.springboot.myfirstwebapp.login.LoginController => login.jsp 29 | 30 | 31 | ## 32 | localhost:8080/login 33 | 34 | B1: Identifies correct Controller method 35 | /login => LoginController.gotoLoginPage 36 | 37 | B2: Executes Controller method 38 | => Puts data into model 39 | => Returns view name => login 40 | 41 | B3: Identifies correct View 42 | /WEB-INF/jsp/login.jsp 43 | 44 | B4: Executes view 45 | 46 | 47 | ## Todo 48 | 49 | id 50 | username 51 | description 52 | targetDate 53 | done 54 | 55 | TodoController 56 | listTodos.jsp 57 | 58 | ## Request vs Model vs Session 59 | 60 | - Request 61 | - Model 62 | - Session 63 | 64 | ## Validations 65 | - Client Side vs Server Side 66 | - 1: spring-boot-starter-validation 67 | - 2: 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step01.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | ## Complete Code Example 6 | 7 | 8 | ### /pom.xml 9 | 10 | ```xml 11 | 12 | 14 | 4.0.0 15 | 16 | org.springframework.boot 17 | spring-boot-starter-parent 18 | 3.3.4 19 | 20 | 21 | com.in28minutes.springboot 22 | myfirstwebapp 23 | 0.0.1-SNAPSHOT 24 | myfirstwebapp 25 | Demo project for Spring Boot 26 | 27 | 21 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-web 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-devtools 38 | runtime 39 | true 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-test 44 | test 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-maven-plugin 53 | 54 | 55 | 56 | 57 | 58 | spring-milestones 59 | Spring Milestones 60 | https://repo.spring.io/milestone 61 | 62 | false 63 | 64 | 65 | 66 | 67 | 68 | spring-milestones 69 | Spring Milestones 70 | https://repo.spring.io/milestone 71 | 72 | false 73 | 74 | 75 | 76 | 77 | 78 | ``` 79 | --- 80 | 81 | ### /src/main/java/com/in28minutes/springboot/myfirstwebapp/MyfirstwebappApplication.java 82 | 83 | ```java 84 | package com.in28minutes.springboot.myfirstwebapp; 85 | 86 | import org.springframework.boot.SpringApplication; 87 | import org.springframework.boot.autoconfigure.SpringBootApplication; 88 | 89 | @SpringBootApplication 90 | public class MyfirstwebappApplication { 91 | 92 | public static void main(String[] args) { 93 | SpringApplication.run(MyfirstwebappApplication.class, args); 94 | } 95 | 96 | } 97 | ``` 98 | --- 99 | 100 | ### /src/main/resources/application.properties 101 | 102 | ```properties 103 | #server.port=8081 104 | ``` 105 | --- 106 | 107 | ### /src/test/java/com/in28minutes/springboot/myfirstwebapp/MyfirstwebappApplicationTests.java 108 | 109 | ```java 110 | package com.in28minutes.springboot.myfirstwebapp; 111 | 112 | import org.junit.jupiter.api.Test; 113 | import org.springframework.boot.test.context.SpringBootTest; 114 | 115 | @SpringBootTest 116 | class MyfirstwebappApplicationTests { 117 | 118 | @Test 119 | void contextLoads() { 120 | } 121 | 122 | } 123 | ``` 124 | --- 125 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step01.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step01.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step03.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step03.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step04.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step04.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step05.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step05.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step06.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step06.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step08.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step08.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step11.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step11.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step13.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step13.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step17.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step17.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step19.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step19.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step20.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step20.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step25.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step25.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step26.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step26.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step27.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step27.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step28.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step28.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step29.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step29.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step31.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step31.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step33.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step33.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step35.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step35.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step36.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step36.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step38.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step38.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/Step41.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application-V2/Step41.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/java/com/in28minutes/springboot/myfirstwebapp/MyfirstwebappApplication.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.myfirstwebapp; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class MyfirstwebappApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(MyfirstwebappApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/java/com/in28minutes/springboot/myfirstwebapp/hello/SayHelloController.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.myfirstwebapp.hello; 2 | 3 | import org.springframework.stereotype.Controller; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.ResponseBody; 6 | 7 | @Controller 8 | public class SayHelloController { 9 | 10 | //"say-hello" => "Hello! What are you learning today?" 11 | 12 | //say-hello 13 | // http://localhost:8080/say-hello 14 | @RequestMapping("say-hello") 15 | @ResponseBody 16 | public String sayHello() { 17 | return "Hello! What are you learning today?"; 18 | } 19 | 20 | @RequestMapping("say-hello-html") 21 | @ResponseBody 22 | public String sayHelloHtml() { 23 | StringBuffer sb = new StringBuffer(); 24 | sb.append(""); 25 | sb.append(""); 26 | sb.append(" My First HTML Page - Changed"); 27 | sb.append(""); 28 | sb.append(""); 29 | sb.append("My first html page with body - Changed"); 30 | sb.append(""); 31 | sb.append(""); 32 | 33 | return sb.toString(); 34 | } 35 | 36 | // 37 | // "say-hello-jsp" => sayHello.jsp 38 | // /src/main/resources/META-INF/resources/WEB-INF/jsp/sayHello.jsp 39 | // /src/main/resources/META-INF/resources/WEB-INF/jsp/welcome.jsp 40 | // /src/main/resources/META-INF/resources/WEB-INF/jsp/login.jsp 41 | // /src/main/resources/META-INF/resources/WEB-INF/jsp/todos.jsp 42 | @RequestMapping("say-hello-jsp") 43 | public String sayHelloJsp() { 44 | return "sayHello"; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/java/com/in28minutes/springboot/myfirstwebapp/login/WelcomeController.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.myfirstwebapp.login; 2 | 3 | import org.springframework.security.core.Authentication; 4 | import org.springframework.security.core.context.SecurityContextHolder; 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.ui.ModelMap; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.SessionAttributes; 10 | 11 | @Controller 12 | @SessionAttributes("name") 13 | public class WelcomeController { 14 | 15 | @RequestMapping(value="/",method = RequestMethod.GET) 16 | public String gotoWelcomePage(ModelMap model) { 17 | model.put("name", getLoggedinUsername()); 18 | return "welcome"; 19 | } 20 | 21 | private String getLoggedinUsername() { 22 | Authentication authentication = 23 | SecurityContextHolder.getContext().getAuthentication(); 24 | return authentication.getName(); 25 | } 26 | } -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/java/com/in28minutes/springboot/myfirstwebapp/security/SpringSecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.myfirstwebapp.security; 2 | 3 | import static org.springframework.security.config.Customizer.withDefaults; 4 | 5 | import java.util.function.Function; 6 | 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10 | import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; 11 | import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer; 12 | import org.springframework.security.core.userdetails.User; 13 | import org.springframework.security.core.userdetails.UserDetails; 14 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 15 | import org.springframework.security.crypto.password.PasswordEncoder; 16 | import org.springframework.security.provisioning.InMemoryUserDetailsManager; 17 | import org.springframework.security.web.SecurityFilterChain; 18 | 19 | @Configuration 20 | public class SpringSecurityConfiguration { 21 | //LDAP or Database 22 | //In Memory 23 | 24 | //InMemoryUserDetailsManager 25 | //InMemoryUserDetailsManager(UserDetails... users) 26 | 27 | @Bean 28 | public InMemoryUserDetailsManager createUserDetailsManager() { 29 | 30 | UserDetails userDetails1 = createNewUser("in28minutes", "dummy"); 31 | UserDetails userDetails2 = createNewUser("ranga", "dummydummy"); 32 | 33 | return new InMemoryUserDetailsManager(userDetails1, userDetails2); 34 | } 35 | 36 | private UserDetails createNewUser(String username, String password) { 37 | Function passwordEncoder 38 | = input -> passwordEncoder().encode(input); 39 | 40 | UserDetails userDetails = User.builder() 41 | .passwordEncoder(passwordEncoder) 42 | .username(username) 43 | .password(password) 44 | .roles("USER","ADMIN") 45 | .build(); 46 | return userDetails; 47 | } 48 | 49 | @Bean 50 | public PasswordEncoder passwordEncoder() { 51 | return new BCryptPasswordEncoder(); 52 | } 53 | 54 | //All URLs are protected 55 | //A login form is shown for unauthorized requests 56 | //CSRF disable 57 | //Frames 58 | 59 | // Starting from Spring Boot 3.1.x Build Pattern/Fluent API Replaced with Lambda DSL(Domain Specific Language) or Method Reference 60 | @Bean 61 | public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { 62 | 63 | http.authorizeHttpRequests( 64 | auth -> auth.anyRequest().authenticated()); 65 | http.formLogin(withDefaults()); 66 | 67 | // http.csrf().disable(); 68 | http.csrf(csrf -> csrf.disable()); 69 | // http.csrf(AbstractHttpConfigurer::disable); 70 | // http.headers().frameOptions().disable(); 71 | http.headers(headers -> headers.frameOptions(frameOptionsConfig-> frameOptionsConfig.disable())); 72 | 73 | // http.headers(headers -> headers.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable)); 74 | 75 | return http.build(); 76 | } 77 | 78 | 79 | 80 | 81 | 82 | } 83 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/java/com/in28minutes/springboot/myfirstwebapp/todo/Todo.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.myfirstwebapp.todo; 2 | 3 | import java.time.LocalDate; 4 | 5 | import jakarta.persistence.Entity; 6 | import jakarta.persistence.GeneratedValue; 7 | import jakarta.persistence.Id; 8 | import jakarta.validation.constraints.Size; 9 | 10 | //Database (MySQL) 11 | //Static List of todos => Database (H2, MySQL) 12 | 13 | //JPA 14 | // Bean -> Database Table 15 | 16 | @Entity 17 | public class Todo { 18 | 19 | public Todo() { 20 | 21 | } 22 | 23 | public Todo(int id, String username, String description, LocalDate targetDate, boolean done) { 24 | super(); 25 | this.id = id; 26 | this.username = username; 27 | this.description = description; 28 | this.targetDate = targetDate; 29 | this.done = done; 30 | } 31 | 32 | @Id 33 | @GeneratedValue 34 | private int id; 35 | 36 | private String username; 37 | 38 | @Size(min=10, message="Enter at least 10 characters") 39 | private String description; 40 | private LocalDate targetDate; 41 | private boolean done; 42 | 43 | public int getId() { 44 | return id; 45 | } 46 | 47 | public void setId(int id) { 48 | this.id = id; 49 | } 50 | 51 | public String getUsername() { 52 | return username; 53 | } 54 | 55 | public void setUsername(String username) { 56 | this.username = username; 57 | } 58 | 59 | public String getDescription() { 60 | return description; 61 | } 62 | 63 | public void setDescription(String description) { 64 | this.description = description; 65 | } 66 | 67 | public LocalDate getTargetDate() { 68 | return targetDate; 69 | } 70 | 71 | public void setTargetDate(LocalDate targetDate) { 72 | this.targetDate = targetDate; 73 | } 74 | 75 | public boolean isDone() { 76 | return done; 77 | } 78 | 79 | public void setDone(boolean done) { 80 | this.done = done; 81 | } 82 | 83 | @Override 84 | public String toString() { 85 | return "Todo [id=" + id + ", username=" + username + ", description=" + description + ", targetDate=" 86 | + targetDate + ", done=" + done + "]"; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/java/com/in28minutes/springboot/myfirstwebapp/todo/TodoController.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.myfirstwebapp.todo; 2 | 3 | import java.time.LocalDate; 4 | import java.util.List; 5 | 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.security.core.context.SecurityContextHolder; 8 | import org.springframework.ui.ModelMap; 9 | import org.springframework.validation.BindingResult; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import jakarta.validation.Valid; 13 | 14 | //@Controller 15 | @SessionAttributes("name") 16 | public class TodoController { 17 | 18 | private TodoService todoService; 19 | 20 | public TodoController(TodoService todoService) { 21 | super(); 22 | this.todoService = todoService; 23 | } 24 | 25 | @RequestMapping("list-todos") 26 | public String listAllTodos(ModelMap model) { 27 | String username = getLoggedInUsername(model); 28 | List todos = todoService.findByUsername(username); 29 | model.addAttribute("todos", todos); 30 | 31 | return "listTodos"; 32 | } 33 | 34 | //GET, POST 35 | @RequestMapping(value="add-todo", method = RequestMethod.GET) 36 | public String showNewTodoPage(ModelMap model) { 37 | String username = getLoggedInUsername(model); 38 | Todo todo = new Todo(0, username, "", LocalDate.now().plusYears(1), false); 39 | model.put("todo", todo); 40 | return "todo"; 41 | } 42 | 43 | @RequestMapping(value="add-todo", method = RequestMethod.POST) 44 | public String addNewTodo(ModelMap model, @Valid Todo todo, BindingResult result) { 45 | 46 | if(result.hasErrors()) { 47 | return "todo"; 48 | } 49 | 50 | String username = getLoggedInUsername(model); 51 | todoService.addTodo(username, todo.getDescription(), 52 | LocalDate.now().plusYears(1), false); 53 | return "redirect:list-todos"; 54 | } 55 | 56 | @RequestMapping("delete-todo") 57 | public String deleteTodo(@RequestParam int id) { 58 | //Delete todo 59 | 60 | todoService.deleteById(id); 61 | return "redirect:list-todos"; 62 | 63 | } 64 | 65 | @RequestMapping(value="update-todo", method = RequestMethod.GET) 66 | public String showUpdateTodoPage(@RequestParam int id, ModelMap model) { 67 | Todo todo = todoService.findById(id); 68 | model.addAttribute("todo", todo); 69 | return "todo"; 70 | } 71 | 72 | @RequestMapping(value="update-todo", method = RequestMethod.POST) 73 | public String updateTodo(ModelMap model, @Valid Todo todo, BindingResult result) { 74 | 75 | if(result.hasErrors()) { 76 | return "todo"; 77 | } 78 | 79 | String username = getLoggedInUsername(model); 80 | todo.setUsername(username); 81 | todoService.updateTodo(todo); 82 | return "redirect:list-todos"; 83 | } 84 | 85 | private String getLoggedInUsername(ModelMap model) { 86 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 87 | return authentication.getName(); 88 | } 89 | 90 | } -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/java/com/in28minutes/springboot/myfirstwebapp/todo/TodoControllerJpa.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.myfirstwebapp.todo; 2 | 3 | import java.time.LocalDate; 4 | import java.util.List; 5 | 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.security.core.context.SecurityContextHolder; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.ui.ModelMap; 10 | import org.springframework.validation.BindingResult; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RequestMethod; 13 | import org.springframework.web.bind.annotation.RequestParam; 14 | import org.springframework.web.bind.annotation.SessionAttributes; 15 | 16 | import jakarta.validation.Valid; 17 | 18 | @Controller 19 | @SessionAttributes("name") 20 | public class TodoControllerJpa { 21 | 22 | private TodoRepository todoRepository; 23 | 24 | public TodoControllerJpa(TodoRepository todoRepository) { 25 | super(); 26 | this.todoRepository = todoRepository; 27 | } 28 | 29 | @RequestMapping("list-todos") 30 | public String listAllTodos(ModelMap model) { 31 | String username = getLoggedInUsername(model); 32 | 33 | List todos = todoRepository.findByUsername(username); 34 | model.addAttribute("todos", todos); 35 | 36 | return "listTodos"; 37 | } 38 | 39 | //GET, POST 40 | @RequestMapping(value="add-todo", method = RequestMethod.GET) 41 | public String showNewTodoPage(ModelMap model) { 42 | String username = getLoggedInUsername(model); 43 | Todo todo = new Todo(0, username, "", LocalDate.now().plusYears(1), false); 44 | model.put("todo", todo); 45 | return "todo"; 46 | } 47 | 48 | @RequestMapping(value="add-todo", method = RequestMethod.POST) 49 | public String addNewTodo(ModelMap model, @Valid Todo todo, BindingResult result) { 50 | 51 | if(result.hasErrors()) { 52 | return "todo"; 53 | } 54 | 55 | String username = getLoggedInUsername(model); 56 | todo.setUsername(username); 57 | todoRepository.save(todo); 58 | // todoService.addTodo(username, todo.getDescription(), 59 | // todo.getTargetDate(), todo.isDone()); 60 | return "redirect:list-todos"; 61 | } 62 | 63 | @RequestMapping("delete-todo") 64 | public String deleteTodo(@RequestParam int id) { 65 | //Delete todo 66 | todoRepository.deleteById(id); 67 | return "redirect:list-todos"; 68 | 69 | } 70 | 71 | @RequestMapping(value="update-todo", method = RequestMethod.GET) 72 | public String showUpdateTodoPage(@RequestParam int id, ModelMap model) { 73 | Todo todo = todoRepository.findById(id).get(); 74 | model.addAttribute("todo", todo); 75 | return "todo"; 76 | } 77 | 78 | @RequestMapping(value="update-todo", method = RequestMethod.POST) 79 | public String updateTodo(ModelMap model, @Valid Todo todo, BindingResult result) { 80 | 81 | if(result.hasErrors()) { 82 | return "todo"; 83 | } 84 | 85 | String username = getLoggedInUsername(model); 86 | todo.setUsername(username); 87 | todoRepository.save(todo); 88 | return "redirect:list-todos"; 89 | } 90 | 91 | private String getLoggedInUsername(ModelMap model) { 92 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 93 | return authentication.getName(); 94 | } 95 | 96 | } -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/java/com/in28minutes/springboot/myfirstwebapp/todo/TodoRepository.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.myfirstwebapp.todo; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | public interface TodoRepository extends JpaRepository{ 8 | List findByUsername(String username); 9 | } 10 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/java/com/in28minutes/springboot/myfirstwebapp/todo/TodoService.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.myfirstwebapp.todo; 2 | 3 | import java.time.LocalDate; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.function.Predicate; 7 | 8 | import org.springframework.stereotype.Service; 9 | 10 | import jakarta.validation.Valid; 11 | 12 | @Service 13 | public class TodoService { 14 | 15 | private static final List todos = new ArrayList<>(); 16 | 17 | private static int todosCount = 0; 18 | 19 | static { 20 | todos.add(new Todo(++todosCount, "in28minutes","Get AWS Certified 1", 21 | LocalDate.now().plusYears(1), false )); 22 | todos.add(new Todo(++todosCount, "in28minutes","Learn DevOps 1", 23 | LocalDate.now().plusYears(2), false )); 24 | todos.add(new Todo(++todosCount, "in28minutes","Learn Full Stack Development 1", 25 | LocalDate.now().plusYears(3), false )); 26 | } 27 | 28 | public List findByUsername(String username){ 29 | Predicate predicate = 30 | todo -> todo.getUsername().equalsIgnoreCase(username); 31 | return todos.stream().filter(predicate).toList(); 32 | } 33 | 34 | public void addTodo(String username, String description, LocalDate targetDate, boolean done) { 35 | Todo todo = new Todo(++todosCount,username,description,targetDate,done); 36 | todos.add(todo); 37 | } 38 | 39 | public void deleteById(int id) { 40 | //todo.getId() == id 41 | // todo -> todo.getId() == id 42 | Predicate predicate = todo -> todo.getId() == id; 43 | todos.removeIf(predicate); 44 | } 45 | 46 | public Todo findById(int id) { 47 | Predicate predicate = todo -> todo.getId() == id; 48 | Todo todo = todos.stream().filter(predicate).findFirst().get(); 49 | return todo; 50 | } 51 | 52 | public void updateTodo(@Valid Todo todo) { 53 | deleteById(todo.getId()); 54 | todos.add(todo); 55 | } 56 | } -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/resources/META-INF/resources/WEB-INF/jsp/common/footer.jspf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/resources/META-INF/resources/WEB-INF/jsp/common/header.jspf: -------------------------------------------------------------------------------- 1 | <%@ taglib prefix="c" uri="jakarta.tags.core" %> 2 | <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Manage Your Todos 11 | 12 | 13 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/resources/META-INF/resources/WEB-INF/jsp/common/navigation.jspf: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/resources/META-INF/resources/WEB-INF/jsp/listTodos.jsp: -------------------------------------------------------------------------------- 1 | <%@ include file="common/header.jspf" %> 2 | <%@ include file="common/navigation.jspf" %> 3 |
4 |

Your Todos

5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
DescriptionTarget DateIs Done?
${todo.description}${todo.targetDate}${todo.done} Delete Update
27 | Add Todo 28 |
29 | 30 | <%@ include file="common/footer.jspf" %> -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/resources/META-INF/resources/WEB-INF/jsp/sayHello.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | My first HTML Page - JSP 4 | 5 | 6 |

Heading 1

7 |

Heading 2

8 | 9 | My first html page with body - JSP 10 | 11 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/resources/META-INF/resources/WEB-INF/jsp/todo.jsp: -------------------------------------------------------------------------------- 1 | <%@ include file="common/header.jspf" %> 2 | <%@ include file="common/navigation.jspf" %> 3 | 4 |
5 | 6 |

Enter Todo Details

7 | 8 | 9 | 10 |
11 | Description 12 | 13 | 14 |
15 | 16 |
17 | Target Date 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
32 | 33 | <%@ include file="common/footer.jspf" %> 34 | 35 | 40 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/resources/META-INF/resources/WEB-INF/jsp/welcome.jsp: -------------------------------------------------------------------------------- 1 | <%@ include file="common/header.jspf" %> 2 | <%@ include file="common/navigation.jspf" %> 3 | 4 |
5 |

Welcome ${name}

6 | Manage your todos 7 |
8 | 9 | <%@ include file="common/footer.jspf" %> 10 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #server.port=8081 2 | #sayHello.jsp 3 | #/WEB-INF/jsp/sayHello.jsp 4 | 5 | # /WEB-INF/jsp/login.jsp => View Resolver 6 | spring.mvc.view.prefix=/WEB-INF/jsp/ 7 | spring.mvc.view.suffix=.jsp 8 | logging.level.org.springframework.security=info 9 | logging.level.com.in28minutes.springboot.myfirstwebapp=info 10 | 11 | spring.mvc.format.date=yyyy-MM-dd 12 | 13 | #spring.datasource.url=jdbc:h2:mem:testdb 14 | spring.jpa.defer-datasource-initialization=true 15 | 16 | spring.datasource.url=jdbc:mysql://localhost:3306/todos 17 | spring.datasource.username=todos-user 18 | spring.datasource.password=dummytodos 19 | spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect 20 | 21 | spring.jpa.hibernate.ddl-auto=update 22 | 23 | #/connect todos-user@localhost:3306 24 | #docker run --detach 25 | #--env MYSQL_ROOT_PASSWORD=dummypassword 26 | #--env MYSQL_USER=todos-user 27 | #--env MYSQL_PASSWORD=dummytodos 28 | #--env MYSQL_DATABASE=todos 29 | #--name mysql 30 | #--publish 3306:3306 31 | #mysql:8-oracle -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/main/resources/data.sql: -------------------------------------------------------------------------------- 1 | insert into todo (ID, USERNAME, DESCRIPTION, TARGET_DATE, DONE) 2 | values(10001,'in28minutes', 'Get AWS Certified', CURRENT_DATE(), false); 3 | 4 | insert into todo (ID, USERNAME, DESCRIPTION, TARGET_DATE, DONE) 5 | values(10002,'in28minutes', 'Get Azure Certified', CURRENT_DATE(), false); 6 | 7 | insert into todo (ID, USERNAME, DESCRIPTION, TARGET_DATE, DONE) 8 | values(10003,'in28minutes', 'Get GCP Certified', CURRENT_DATE(), false); 9 | 10 | insert into todo (ID, USERNAME, DESCRIPTION, TARGET_DATE, DONE) 11 | values(10004,'in28minutes', 'Learn DevOps', CURRENT_DATE(), false); -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application-V2/src/test/java/com/in28minutes/springboot/myfirstwebapp/MyfirstwebappApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.myfirstwebapp; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class MyfirstwebappApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step01.md: -------------------------------------------------------------------------------- 1 | ## What You Will Learn during this Step: 2 | - Lets create a simple web application using Spring Boot 3 | - Lets run the Spring Boot Application 4 | - There is a lot of magic happening in here! We will take a deep dive into the magic in Step 03. 5 | 6 | ## Files List 7 | 8 | ### pom.xml 9 | 10 | ```xml 11 | 12 | 14 | 4.0.0 15 | 16 | com.in28minutes.springboot.web 17 | spring-boot-first-web-application 18 | 0.0.1-SNAPSHOT 19 | jar 20 | 21 | spring-boot-first-web-application 22 | Demo project for Spring Boot 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-parent 27 | 1.4.3.RELEASE 28 | 29 | 30 | 31 | 32 | UTF-8 33 | UTF-8 34 | 1.8 35 | 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-web 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-devtools 45 | runtime 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-test 50 | test 51 | 52 | 53 | 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-maven-plugin 59 | 60 | 61 | 62 | 63 | 64 | ``` 65 | --- 66 | ### src/main/java/com/in28minutes/springboot/web/SpringBootFirstWebApplication.java 67 | 68 | ```java 69 | package com.in28minutes.springboot.web; 70 | 71 | import org.springframework.boot.SpringApplication; 72 | import org.springframework.boot.autoconfigure.SpringBootApplication; 73 | 74 | @SpringBootApplication 75 | public class SpringBootFirstWebApplication { 76 | 77 | public static void main(String[] args) { 78 | SpringApplication.run(SpringBootFirstWebApplication.class, args); 79 | } 80 | } 81 | ``` 82 | --- 83 | ### src/main/resources/application.properties 84 | 85 | ``` 86 | ``` 87 | --- 88 | ### src/test/java/com/in28minutes/springboot/web/SpringBootFirstWebApplicationTests.java 89 | 90 | ```java 91 | package com.in28minutes.springboot.web; 92 | 93 | import org.junit.Test; 94 | import org.junit.runner.RunWith; 95 | import org.springframework.boot.test.context.SpringBootTest; 96 | import org.springframework.test.context.junit4.SpringRunner; 97 | 98 | @RunWith(SpringRunner.class) 99 | @SpringBootTest 100 | public class SpringBootFirstWebApplicationTests { 101 | 102 | @Test 103 | public void contextLoads() { 104 | } 105 | 106 | } 107 | ``` 108 | --- 109 | ### todo.txt 110 | 111 | ``` 112 | Spring Boot Starter Parent 113 | Spring Boot Starter Web 114 | @SpringBootApplication 115 | Auto Configuration 116 | ``` 117 | --- 118 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step03.md: -------------------------------------------------------------------------------- 1 | ## What You Will Learn during this Step: 2 | - Demystifying some of the magic 3 | - Spring Boot Starter Parent 4 | - Spring Boot Starter Web 5 | - Embedded Tomcat 6 | - Dev Tools 7 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step06.md: -------------------------------------------------------------------------------- 1 | ## What You Will Learn during this Step: 2 | - Understand importance of DispatcherServlet. 3 | 4 | ## Spring MVC Request Flow 5 | - DispatcherServlet receives HTTP Request. 6 | - DispatcherServlet identifies the right Controller based on the URL. 7 | - Controller executes Business Logic. 8 | - Controller returns a) Model b) View Name Back to DispatcherServlet. 9 | - DispatcherServlet identifies the correct view (ViewResolver). 10 | - DispatcherServlet makes the model available to view and executes it. 11 | - DispatcherServlet returns HTTP Response Back. 12 | - Flow : http://docs.spring.io/spring-framework/docs/2.0.8/reference/images/mvc.png 13 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step07.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/Step07.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step08.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/Step08.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step09.md: -------------------------------------------------------------------------------- 1 | ## What You Will Learn during this Step: 2 | - Magic of Spring 3 | - Learn about Spring Auto-wiring and Dependency Management. 4 | - @Autowired, @Component 5 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step11.md: -------------------------------------------------------------------------------- 1 | ## What we will do: 2 | - Lets discuss about Architecture of web applications 3 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step12.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/Step12.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step13.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/Step13.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step14.md: -------------------------------------------------------------------------------- 1 | ## What we will do: 2 | - Display Todos in a table using JSTL Tags 3 | - <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 4 | - Add Dependency for jstl 5 | 6 | ## Snippet 7 | ``` 8 | 9 | javax.servlet 10 | jstl 11 | 12 | ``` 13 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step15.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/Step15.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step16.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/Step16.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step18.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/Step18.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step19.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/Step19.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step20.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/Step20.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step21.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/Step21.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step22.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/Step22.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step23.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/Step23.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step24.md: -------------------------------------------------------------------------------- 1 | ## What we will do: 2 | - Remove Hardcoding of User Name 3 | - Remove LoginService 4 | - Rename LoginController to WelcomeController 5 | - Add Logout Functionality 6 | 7 | ## Useful Snippets 8 | ``` 9 | private String getLoggedInUserName(ModelMap model) { 10 | Object principal = SecurityContextHolder.getContext() 11 | .getAuthentication().getPrincipal(); 12 | 13 | if (principal instanceof UserDetails) 14 | return ((UserDetails) principal).getUsername(); 15 | 16 | return principal.toString(); 17 | } 18 | 19 | 22 | 23 | @RequestMapping(value = "/logout", method = RequestMethod.GET) 24 | public String logout(HttpServletRequest request, 25 | HttpServletResponse response) { 26 | Authentication auth = SecurityContextHolder.getContext() 27 | .getAuthentication(); 28 | if (auth != null) { 29 | new SecurityContextLogoutHandler().logout(request, response, auth); 30 | } 31 | return "redirect:/"; 32 | } 33 | 34 | ``` 35 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/Step25.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/Step25.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/StepReference.md: -------------------------------------------------------------------------------- 1 | ## What You Will Learn during this Step: 2 | - First 3 | - Second 4 | - Third 5 | 6 | ## Useful Snippets and References 7 | First Snippet 8 | ``` 9 | ``` 10 | Second Snippet 11 | ``` 12 | ``` 13 | 14 | ## Exercises 15 | 16 | ## Files List 17 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/java/com/in28minutes/springboot/web/SpringBootFirstWebApplication.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.web; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.ComponentScan; 6 | 7 | @SpringBootApplication 8 | @ComponentScan("com.in28minutes.springboot.web") 9 | public class SpringBootFirstWebApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(SpringBootFirstWebApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/java/com/in28minutes/springboot/web/controller/ErrorController.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.web.controller; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.web.bind.annotation.ExceptionHandler; 7 | import org.springframework.web.servlet.ModelAndView; 8 | 9 | @Controller("error") 10 | public class ErrorController { 11 | 12 | @ExceptionHandler(Exception.class) 13 | public ModelAndView handleException 14 | (HttpServletRequest request, Exception ex){ 15 | ModelAndView mv = new ModelAndView(); 16 | 17 | mv.addObject("exception", ex.getLocalizedMessage()); 18 | mv.addObject("url", request.getRequestURL()); 19 | 20 | mv.setViewName("error"); 21 | return mv; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/java/com/in28minutes/springboot/web/controller/LogoutController.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.web.controller; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | import javax.servlet.http.HttpServletResponse; 5 | 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.security.core.context.SecurityContextHolder; 8 | import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RequestMethod; 12 | 13 | @Controller 14 | public class LogoutController { 15 | 16 | @RequestMapping(value = "/logout", method = RequestMethod.GET) 17 | public String logout(HttpServletRequest request, 18 | HttpServletResponse response) { 19 | 20 | Authentication authentication = SecurityContextHolder.getContext() 21 | .getAuthentication(); 22 | 23 | if (authentication != null) { 24 | new SecurityContextLogoutHandler().logout(request, response, 25 | authentication); 26 | } 27 | 28 | return "redirect:/"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/java/com/in28minutes/springboot/web/controller/WelcomeController.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.web.controller; 2 | 3 | import org.springframework.security.core.context.SecurityContextHolder; 4 | import org.springframework.security.core.userdetails.UserDetails; 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.ui.ModelMap; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | 10 | @Controller 11 | public class WelcomeController { 12 | 13 | @RequestMapping(value = "/", method = RequestMethod.GET) 14 | public String showWelcomePage(ModelMap model) { 15 | model.put("name", getLoggedinUserName()); 16 | return "welcome"; 17 | } 18 | 19 | private String getLoggedinUserName() { 20 | Object principal = SecurityContextHolder.getContext() 21 | .getAuthentication().getPrincipal(); 22 | 23 | if (principal instanceof UserDetails) { 24 | return ((UserDetails) principal).getUsername(); 25 | } 26 | 27 | return principal.toString(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/java/com/in28minutes/springboot/web/model/Todo.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.web.model; 2 | 3 | import java.util.Date; 4 | 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.Id; 8 | import javax.validation.constraints.Size; 9 | 10 | @Entity 11 | public class Todo { 12 | 13 | @Id 14 | @GeneratedValue 15 | private int id; 16 | 17 | private String user; 18 | 19 | @Size(min=10, message="Enter at least 10 Characters...") 20 | private String desc; 21 | 22 | private Date targetDate; 23 | private boolean isDone; 24 | 25 | public Todo() { 26 | super(); 27 | } 28 | 29 | public Todo(int id, String user, String desc, Date targetDate, 30 | boolean isDone) { 31 | super(); 32 | this.id = id; 33 | this.user = user; 34 | this.desc = desc; 35 | this.targetDate = targetDate; 36 | this.isDone = isDone; 37 | } 38 | 39 | public int getId() { 40 | return id; 41 | } 42 | 43 | public void setId(int id) { 44 | this.id = id; 45 | } 46 | 47 | public String getUser() { 48 | return user; 49 | } 50 | 51 | public void setUser(String user) { 52 | this.user = user; 53 | } 54 | 55 | public String getDesc() { 56 | return desc; 57 | } 58 | 59 | public void setDesc(String desc) { 60 | this.desc = desc; 61 | } 62 | 63 | public Date getTargetDate() { 64 | return targetDate; 65 | } 66 | 67 | public void setTargetDate(Date targetDate) { 68 | this.targetDate = targetDate; 69 | } 70 | 71 | public boolean isDone() { 72 | return isDone; 73 | } 74 | 75 | public void setDone(boolean isDone) { 76 | this.isDone = isDone; 77 | } 78 | 79 | @Override 80 | public int hashCode() { 81 | final int prime = 31; 82 | int result = 1; 83 | result = prime * result + id; 84 | return result; 85 | } 86 | 87 | @Override 88 | public boolean equals(Object obj) { 89 | if (this == obj) { 90 | return true; 91 | } 92 | if (obj == null) { 93 | return false; 94 | } 95 | if (getClass() != obj.getClass()) { 96 | return false; 97 | } 98 | Todo other = (Todo) obj; 99 | if (id != other.id) { 100 | return false; 101 | } 102 | return true; 103 | } 104 | 105 | @Override 106 | public String toString() { 107 | return String.format( 108 | "Todo [id=%s, user=%s, desc=%s, targetDate=%s, isDone=%s]", id, 109 | user, desc, targetDate, isDone); 110 | } 111 | 112 | } -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/java/com/in28minutes/springboot/web/security/SecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.web.security; 2 | 3 | // import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | // import org.springframework.context.annotation.Configuration; 6 | // import org.springframework.http.HttpMethod; 7 | // import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 8 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 9 | // import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 10 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 11 | import org.springframework.security.core.userdetails.User; 12 | import org.springframework.security.core.userdetails.UserDetails; 13 | import org.springframework.security.provisioning.InMemoryUserDetailsManager; 14 | import org.springframework.security.web.SecurityFilterChain; 15 | 16 | // @Configuration 17 | // public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 18 | @EnableWebSecurity 19 | public class SecurityConfiguration { 20 | //Create User - in28Minutes/dummy 21 | // @Autowired 22 | // public void configureGlobalSecurity(AuthenticationManagerBuilder auth) 23 | // throws Exception { 24 | // auth.inMemoryAuthentication() 25 | // .passwordEncoder(NoOpPasswordEncoder.getInstance()) 26 | // .withUser("in28Minutes").password("dummy") 27 | // .roles("USER", "ADMIN"); 28 | // } 29 | 30 | // We used the method User.withDefaultPasswordEncoder() for readability and course purpose. 31 | // It is not intended for PRODUCTION environment, and instead we recommend hashing your passwords externally 32 | @Bean 33 | public InMemoryUserDetailsManager userDetailsService() { 34 | UserDetails user = User.withDefaultPasswordEncoder() 35 | .username("in28Minutes") 36 | .password("dummy") 37 | .roles("ADMIN", "USER") 38 | .build(); 39 | 40 | return new InMemoryUserDetailsManager(user); 41 | } 42 | 43 | // In Spring Security 5.4 introduced the ability to configure HttpSecurity by creating a SecurityFilterChain bean. 44 | @Bean 45 | public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { 46 | http.authorizeRequests((authorize) -> { 47 | try { 48 | authorize 49 | .antMatchers("/login", "/h2-console/**").permitAll() 50 | .antMatchers("/", "/*todo*/**").hasRole("USER") 51 | .and().formLogin() 52 | .and().csrf().disable() 53 | .headers().frameOptions().disable(); 54 | 55 | } catch (Exception e) { 56 | throw new RuntimeException(e); 57 | } 58 | }); 59 | 60 | 61 | return http.build(); 62 | } 63 | 64 | // Previous version that securing all endpoints with HTTP basic 65 | // @Override 66 | // protected void configure(HttpSecurity http) throws Exception { 67 | // http.authorizeRequests().antMatchers("/login", "/h2-console/**").permitAll() 68 | // .antMatchers("/", "/*todo*/**").access("hasRole('USER')").and() 69 | // .formLogin(); 70 | // 71 | // http.csrf().disable(); 72 | // http.headers().frameOptions().disable(); 73 | // } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/java/com/in28minutes/springboot/web/service/TodoRepository.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.web.service; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import com.in28minutes.springboot.web.model.Todo; 8 | 9 | public interface TodoRepository extends JpaRepository{ 10 | List findByUser(String userName); 11 | 12 | //service.retrieveTodos(name) 13 | 14 | //service.deleteTodo(id); 15 | //service.retrieveTodo(id) 16 | //service.updateTodo(todo) 17 | //service.addTodo(getLoggedInUserName(model), todo.getDesc(), todo.getTargetDate(),false); 18 | } 19 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/java/com/in28minutes/springboot/web/service/TodoService.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.web.service; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Date; 5 | import java.util.Iterator; 6 | import java.util.List; 7 | 8 | import org.springframework.stereotype.Service; 9 | 10 | import com.in28minutes.springboot.web.model.Todo; 11 | 12 | @Service 13 | public class TodoService { 14 | private static List todos = new ArrayList(); 15 | private static int todoCount = 3; 16 | 17 | static { 18 | todos.add(new Todo(1, "in28Minutes", "Learn Spring MVC", new Date(), 19 | false)); 20 | todos.add(new Todo(2, "in28Minutes", "Learn Struts", new Date(), false)); 21 | todos.add(new Todo(3, "in28Minutes", "Learn Hibernate", new Date(), 22 | false)); 23 | } 24 | 25 | public List retrieveTodos(String user) { 26 | List filteredTodos = new ArrayList(); 27 | for (Todo todo : todos) { 28 | if (todo.getUser().equalsIgnoreCase(user)) { 29 | filteredTodos.add(todo); 30 | } 31 | } 32 | return filteredTodos; 33 | } 34 | 35 | public Todo retrieveTodo(int id) { 36 | for (Todo todo : todos) { 37 | if (todo.getId()==id) { 38 | return todo; 39 | } 40 | } 41 | return null; 42 | } 43 | 44 | public void updateTodo(Todo todo){ 45 | todos.remove(todo); 46 | todos.add(todo); 47 | } 48 | 49 | public void addTodo(String name, String desc, Date targetDate, 50 | boolean isDone) { 51 | todos.add(new Todo(++todoCount, name, desc, targetDate, isDone)); 52 | } 53 | 54 | public void deleteTodo(int id) { 55 | Iterator iterator = todos.iterator(); 56 | while (iterator.hasNext()) { 57 | Todo todo = iterator.next(); 58 | if (todo.getId() == id) { 59 | iterator.remove(); 60 | } 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/resources/META-INF/resources/WEB-INF/jsp/common/footer.jspf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/resources/META-INF/resources/WEB-INF/jsp/common/header.jspf: -------------------------------------------------------------------------------- 1 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> 3 | <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> 4 | 5 | 6 | 7 | 8 | Spring Boot Normal Web Application 9 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/resources/META-INF/resources/WEB-INF/jsp/common/navigation.jspf: -------------------------------------------------------------------------------- 1 | 2 | 16 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/resources/META-INF/resources/WEB-INF/jsp/error.jsp: -------------------------------------------------------------------------------- 1 | <%@ include file="common/header.jspf"%> 2 | <%@ include file="common/navigation.jspf"%> 3 |
4 | An exception occurred! Please contact Support! 5 |
6 | <%@ include file="common/footer.jspf"%> -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/resources/META-INF/resources/WEB-INF/jsp/list-todos.jsp: -------------------------------------------------------------------------------- 1 | <%@ include file="common/header.jspf" %> 2 | <%@ include file="common/navigation.jspf" %> 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 24 | 26 | 27 | 28 | 29 |
Your todos are
DescriptionTarget DateIs it Done?
${todo.desc}${todo.done}UpdateDelete
30 |
31 | Add a Todo 32 |
33 |
34 | <%@ include file="common/footer.jspf" %> -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/resources/META-INF/resources/WEB-INF/jsp/todo.jsp: -------------------------------------------------------------------------------- 1 | <%@ include file="common/header.jspf" %> 2 | <%@ include file="common/navigation.jspf" %> 3 |
4 | 5 | 6 |
7 | Description 8 | 10 | 11 |
12 | 13 |
14 | Target Date 15 | 17 | 18 |
19 | 20 | 21 |
22 |
23 | <%@ include file="common/footer.jspf" %> -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/resources/META-INF/resources/WEB-INF/jsp/welcome.jsp: -------------------------------------------------------------------------------- 1 | <%@ include file="common/header.jspf"%> 2 | <%@ include file="common/navigation.jspf"%> 3 |
4 | Welcome ${name}!! Click here to manage your 5 | todo's. 6 |
7 | <%@ include file="common/footer.jspf"%> -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.mvc.view.prefix=/WEB-INF/jsp/ 2 | spring.mvc.view.suffix=.jsp 3 | logging.level.org.springframework.web=INFO 4 | 5 | spring.jpa.show-sql=true 6 | spring.h2.console.enabled=true 7 | spring.datasource.url=jdbc:h2:mem:testdb;NON_KEYWORDS=USER 8 | spring.jpa.defer-datasource-initialization=true -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/main/resources/data.sql: -------------------------------------------------------------------------------- 1 | /* Changed from sysdate()(NotAvailable in Latest H2 Functions) to CURRENT_DATE */ 2 | insert into TODO 3 | values(10001, 'Learn Spring Boot', false, CURRENT_DATE(), 'in28Minutes'); 4 | insert into TODO 5 | values(10002, 'Learn Angular JS', false, CURRENT_DATE(), 'in28Minutes'); 6 | insert into TODO 7 | values(10003, 'Learn to Dance', false, CURRENT_DATE(), 'in28Minutes'); 8 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/src/test/java/com/in28minutes/springboot/web/SpringBootFirstWebApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.web; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.junit.jupiter.api.extension.ExtendWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit.jupiter.SpringExtension; 7 | 8 | // replaced @RunWith with @ExtendWith 9 | // replaced SpringRunner.class with SpringExtension.class 10 | @ExtendWith(SpringExtension.class) 11 | @SpringBootTest 12 | public class SpringBootFirstWebApplicationTests { 13 | 14 | @Test 15 | public void contextLoads() { 16 | } 17 | 18 | } 19 | 20 | -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/step32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/step32.zip -------------------------------------------------------------------------------- /02.Spring-Boot-Web-Application/step33-Upgrade-To-Sprint-Boot-2-M3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/02.Spring-Boot-Web-Application/step33-Upgrade-To-Sprint-Boot-2-M3.zip -------------------------------------------------------------------------------- /03.JUnit-Introduction-In-5-Steps-V2/prep.md: -------------------------------------------------------------------------------- 1 | ## Slides 2 | 3 | - Large applications can 1000s of Code files and millions of lines of code 4 | - Testing is done to check if the behavior of the application is as expected 5 | - Option 1: Deploy the complete application and test 6 | - This is called System Testing or Integration Testing 7 | - Option 2: Test specific units of application code 8 | - Examples: A specific method or group of methods 9 | - This is called Unit Testing 10 | - Advantages of Unit Testing 11 | - Finds bug early 12 | - Can be run under Continuous Integration 13 | - Easy to fix bugs 14 | - Reduces costs in the long run 15 | 16 | ## Notes 17 | 18 | ``` 19 | Absence of failure is success 20 | 21 | Create a Java Project in Eclipse without using Modules 22 | Add sum method 23 | Create a new Test source folder 24 | Use Eclipse Menu to create New JUnit 5 Test Case, it would automatically ask to add JUnit 5 to class path. 25 | 26 | assertEquals(1,2)//Lot of types 27 | assertTrue 28 | assertFalse 29 | assertNotNull 30 | assertNull 31 | 32 | @BeforeAll 33 | @BeforeEach 34 | @AfterAll 35 | @AfterEach 36 | ``` -------------------------------------------------------------------------------- /03.JUnit-Introduction-In-5-Steps-V2/src/com/in28minutes/junit/MyMath.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.junit; 2 | 3 | public class MyMath { 4 | 5 | //{1,2,3} => 1+2+3 = 6 6 | public int calculateSum(int[] numbers) { 7 | 8 | int sum = 0; 9 | 10 | for(int number:numbers) { 11 | sum += number; 12 | } 13 | 14 | return sum; 15 | } 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /03.JUnit-Introduction-In-5-Steps-V2/test/com/in28minutes/junit/MyAssertTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.junit; 2 | 3 | import static org.junit.Assert.assertArrayEquals; 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | import static org.junit.jupiter.api.Assertions.assertFalse; 6 | import static org.junit.jupiter.api.Assertions.assertTrue; 7 | 8 | import java.util.Arrays; 9 | import java.util.List; 10 | 11 | import org.junit.jupiter.api.Test; 12 | 13 | class MyAssertTest { 14 | 15 | List todos = Arrays.asList("AWS", "Azure", "DevOps"); 16 | 17 | @Test 18 | void testAsserts() { 19 | boolean test = todos.contains("AWS");//Result 20 | boolean test2 = todos.contains("GCP");//Result 21 | 22 | //assertEquals(true, test); 23 | assertTrue(test); 24 | assertFalse(test2); 25 | //assertNull,assertNotNull 26 | assertArrayEquals(new int[] {1,2}, new int[] {2, 1}); 27 | 28 | assertEquals(3, todos.size()); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /03.JUnit-Introduction-In-5-Steps-V2/test/com/in28minutes/junit/MyBeforeAfterTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.junit; 2 | 3 | import org.junit.jupiter.api.AfterAll; 4 | import org.junit.jupiter.api.AfterEach; 5 | import org.junit.jupiter.api.BeforeAll; 6 | import org.junit.jupiter.api.BeforeEach; 7 | import org.junit.jupiter.api.Test; 8 | 9 | class MyBeforeAfterTest { 10 | 11 | 12 | @BeforeAll 13 | static void beforeAll() { 14 | System.out.println("beforeAll"); 15 | } 16 | 17 | @BeforeEach 18 | void beforeEach() { 19 | System.out.println("BeforeEach"); 20 | } 21 | 22 | @Test 23 | void test1() { 24 | System.out.println("test1"); 25 | } 26 | 27 | @Test 28 | void test2() { 29 | System.out.println("test2"); 30 | } 31 | 32 | @Test 33 | void test3() { 34 | System.out.println("test3"); 35 | } 36 | 37 | @AfterEach 38 | void afterEach() { 39 | System.out.println("AfterEach"); 40 | } 41 | 42 | @AfterAll 43 | static void afterAll() { 44 | System.out.println("afterAll"); 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /03.JUnit-Introduction-In-5-Steps-V2/test/com/in28minutes/junit/MyMathTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.junit; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | class MyMathTest { 8 | 9 | private MyMath math = new MyMath(); 10 | 11 | @Test 12 | void calculateSum_ThreeMemberArray() { 13 | assertEquals(6, math.calculateSum(new int[] {1,2,3})); 14 | } 15 | 16 | @Test 17 | void calculateSum_ZeroLengthArray() { 18 | assertEquals(0, math.calculateSum(new int[] {})); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /03.JUnit-Introduction-In-5-Steps/.gitignore: -------------------------------------------------------------------------------- 1 | /bin/ 2 | -------------------------------------------------------------------------------- /03.JUnit-Introduction-In-5-Steps/code-21July2017.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/03.JUnit-Introduction-In-5-Steps/code-21July2017.zip -------------------------------------------------------------------------------- /03.JUnit-Introduction-In-5-Steps/readme.md: -------------------------------------------------------------------------------- 1 | ## First 5 Steps in JUnit 2 | 3 | - Git Repository - https://github.com/in28minutes/getting-started-in-5-steps 4 | - Pre-requisites - Java & Eclipse - https://www.youtube.com/playlist?list=PLBBog2r6uMCSmMVTW_QmDLyASBvovyAO3 5 | - We will use embedded maven in Eclipse 6 | 7 | ### Step 1 : What is JUnit and Unit Testing? 8 | - What is JUnit? 9 | - What is Unit Testing? 10 | - Advantages of Unit Testing 11 | 12 | ### Step 2 : First JUnit Project and Green Bar 13 | - What is JUnit? 14 | - First Project with JUnit 15 | - First JUnit Class 16 | - No Failure is Success 17 | - MyMath class with sum method 18 | 19 | ### Step 3 : First Code and First Unit Test 20 | - Unit test for the sum method 21 | 22 | ### Step 4 : Other assert methods 23 | - assertTrue and assertFalse methods 24 | 25 | ### Step 5 : Important annotations 26 | - @Before @After annotations 27 | - @BeforeClass @AfterClass annotations 28 | 29 | ## Complete Code Example 30 | 31 | 32 | ### /src/com/in28minutes/junit/MyMath.java 33 | 34 | ```java 35 | package com.in28minutes.junit; 36 | 37 | public class MyMath { 38 | int sum(int[] numbers) { 39 | int sum = 0; 40 | for (int i : numbers) { 41 | sum += i; 42 | } 43 | return sum; 44 | } 45 | } 46 | ``` 47 | --- 48 | 49 | ### /test/com/in28minutes/junit/AssertTest.java 50 | 51 | ```java 52 | package com.in28minutes.junit; 53 | 54 | import static org.junit.Assert.assertEquals; 55 | import static org.junit.Assert.assertTrue; 56 | 57 | import org.junit.Test; 58 | 59 | public class AssertTest { 60 | 61 | @Test 62 | public void test() { 63 | boolean condn = true; 64 | assertEquals(true, condn); 65 | assertTrue(condn); 66 | // assertFalse(condn); 67 | } 68 | 69 | } 70 | ``` 71 | --- 72 | 73 | ### /test/com/in28minutes/junit/MyMathTest.java 74 | 75 | ```java 76 | package com.in28minutes.junit; 77 | 78 | import static org.junit.Assert.assertEquals; 79 | 80 | import org.junit.After; 81 | import org.junit.AfterClass; 82 | import org.junit.Before; 83 | import org.junit.BeforeClass; 84 | import org.junit.Test; 85 | 86 | public class MyMathTest { 87 | MyMath myMath = new MyMath(); 88 | 89 | @Before 90 | public void before() { 91 | System.out.println("Before"); 92 | } 93 | 94 | @After 95 | public void after() { 96 | System.out.println("After"); 97 | } 98 | 99 | @BeforeClass 100 | public static void beforeClass() { 101 | System.out.println("Before Class"); 102 | } 103 | 104 | @AfterClass 105 | public static void afterClass() { 106 | System.out.println("After Class"); 107 | } 108 | 109 | // MyMath.sum 110 | // 1,2,3 => 6 111 | @Test 112 | public void sum_with3numbers() { 113 | System.out.println("Test1"); 114 | assertEquals(6, myMath.sum(new int[] { 1, 2, 3 })); 115 | } 116 | 117 | @Test 118 | public void sum_with1number() { 119 | System.out.println("Test2"); 120 | assertEquals(3, myMath.sum(new int[] { 3 })); 121 | } 122 | } 123 | ``` 124 | --- 125 | -------------------------------------------------------------------------------- /03.JUnit-Introduction-In-5-Steps/src/com/in28minutes/junit/MyMath.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.junit; 2 | 3 | public class MyMath { 4 | int sum(int[] numbers) { 5 | int sum = 0; 6 | for (int i : numbers) { 7 | sum += i; 8 | } 9 | return sum; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /03.JUnit-Introduction-In-5-Steps/step22.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/03.JUnit-Introduction-In-5-Steps/step22.zip -------------------------------------------------------------------------------- /03.JUnit-Introduction-In-5-Steps/step25.md: -------------------------------------------------------------------------------- 1 | 2 | ## Complete Code Example 3 | 4 | 5 | ### /in28Minutes/git/getting-started-in-5-steps/junit-in-5-steps/src/com/in28minutes/junit/MyMath.java 6 | 7 | ```java 8 | package com.in28minutes.junit; 9 | 10 | public class MyMath { 11 | int sum(int[] numbers) { 12 | int sum = 0; 13 | for (int i : numbers) { 14 | sum += i; 15 | } 16 | return sum; 17 | } 18 | } 19 | ``` 20 | --- 21 | 22 | ### /in28Minutes/git/getting-started-in-5-steps/junit-in-5-steps/test/com/in28minutes/junit/AssertTest.java 23 | 24 | ```java 25 | package com.in28minutes.junit; 26 | 27 | import static org.junit.Assert.assertEquals; 28 | import static org.junit.Assert.assertTrue; 29 | 30 | import org.junit.Test; 31 | 32 | public class AssertTest { 33 | 34 | @Test 35 | public void test() { 36 | boolean condn = true; 37 | assertEquals(true, condn); 38 | assertTrue(condn); 39 | // assertFalse(condn); 40 | } 41 | 42 | } 43 | ``` 44 | --- 45 | 46 | ### /in28Minutes/git/getting-started-in-5-steps/junit-in-5-steps/test/com/in28minutes/junit/MyMathTest.java 47 | 48 | ```java 49 | package com.in28minutes.junit; 50 | 51 | import static org.junit.Assert.assertEquals; 52 | 53 | import org.junit.After; 54 | import org.junit.AfterClass; 55 | import org.junit.Before; 56 | import org.junit.BeforeClass; 57 | import org.junit.Test; 58 | 59 | public class MyMathTest { 60 | MyMath myMath = new MyMath(); 61 | 62 | @Before 63 | public void before() { 64 | System.out.println("Before"); 65 | } 66 | 67 | @After 68 | public void after() { 69 | System.out.println("After"); 70 | } 71 | 72 | @BeforeClass 73 | public static void beforeClass() { 74 | System.out.println("Before Class"); 75 | } 76 | 77 | @AfterClass 78 | public static void afterClass() { 79 | System.out.println("After Class"); 80 | } 81 | 82 | // MyMath.sum 83 | // 1,2,3 => 6 84 | @Test 85 | public void sum_with3numbers() { 86 | System.out.println("Test1"); 87 | assertEquals(6, myMath.sum(new int[] { 1, 2, 3 })); 88 | } 89 | 90 | @Test 91 | public void sum_with1number() { 92 | System.out.println("Test2"); 93 | assertEquals(3, myMath.sum(new int[] { 3 })); 94 | } 95 | } 96 | ``` 97 | --- 98 | -------------------------------------------------------------------------------- /03.JUnit-Introduction-In-5-Steps/step25.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/03.JUnit-Introduction-In-5-Steps/step25.zip -------------------------------------------------------------------------------- /03.JUnit-Introduction-In-5-Steps/test/com/in28minutes/junit/AssertTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.junit; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | import static org.junit.Assert.assertTrue; 5 | 6 | import org.junit.Test; 7 | 8 | public class AssertTest { 9 | 10 | @Test 11 | public void test() { 12 | boolean condn = true; 13 | assertEquals(true, condn); 14 | assertTrue(condn); 15 | // assertFalse(condn); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /03.JUnit-Introduction-In-5-Steps/test/com/in28minutes/junit/MyMathTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.junit; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.After; 6 | import org.junit.AfterClass; 7 | import org.junit.Before; 8 | import org.junit.BeforeClass; 9 | import org.junit.Test; 10 | 11 | public class MyMathTest { 12 | MyMath myMath = new MyMath(); 13 | 14 | @Before 15 | public void before() { 16 | System.out.println("Before"); 17 | } 18 | 19 | @After 20 | public void after() { 21 | System.out.println("After"); 22 | } 23 | 24 | @BeforeClass 25 | public static void beforeClass() { 26 | System.out.println("Before Class"); 27 | } 28 | 29 | @AfterClass 30 | public static void afterClass() { 31 | System.out.println("After Class"); 32 | } 33 | 34 | // MyMath.sum 35 | // 1,2,3 => 6 36 | @Test 37 | public void sum_with3numbers() { 38 | System.out.println("Test1"); 39 | assertEquals(6, myMath.sum(new int[] { 1, 2, 3 })); 40 | } 41 | 42 | @Test 43 | public void sum_with1number() { 44 | System.out.println("Test2"); 45 | assertEquals(3, myMath.sum(new int[] { 3 })); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps-V2/HELP.md: -------------------------------------------------------------------------------- 1 | # Read Me First 2 | The following was discovered as part of building this project: 3 | 4 | * The original package name 'com.in28minutes.mockito.mockito-demo' is invalid and this project uses 'com.in28minutes.mockito.mockitodemo' instead. 5 | 6 | # Getting Started 7 | 8 | ### Reference Documentation 9 | For further reference, please consider the following sections: 10 | 11 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html) 12 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/3.0.0-M3/maven-plugin/reference/html/) 13 | * [Create an OCI image](https://docs.spring.io/spring-boot/docs/3.0.0-M3/maven-plugin/reference/html/#build-image) 14 | 15 | -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps-V2/Step5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/04.Mockito-Introduction-In-5-Steps-V2/Step5.zip -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps-V2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 3.3.4 9 | 10 | 11 | com.in28minutes.mockito 12 | mockito-demo 13 | 0.0.1-SNAPSHOT 14 | mockito-demo 15 | Demo project for Spring Boot 16 | 17 | 21 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-test 28 | test 29 | 30 | 31 | 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-maven-plugin 37 | 38 | 39 | 40 | 41 | 42 | spring-milestones 43 | Spring Milestones 44 | https://repo.spring.io/milestone 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | spring-milestones 53 | Spring Milestones 54 | https://repo.spring.io/milestone 55 | 56 | false 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps-V2/src/main/java/com/in28minutes/mockito/mockitodemo/MockitoDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.mockito.mockitodemo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class MockitoDemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(MockitoDemoApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps-V2/src/main/java/com/in28minutes/mockito/mockitodemo/business/SomeBusinessImpl.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.mockito.mockitodemo.business; 2 | 3 | public class SomeBusinessImpl { 4 | 5 | private DataService dataService; 6 | 7 | public SomeBusinessImpl(DataService dataService) { 8 | super(); 9 | this.dataService = dataService; 10 | } 11 | 12 | public int findTheGreatestFromAllData() { 13 | int[] data = dataService.retrieveAllData(); 14 | int greatestValue = Integer.MIN_VALUE; 15 | for(int value:data) { 16 | if(value > greatestValue) 17 | greatestValue = value; 18 | } 19 | return greatestValue; 20 | } 21 | 22 | } 23 | 24 | interface DataService { 25 | int[] retrieveAllData(); 26 | } -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps-V2/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps-V2/src/test/java/com/in28minutes/mockito/mockitodemo/MockitoDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.mockito.mockitodemo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class MockitoDemoApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps-V2/src/test/java/com/in28minutes/mockito/mockitodemo/business/SomeBusinessImplMockTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.mockito.mockitodemo.business; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.mockito.Mockito.when; 5 | 6 | import org.junit.jupiter.api.Test; 7 | import org.junit.jupiter.api.extension.ExtendWith; 8 | import org.mockito.InjectMocks; 9 | import org.mockito.Mock; 10 | import org.mockito.junit.jupiter.MockitoExtension; 11 | 12 | @ExtendWith(MockitoExtension.class) 13 | class SomeBusinessImplMockTest { 14 | 15 | @Mock 16 | private DataService dataServiceMock; 17 | 18 | @InjectMocks 19 | private SomeBusinessImpl businessImpl; 20 | 21 | @Test 22 | void findTheGreatestFromAllData_basicScenario() { 23 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[]{25, 15, 5}); 24 | assertEquals(25, businessImpl.findTheGreatestFromAllData()); 25 | } 26 | 27 | @Test 28 | void findTheGreatestFromAllData_OneValue() { 29 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[]{35}); 30 | assertEquals(35, businessImpl.findTheGreatestFromAllData()); 31 | } 32 | 33 | @Test 34 | void findTheGreatestFromAllData_EmptyArray() { 35 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[]{}); 36 | assertEquals(Integer.MIN_VALUE, businessImpl.findTheGreatestFromAllData()); 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps-V2/src/test/java/com/in28minutes/mockito/mockitodemo/business/SomeBusinessImplStubTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.mockito.mockitodemo.business; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | class SomeBusinessImplStubTest { 8 | 9 | @Test 10 | void findTheGreatestFromAllData_basicScenario() { 11 | DataService dataServiceStub = new DataServiceStub1(); 12 | SomeBusinessImpl businessImpl = new SomeBusinessImpl(dataServiceStub); 13 | int result = businessImpl.findTheGreatestFromAllData(); 14 | assertEquals(25, result); 15 | } 16 | 17 | @Test 18 | void findTheGreatestFromAllData_withOneValue() { 19 | DataService dataServiceStub = new DataServiceStub2(); 20 | SomeBusinessImpl businessImpl = new SomeBusinessImpl(dataServiceStub); 21 | int result = businessImpl.findTheGreatestFromAllData(); 22 | assertEquals(35, result); 23 | } 24 | 25 | } 26 | 27 | class DataServiceStub1 implements DataService { 28 | 29 | @Override 30 | public int[] retrieveAllData() { 31 | return new int[]{25, 15, 5}; 32 | } 33 | 34 | } 35 | 36 | 37 | class DataServiceStub2 implements DataService { 38 | 39 | @Override 40 | public int[] retrieveAllData() { 41 | return new int[]{35}; 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps-V2/src/test/java/com/in28minutes/mockito/mockitodemo/list/ListTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.mockito.mockitodemo.list; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.mockito.Mockito.mock; 5 | import static org.mockito.Mockito.when; 6 | 7 | import java.util.List; 8 | 9 | import org.junit.jupiter.api.Test; 10 | import org.mockito.Mockito; 11 | 12 | public class ListTest { 13 | 14 | @Test 15 | void simpleTest() { 16 | List listMock = mock(List.class); 17 | //listMock.size() => 3 18 | when(listMock.size()).thenReturn(3); 19 | assertEquals(3, listMock.size()); 20 | assertEquals(3, listMock.size()); 21 | assertEquals(3, listMock.size()); 22 | assertEquals(3, listMock.size()); 23 | } 24 | 25 | @Test 26 | void multipleReturns() { 27 | List listMock = mock(List.class); 28 | //listMock.size() => 3 29 | when(listMock.size()).thenReturn(1).thenReturn(2); 30 | assertEquals(1, listMock.size()); 31 | assertEquals(2, listMock.size()); 32 | assertEquals(2, listMock.size()); 33 | assertEquals(2, listMock.size()); 34 | } 35 | 36 | @Test 37 | void specificParameters() { 38 | List listMock = mock(List.class); 39 | //listMock.size() => 3 40 | when(listMock.get(0)).thenReturn("SomeString"); 41 | assertEquals("SomeString", listMock.get(0)); 42 | assertEquals(null, listMock.get(1)); 43 | } 44 | 45 | @Test 46 | void genericParameters() { 47 | List listMock = mock(List.class); 48 | //listMock.size() => 3 49 | when(listMock.get(Mockito.anyInt())).thenReturn("SomeOtherString"); 50 | assertEquals("SomeOtherString", listMock.get(0)); 51 | assertEquals("SomeOtherString", listMock.get(1)); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/04.Mockito-Introduction-In-5-Steps/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip 2 | -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps/code-21July2017.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/04.Mockito-Introduction-In-5-Steps/code-21July2017.zip -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.in28minutes.mockito 7 | mockito-demo 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | mockito-demo 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.7.0 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 17 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-test 36 | test 37 | 38 | 39 | 40 | 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-maven-plugin 45 | 46 | 47 | 48 | 49 | 50 | 51 | spring-snapshots 52 | Spring Snapshots 53 | https://repo.spring.io/snapshot 54 | 55 | true 56 | 57 | 58 | 59 | spring-milestones 60 | Spring Milestones 61 | https://repo.spring.io/milestone 62 | 63 | false 64 | 65 | 66 | 67 | 68 | 69 | 70 | spring-snapshots 71 | Spring Snapshots 72 | https://repo.spring.io/snapshot 73 | 74 | true 75 | 76 | 77 | 78 | spring-milestones 79 | Spring Milestones 80 | https://repo.spring.io/milestone 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps/src/main/java/com/in28minutes/mockito/mockitodemo/DataService.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.mockito.mockitodemo; 2 | 3 | public interface DataService { 4 | int[] retrieveAllData(); 5 | } -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps/src/main/java/com/in28minutes/mockito/mockitodemo/MockitoDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.mockito.mockitodemo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class MockitoDemoApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(MockitoDemoApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps/src/main/java/com/in28minutes/mockito/mockitodemo/SomeBusinessImpl.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.mockito.mockitodemo; 2 | 3 | public class SomeBusinessImpl { 4 | private DataService dataService; 5 | 6 | public SomeBusinessImpl(DataService dataService) { 7 | super(); 8 | this.dataService = dataService; 9 | } 10 | 11 | int findTheGreatestFromAllData() { 12 | int[] data = dataService.retrieveAllData(); 13 | int greatest = Integer.MIN_VALUE; 14 | 15 | for (int value : data) { 16 | if (value > greatest) { 17 | greatest = value; 18 | } 19 | } 20 | return greatest; 21 | } 22 | } -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps/src/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/04.Mockito-Introduction-In-5-Steps/src/main/resources/application.properties -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps/src/test/java/com/in28minutes/mockito/mockitodemo/ListTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.mockito.mockitodemo; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertNull; 5 | import static org.mockito.Mockito.mock; 6 | import static org.mockito.Mockito.when; 7 | 8 | import java.util.List; 9 | 10 | import org.junit.jupiter.api.Test; 11 | import org.mockito.Mockito; 12 | 13 | public class ListTest { 14 | 15 | @Test 16 | public void testSize() { 17 | List listMock = mock(List.class); 18 | when(listMock.size()).thenReturn(10); 19 | assertEquals(10, listMock.size()); 20 | assertEquals(10, listMock.size()); 21 | } 22 | 23 | @Test 24 | public void testSize_multipleReturns() { 25 | List listMock = mock(List.class); 26 | when(listMock.size()).thenReturn(10).thenReturn(20); 27 | assertEquals(10, listMock.size()); 28 | assertEquals(20, listMock.size()); 29 | assertEquals(20, listMock.size()); 30 | } 31 | 32 | @Test 33 | public void testGet_SpecificParameter() { 34 | List listMock = mock(List.class); 35 | when(listMock.get(0)).thenReturn("SomeString"); 36 | assertEquals("SomeString", listMock.get(0)); 37 | assertNull(listMock.get(1)); 38 | } 39 | 40 | @Test 41 | public void testGet_GenericParameter() { 42 | List listMock = mock(List.class); 43 | when(listMock.get(Mockito.anyInt())).thenReturn("SomeString"); 44 | assertEquals("SomeString", listMock.get(0)); 45 | assertEquals("SomeString", listMock.get(1)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps/src/test/java/com/in28minutes/mockito/mockitodemo/MockitoDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.mockito.mockitodemo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.junit.jupiter.api.extension.ExtendWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit.jupiter.SpringExtension; 7 | 8 | // replaced @RunWith with @ExtendWith 9 | // replaced SpringRunner.class with SpringExtension.class 10 | @ExtendWith(SpringExtension.class) 11 | @SpringBootTest 12 | public class MockitoDemoApplicationTests { 13 | 14 | @Test 15 | public void contextLoads() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps/src/test/java/com/in28minutes/mockito/mockitodemo/SomeBusinessMockAnnotationsTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.mockito.mockitodemo; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.mockito.Mockito.when; 5 | 6 | import org.junit.jupiter.api.Test; 7 | import org.junit.jupiter.api.extension.ExtendWith; 8 | import org.mockito.InjectMocks; 9 | import org.mockito.Mock; 10 | import org.mockito.junit.jupiter.MockitoExtension; 11 | 12 | // replaced @RunWith with @ExtendWith 13 | // replaced MockitoJUnitRunner.class with MockitoExtension.class 14 | @ExtendWith(MockitoExtension.class) 15 | public class SomeBusinessMockAnnotationsTest { 16 | 17 | @Mock 18 | DataService dataServiceMock; 19 | 20 | @InjectMocks 21 | SomeBusinessImpl businessImpl; 22 | 23 | @Test 24 | public void testFindTheGreatestFromAllData() { 25 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 24, 15, 3 }); 26 | assertEquals(24, businessImpl.findTheGreatestFromAllData()); 27 | } 28 | 29 | @Test 30 | public void testFindTheGreatestFromAllData_ForOneValue() { 31 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 15 }); 32 | assertEquals(15, businessImpl.findTheGreatestFromAllData()); 33 | } 34 | 35 | @Test 36 | public void testFindTheGreatestFromAllData_NoValues() { 37 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] {}); 38 | assertEquals(Integer.MIN_VALUE, businessImpl.findTheGreatestFromAllData()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps/src/test/java/com/in28minutes/mockito/mockitodemo/SomeBusinessMockTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.mockito.mockitodemo; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.mockito.Mockito.mock; 5 | import static org.mockito.Mockito.when; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class SomeBusinessMockTest { 10 | 11 | @Test 12 | public void testFindTheGreatestFromAllData() { 13 | DataService dataServiceMock = mock(DataService.class); 14 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 24, 15, 3 }); 15 | SomeBusinessImpl businessImpl = new SomeBusinessImpl(dataServiceMock); 16 | int result = businessImpl.findTheGreatestFromAllData(); 17 | assertEquals(24, result); 18 | } 19 | 20 | @Test 21 | public void testFindTheGreatestFromAllData_ForOneValue() { 22 | DataService dataServiceMock = mock(DataService.class); 23 | when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 15 }); 24 | SomeBusinessImpl businessImpl = new SomeBusinessImpl(dataServiceMock); 25 | int result = businessImpl.findTheGreatestFromAllData(); 26 | assertEquals(15, result); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /04.Mockito-Introduction-In-5-Steps/src/test/java/com/in28minutes/mockito/mockitodemo/SomeBusinessStubTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.mockito.mockitodemo; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class SomeBusinessStubTest { 8 | @Test 9 | public void testFindTheGreatestFromAllData() { 10 | SomeBusinessImpl businessImpl = new SomeBusinessImpl(new DataServiceStub()); 11 | int result = businessImpl.findTheGreatestFromAllData(); 12 | assertEquals(24, result); 13 | 14 | } 15 | 16 | } 17 | 18 | class DataServiceStub implements DataService { 19 | @Override 20 | public int[] retrieveAllData() { 21 | return new int[] { 24, 6, 15 }; 22 | } 23 | } -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/Step01.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | ## Complete Code Example 6 | 7 | 8 | ### /pom.xml 9 | 10 | ```xml 11 | 12 | 14 | 4.0.0 15 | 16 | org.springframework.boot 17 | spring-boot-starter-parent 18 | 3.3.4 19 | 20 | 21 | com.in28minutes.springboot 22 | first-rest-api 23 | 0.0.1-SNAPSHOT 24 | first-rest-api 25 | Demo project for Spring Boot 26 | 27 | 21 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-web 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-devtools 38 | runtime 39 | true 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-test 44 | test 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-maven-plugin 53 | 54 | 55 | 56 | 57 | 58 | spring-milestones 59 | Spring Milestones 60 | https://repo.spring.io/milestone 61 | 62 | false 63 | 64 | 65 | 66 | 67 | 68 | spring-milestones 69 | Spring Milestones 70 | https://repo.spring.io/milestone 71 | 72 | false 73 | 74 | 75 | 76 | 77 | 78 | ``` 79 | --- 80 | 81 | ### /src/main/java/com/in28minutes/springboot/firstrestapi/FirstRestApiApplication.java 82 | 83 | ```java 84 | package com.in28minutes.springboot.firstrestapi; 85 | 86 | import org.springframework.boot.SpringApplication; 87 | import org.springframework.boot.autoconfigure.SpringBootApplication; 88 | 89 | @SpringBootApplication 90 | public class FirstRestApiApplication { 91 | 92 | public static void main(String[] args) { 93 | SpringApplication.run(FirstRestApiApplication.class, args); 94 | } 95 | 96 | } 97 | ``` 98 | --- 99 | 100 | ### /src/main/resources/application.properties 101 | 102 | ```properties 103 | 104 | ``` 105 | --- 106 | 107 | ### /src/test/java/com/in28minutes/springboot/firstrestapi/FirstRestApiApplicationTests.java 108 | 109 | ```java 110 | package com.in28minutes.springboot.firstrestapi; 111 | 112 | import org.junit.jupiter.api.Test; 113 | import org.springframework.boot.test.context.SpringBootTest; 114 | 115 | @SpringBootTest 116 | class FirstRestApiApplicationTests { 117 | 118 | @Test 119 | void contextLoads() { 120 | } 121 | 122 | } 123 | ``` 124 | --- 125 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/Step01.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced-V2/Step01.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/Step05.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced-V2/Step05.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/Step06.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced-V2/Step06.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/Step07.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced-V2/Step07.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/Step14.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced-V2/Step14.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/Step19.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced-V2/Step19.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/Step23.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced-V2/Step23.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 3.3.4 9 | 10 | 11 | com.in28minutes.springboot 12 | first-rest-api 13 | 0.0.1-SNAPSHOT 14 | first-rest-api 15 | Demo project for Spring Boot 16 | 17 | 21 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-security 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-data-jpa 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-data-rest 38 | 39 | 40 | 41 | com.h2database 42 | h2 43 | runtime 44 | 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-devtools 50 | runtime 51 | true 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-starter-test 57 | test 58 | 59 | 60 | 61 | 62 | 63 | 64 | org.springframework.boot 65 | spring-boot-maven-plugin 66 | 67 | 68 | 69 | 70 | 71 | spring-milestones 72 | Spring Milestones 73 | https://repo.spring.io/milestone 74 | 75 | false 76 | 77 | 78 | 79 | 80 | 81 | spring-milestones 82 | Spring Milestones 83 | https://repo.spring.io/milestone 84 | 85 | false 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/main/java/com/in28minutes/springboot/firstrestapi/FirstRestApiApplication.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.firstrestapi; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class FirstRestApiApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(FirstRestApiApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/main/java/com/in28minutes/springboot/firstrestapi/helloworld/HelloWorldBean.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.firstrestapi.helloworld; 2 | 3 | public class HelloWorldBean { 4 | 5 | public HelloWorldBean(String message) { 6 | super(); 7 | this.message = message; 8 | } 9 | 10 | private String message; 11 | 12 | public String getMessage() { 13 | return message; 14 | } 15 | 16 | @Override 17 | public String toString() { 18 | return "HelloWorldBean [message=" + message + "]"; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/main/java/com/in28minutes/springboot/firstrestapi/helloworld/HelloWorldResource.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.firstrestapi.helloworld; 2 | 3 | import org.springframework.web.bind.annotation.PathVariable; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.ResponseBody; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | //@Controller 9 | @RestController 10 | public class HelloWorldResource { 11 | // /hello-world => "Hello World" 12 | 13 | @RequestMapping("/hello-world") 14 | public String helloWorld() { 15 | return "Hello World"; 16 | } 17 | 18 | 19 | @RequestMapping("/hello-world-bean") 20 | public HelloWorldBean helloWorldBean() { 21 | return new HelloWorldBean("Hello World"); 22 | } 23 | 24 | //Path Variable or Path Params 25 | // /user/Ranga/todos/1 26 | 27 | @RequestMapping("/hello-world-path-param/{name}") 28 | public HelloWorldBean helloWorldPathParam(@PathVariable String name) { 29 | return new HelloWorldBean("Hello World, " + name); 30 | } 31 | 32 | @RequestMapping("/hello-world-path-param/{name}/message/{message}") 33 | public HelloWorldBean helloWorldMultiplePathParam 34 | (@PathVariable String name, 35 | @PathVariable String message) { 36 | return new HelloWorldBean("Hello World " + name + "," + message); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/main/java/com/in28minutes/springboot/firstrestapi/security/SpringSecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.firstrestapi.security; 2 | 3 | import static org.springframework.security.config.Customizer.withDefaults; 4 | 5 | import java.util.function.Function; 6 | 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10 | import org.springframework.security.core.userdetails.User; 11 | import org.springframework.security.core.userdetails.UserDetails; 12 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 13 | import org.springframework.security.crypto.password.PasswordEncoder; 14 | import org.springframework.security.provisioning.InMemoryUserDetailsManager; 15 | import org.springframework.security.web.SecurityFilterChain; 16 | 17 | @Configuration 18 | public class SpringSecurityConfiguration { 19 | //LDAP or Database 20 | //In Memory 21 | 22 | //InMemoryUserDetailsManager 23 | //InMemoryUserDetailsManager(UserDetails... users) 24 | 25 | @Bean 26 | public InMemoryUserDetailsManager createUserDetailsManager() { 27 | 28 | UserDetails userDetails1 = createNewUser("admin", "password"); 29 | UserDetails userDetails2 = createNewUser("ranga", "dummydummy"); 30 | 31 | return new InMemoryUserDetailsManager(userDetails1, userDetails2); 32 | } 33 | 34 | private UserDetails createNewUser(String username, String password) { 35 | Function passwordEncoder 36 | = input -> passwordEncoder().encode(input); 37 | 38 | UserDetails userDetails = User.builder() 39 | .passwordEncoder(passwordEncoder) 40 | .username(username) 41 | .password(password) 42 | .roles("USER","ADMIN") 43 | .build(); 44 | return userDetails; 45 | } 46 | 47 | @Bean 48 | public PasswordEncoder passwordEncoder() { 49 | return new BCryptPasswordEncoder(); 50 | } 51 | 52 | //All URLs are protected 53 | //A login form is shown for unauthorized requests 54 | //CSRF disable 55 | //Frames 56 | 57 | // dothis 58 | // dothis 59 | // executeRequest 60 | 61 | @Bean 62 | public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { 63 | 64 | http.authorizeHttpRequests( 65 | auth -> auth.anyRequest().authenticated()); 66 | 67 | http.httpBasic(withDefaults()); 68 | 69 | http.csrf(csrf -> csrf.disable()); //POST or PUT 70 | 71 | http.headers(headers -> headers.frameOptions(frameOptionsConfig-> frameOptionsConfig.disable())); 72 | 73 | return http.build(); 74 | } 75 | } -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/main/java/com/in28minutes/springboot/firstrestapi/survey/Question.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.firstrestapi.survey; 2 | 3 | import java.util.List; 4 | 5 | public class Question { 6 | 7 | public Question() { 8 | 9 | } 10 | 11 | public Question(String id, String description, List options, String correctAnswer) { 12 | super(); 13 | this.id = id; 14 | this.description = description; 15 | this.options = options; 16 | this.correctAnswer = correctAnswer; 17 | } 18 | 19 | private String id; 20 | private String description; 21 | private List options; 22 | private String correctAnswer; 23 | 24 | public String getId() { 25 | return id; 26 | } 27 | 28 | public void setId(String id) { 29 | this.id = id; 30 | } 31 | 32 | 33 | public String getDescription() { 34 | return description; 35 | } 36 | 37 | public List getOptions() { 38 | return options; 39 | } 40 | 41 | public String getCorrectAnswer() { 42 | return correctAnswer; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "Question [id=" + id + ", description=" + description + ", options=" + options + ", correctAnswer=" 48 | + correctAnswer + "]"; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/main/java/com/in28minutes/springboot/firstrestapi/survey/Survey.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.firstrestapi.survey; 2 | 3 | import java.util.List; 4 | 5 | public class Survey { 6 | 7 | public Survey() { 8 | 9 | } 10 | 11 | public Survey(String id, String title, String description, List questions) { 12 | super(); 13 | this.id = id; 14 | this.title = title; 15 | this.description = description; 16 | this.questions = questions; 17 | } 18 | 19 | private String id; 20 | private String title; 21 | private String description; 22 | private List questions; 23 | 24 | public String getId() { 25 | return id; 26 | } 27 | 28 | public String getTitle() { 29 | return title; 30 | } 31 | 32 | public String getDescription() { 33 | return description; 34 | } 35 | 36 | public List getQuestions() { 37 | return questions; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return "Survey [id=" + id + ", title=" + title + ", description=" + description + ", questions=" + questions 43 | + "]"; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/main/java/com/in28minutes/springboot/firstrestapi/survey/SurveyResource.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.firstrestapi.survey; 2 | 3 | import java.net.URI; 4 | import java.util.List; 5 | 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RequestMethod; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import org.springframework.web.server.ResponseStatusException; 14 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder; 15 | 16 | @RestController 17 | public class SurveyResource { 18 | 19 | private SurveyService surveyService; 20 | 21 | public SurveyResource(SurveyService surveyService) { 22 | super(); 23 | this.surveyService = surveyService; 24 | } 25 | 26 | // /surveys => surveys 27 | @RequestMapping("/surveys") 28 | public List retrieveAllSurveys(){ 29 | return surveyService.retrieveAllSurveys(); 30 | } 31 | 32 | @RequestMapping("/surveys/{surveyId}") 33 | public Survey retrieveSurveyById(@PathVariable String surveyId){ 34 | Survey survey = surveyService.retrieveSurveyById(surveyId); 35 | 36 | if(survey==null) 37 | throw new ResponseStatusException(HttpStatus.NOT_FOUND); 38 | 39 | return survey; 40 | } 41 | 42 | @RequestMapping("/surveys/{surveyId}/questions") 43 | public List retrieveAllSurveyQuestions(@PathVariable String surveyId){ 44 | List questions = surveyService.retrieveAllSurveyQuestions(surveyId); 45 | 46 | if(questions==null) 47 | throw new ResponseStatusException(HttpStatus.NOT_FOUND); 48 | 49 | return questions; 50 | } 51 | 52 | @RequestMapping("/surveys/{surveyId}/questions/{questionId}") 53 | public Question retrieveSpecificSurveyQuestion(@PathVariable String surveyId, 54 | @PathVariable String questionId){ 55 | Question question = surveyService.retrieveSpecificSurveyQuestion 56 | (surveyId, questionId); 57 | 58 | if(question==null) 59 | throw new ResponseStatusException(HttpStatus.NOT_FOUND); 60 | 61 | return question; 62 | } 63 | 64 | @RequestMapping(value="/surveys/{surveyId}/questions", method = RequestMethod.POST) 65 | public ResponseEntity addNewSurveyQuestion(@PathVariable String surveyId, 66 | @RequestBody Question question){ 67 | 68 | String questionId = surveyService.addNewSurveyQuestion(surveyId, question); 69 | // /surveys/{surveyId}/questions/{questionId} 70 | URI location = ServletUriComponentsBuilder.fromCurrentRequest() 71 | .path("/{questionId}").buildAndExpand(questionId).toUri(); 72 | return ResponseEntity.created(location ).build(); 73 | 74 | } 75 | 76 | @RequestMapping(value="/surveys/{surveyId}/questions/{questionId}", method = RequestMethod.DELETE) 77 | public ResponseEntity deleteSurveyQuestion(@PathVariable String surveyId, 78 | @PathVariable String questionId){ 79 | surveyService.deleteSurveyQuestion(surveyId, questionId); 80 | return ResponseEntity.noContent().build(); 81 | } 82 | 83 | @RequestMapping(value="/surveys/{surveyId}/questions/{questionId}", method = RequestMethod.PUT) 84 | public ResponseEntity updateSurveyQuestion(@PathVariable String surveyId, 85 | @PathVariable String questionId, 86 | @RequestBody Question question){ 87 | 88 | surveyService.updateSurveyQuestion(surveyId, questionId, question); 89 | 90 | return ResponseEntity.noContent().build(); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/main/java/com/in28minutes/springboot/firstrestapi/survey/SurveyService.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.firstrestapi.survey; 2 | 3 | import java.math.BigInteger; 4 | import java.security.SecureRandom; 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | import java.util.Optional; 9 | import java.util.function.Predicate; 10 | 11 | import org.springframework.stereotype.Service; 12 | 13 | @Service 14 | public class SurveyService { 15 | 16 | private static final List surveys = new ArrayList<>(); 17 | 18 | static { 19 | 20 | var question1 = new Question("Question1", "Most Popular Cloud Platform Today", 21 | List.of("AWS", "Azure", "Google Cloud", "Oracle Cloud"), "AWS"); 22 | var question2 = new Question("Question2", "Fastest Growing Cloud Platform", 23 | List.of("AWS", "Azure", "Google Cloud", "Oracle Cloud"), "Google Cloud"); 24 | var question3 = new Question("Question3", "Most Popular DevOps Tool", 25 | List.of("Kubernetes", "Docker", "Terraform", "Azure DevOps"), "Kubernetes"); 26 | 27 | List questions = new ArrayList<>(List.of(question1, question2, question3)); 28 | 29 | var survey = new Survey("Survey1", "My Favorite Survey", "Description of the Survey", questions); 30 | 31 | surveys.add(survey); 32 | 33 | } 34 | 35 | public List retrieveAllSurveys() { 36 | return surveys; 37 | } 38 | 39 | public Survey retrieveSurveyById(String surveyId) { 40 | 41 | Predicate predicate = survey -> survey.getId().equalsIgnoreCase(surveyId); 42 | 43 | Optional optionalSurvey = surveys.stream().filter(predicate).findFirst(); 44 | 45 | return optionalSurvey.orElse(null); 46 | 47 | } 48 | 49 | public List retrieveAllSurveyQuestions(String surveyId) { 50 | Survey survey = retrieveSurveyById(surveyId); 51 | 52 | if (survey == null) 53 | return null; 54 | 55 | return survey.getQuestions(); 56 | } 57 | 58 | public Question retrieveSpecificSurveyQuestion(String surveyId, String questionId) { 59 | 60 | List surveyQuestions = retrieveAllSurveyQuestions(surveyId); 61 | 62 | if (surveyQuestions == null) 63 | return null; 64 | 65 | Optional optionalQuestion = surveyQuestions.stream() 66 | .filter(q -> q.getId().equalsIgnoreCase(questionId)).findFirst(); 67 | 68 | return optionalQuestion.orElse(null); 69 | 70 | } 71 | 72 | public String addNewSurveyQuestion(String surveyId, Question question) { 73 | List questions = retrieveAllSurveyQuestions(surveyId); 74 | question.setId(generateRandomId()); 75 | questions.add(question); 76 | return question.getId(); 77 | } 78 | 79 | private String generateRandomId() { 80 | SecureRandom secureRandom = new SecureRandom(); 81 | String randomId = new BigInteger(32, secureRandom).toString(); 82 | return randomId; 83 | } 84 | 85 | public String deleteSurveyQuestion(String surveyId, String questionId) { 86 | 87 | List surveyQuestions = retrieveAllSurveyQuestions(surveyId); 88 | 89 | if (surveyQuestions == null) 90 | return null; 91 | 92 | 93 | Predicate predicate = q -> q.getId().equalsIgnoreCase(questionId); 94 | boolean removed = surveyQuestions.removeIf(predicate); 95 | 96 | if(!removed) return null; 97 | 98 | return questionId; 99 | } 100 | 101 | public void updateSurveyQuestion(String surveyId, String questionId, Question question) { 102 | List questions = retrieveAllSurveyQuestions(surveyId); 103 | questions.removeIf(q -> q.getId().equalsIgnoreCase(questionId)); 104 | questions.add(question); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/main/java/com/in28minutes/springboot/firstrestapi/user/UserDetails.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.firstrestapi.user; 2 | 3 | import jakarta.persistence.Entity; 4 | import jakarta.persistence.GeneratedValue; 5 | import jakarta.persistence.Id; 6 | 7 | @Entity 8 | public class UserDetails { 9 | 10 | @Id 11 | @GeneratedValue 12 | private Long id; 13 | 14 | private String name; 15 | private String role; 16 | 17 | public UserDetails() { 18 | 19 | } 20 | 21 | public UserDetails(String name, String role) { 22 | super(); 23 | this.name = name; 24 | this.role = role; 25 | } 26 | 27 | public Long getId() { 28 | return id; 29 | } 30 | 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | public String getRole() { 36 | return role; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "UserDetails [id=" + id + ", name=" + name + ", role=" + role + "]"; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/main/java/com/in28minutes/springboot/firstrestapi/user/UserDetailsCommandLineRunner.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.firstrestapi.user; 2 | 3 | import java.util.List; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.boot.CommandLineRunner; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Component 11 | public class UserDetailsCommandLineRunner implements CommandLineRunner { 12 | 13 | private final Logger logger = LoggerFactory.getLogger(getClass()); 14 | 15 | private final UserDetailsRepository repository; 16 | 17 | public UserDetailsCommandLineRunner(UserDetailsRepository repository) { 18 | super(); 19 | this.repository = repository; 20 | } 21 | 22 | @Override 23 | public void run(String... args) throws Exception { 24 | repository.save(new UserDetails("Ranga", "Admin")); 25 | repository.save(new UserDetails("Ravi", "Admin")); 26 | repository.save(new UserDetails("John", "User")); 27 | 28 | //List users = repository.findAll(); 29 | 30 | List users = repository.findByRole("Admin"); 31 | 32 | users.forEach(user -> logger.info(user.toString())); 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/main/java/com/in28minutes/springboot/firstrestapi/user/UserDetailsRepository.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.firstrestapi.user; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | public interface UserDetailsRepository extends JpaRepository{ 8 | List findByRole(String role); 9 | } 10 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/main/java/com/in28minutes/springboot/firstrestapi/user/UserDetailsRestRepository.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.firstrestapi.user; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.repository.PagingAndSortingRepository; 6 | 7 | public interface UserDetailsRestRepository extends PagingAndSortingRepository{ 8 | List findByRole(String role); 9 | } 10 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | logging.level.org.springframework=info 2 | spring.datasource.url=jdbc:h2:mem:testdb 3 | spring.jpa.show-sql=true -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/test/java/com/in28minutes/springboot/firstrestapi/FirstRestApiApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.firstrestapi; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class FirstRestApiApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced-V2/src/test/java/com/in28minutes/springboot/firstrestapi/survey/JsonAssertTest.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.firstrestapi.survey; 2 | 3 | import org.json.JSONException; 4 | import org.junit.jupiter.api.Test; 5 | import org.skyscreamer.jsonassert.JSONAssert; 6 | 7 | class JsonAssertTest { 8 | 9 | @Test 10 | void jsonAssert_learningBasics() throws JSONException { 11 | 12 | String expectedResponse = 13 | """ 14 | { 15 | "id":"Question1", 16 | "description":"Most Popular Cloud Platform Today", 17 | "correctAnswer":"AWS" 18 | } 19 | """; 20 | 21 | String actualResponse = 22 | """ 23 | {"id":"Question1", 24 | "description":"Most Popular Cloud Platform Today", 25 | "options":["AWS","Azure","Google Cloud","Oracle "], 26 | "correctAnswer":"AWS"} 27 | """; 28 | 29 | JSONAssert.assertEquals(expectedResponse, actualResponse, false); 30 | 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step01.md: -------------------------------------------------------------------------------- 1 | ## What You Will Learn during this Step: 2 | - Set up an Maven Project with Eclipse. 3 | - Intellij Link : https://www.jetbrains.com/help/idea/2016.2/getting-started-with-maven.html#create_maven_project 4 | - Copy Two Files pom.xml and Application.java 5 | - Launch Your First Spring Boot Application. 6 | - You will be introduced to Maven 7 | - Dependency Management 8 | 9 | ## Cool thing to note! 10 | - Without a lot of configuration, we are up and running with a web application 11 | - Refer https://github.com/in28minutes/SpringMvcStepByStep/blob/master/Step15.md to understand the sort of stuff - web.xml, dispatcher servlet configuration, maven dependency management and plugins - that are need to launch a typical web application without Spring Boot! 12 | 13 | ## What You Will NOT Learn during this Step: 14 | - Spring Boot does a lot of magic. This magic is called Auto Configuration. We will discuss about different terms related to Spring Boot - Starter Parent, Starter projects, Auto configuration - in depth during our first 10 steps. 15 | - As far as this step is concerned, we will focus on getting up and running with Spring Boot. We will understand all the magic a little later. 16 | - We will copy a lot of code in this step - just to avoid typos 17 | 18 | ## Exercises 19 | - If you are comfortable with Spring, try to create a few dependencies and see if are automatically auto-wired! 20 | 21 | ## Files List 22 | ### pom.xml 23 | ``` 24 | 26 | 4.0.0 27 | com.in28minutes.springboot 28 | first-springboot-project 29 | 0.0.1-SNAPSHOT 30 | 31 | org.springframework.boot 32 | spring-boot-starter-parent 33 | 2.3.1.RELEASE 34 | 35 | 36 | 37 | 1.8 38 | 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-web 44 | 45 | 46 | 47 | 48 | 49 | 50 | org.springframework.boot 51 | spring-boot-maven-plugin 52 | 53 | 54 | 55 | 56 | ``` 57 | ### src/main/java/com/in28minutes/springboot/Application.java 58 | ``` 59 | package com.in28minutes.springboot; 60 | 61 | import org.springframework.boot.SpringApplication; 62 | import org.springframework.boot.autoconfigure.SpringBootApplication; 63 | import org.springframework.context.ApplicationContext; 64 | 65 | @SpringBootApplication 66 | public class Application { 67 | 68 | public static void main(String[] args) { 69 | ApplicationContext ctx = SpringApplication.run(Application.class, args); 70 | 71 | } 72 | 73 | } 74 | ``` 75 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step01.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step01.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step02.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step02.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step04.md: -------------------------------------------------------------------------------- 1 | ## What You Will Learn during this Step: 2 | - Understand Starter Parent 3 | - How to override things defined in Starter Parent 4 | - Other starter projects 5 | 6 | ## Starter Parent 7 | - Dependency Versions 8 | - Java Versions 9 | - Default Plugins 10 | 11 | ## Other Starter Projects 12 | - spring-boot-starter-web-services 13 | - spring-boot-starter-test 14 | - spring-boot-starter-jdbc 15 | - spring-boot-starter-security 16 | - spring-boot-starter-data-jpa 17 | - spring-boot-starter-data-rest 18 | - More at https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#using-boot-starter 19 | 20 | ## Useful Snippets and References 21 | First Snippet 22 | ``` 23 | 24 | org.springframework.boot 25 | spring-boot-starter-parent 26 | 2.3.1.RELEASE 27 | 28 | ``` 29 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step05.md: -------------------------------------------------------------------------------- 1 | ## What You Will Learn during this Step: 2 | - Spring Boot vs Spring 3 | - What Spring Boot is Not! 4 | 5 | ## Spring Boot vs Spring 6 | 7 | ### Spring 8 | - Spring is just a dependency injection framework. Spring focuses on the "plumbing" of enterprise applications so that teams can focus on application-level business logic, without unnecessary ties to specific deployment environments. 9 | - First half of the 2000 decade! EJBs 10 | - EJBs were NOT easy to develop. 11 | - Write a lot of xml and plumbing code to get EJBs running 12 | - Impossible to Unit Test 13 | - Alternative - Writing simple JDBC Code involved a lot of plumbing 14 | - Spring framework started with aim of making Java EE development simpler. 15 | - Goals 16 | - Make applications testable. i.e. easier to write unit tests 17 | - Reduce plumbing code of JDBC and JMS 18 | - Simple architecture. Minus EJB. 19 | - Integrates well with other popular frameworks. 20 | 21 | ### Applications with Spring Framework 22 | - Over the next few years, a number of applications were developed with Spring Framework 23 | - Testable but 24 | - Lot of configuration (XML and Java) 25 | - Developing Spring Based application need configuration of a lot of beans! 26 | - Integration with other frameworks need configuration as well! 27 | - In the last few years, focus is moving from monolith applications to microservices. We need to be able to start project quickly. Minimum or Zero start up time 28 | - Framework Setup 29 | - Deployment - Configurability 30 | - Logging, Transaction Management 31 | - Monitoring 32 | - Web Server Configuration 33 | 34 | ### Spring Boot 35 | - Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”. 36 | - We take an opinionated view of the Spring platform and third-party libraries so you can get started with minimum fuss. 37 | - Example Problem Statements 38 | - You want to add Hibernate to your project. You dont worry about configuring a data source and a session factory. I will do if for you! 39 | - Goals 40 | - Provide quick start for projects with Spring. 41 | - Be opinionated but provide options. 42 | - Provide a range of non-functional features that are common to large classes of projects (e.g. embedded servers, security, metrics, health checks, externalized configuration). 43 | 44 | #### What Spring Boot is NOT? 45 | - It’s not an app or a web server 46 | - Does not implement any specific framework - for example, JPA or JMS 47 | - Does not generate code 48 | 49 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step06.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step06.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step08.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step08.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step09.md: -------------------------------------------------------------------------------- 1 | ## What You Will Learn during this Step: 2 | - I hate the fact that I've to stop and start the server each time. Can somebody save me? 3 | - Yeah. Spring Boot Developer Tools 4 | - By default, any entry on the classpath that points to a folder will be monitored for changes. 5 | - These will not trigger restart - /META-INF/maven, /META-INF/resources ,/resources ,/static ,/public or /templates 6 | - Folders can be configured : spring.devtools.restart.exclude=static/**,public/** 7 | - Additional Paths : spring.devtools.restart.additional-paths 8 | - LiveReload http://livereload.com/extensions/ 9 | - Technology in progress!! So, expect a few problems! 10 | - Programming Tip 11 | - Become an expert at your IDE - https://www.youtube.com/watch?v=dN9GYsG1v_c 12 | 13 | ## Useful Snippets and References 14 | First Snippet 15 | ``` 16 | 17 | org.springframework.boot 18 | spring-boot-devtools 19 | true 20 | 21 | ``` 22 | 23 | ## Exercises 24 | - Make changes and see if they reflect immediately 25 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step10.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step10.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step11.md: -------------------------------------------------------------------------------- 1 | ## What You Will Learn during this Step: 2 | - Understand Content Negotiation 3 | - Accept:application/xml 4 | - Deliver XML Responses from the REST Services 5 | - http://localhost:8080/surveys/Survey1/questions/ 6 | 7 | ## Useful Snippets and References 8 | First Snippet 9 | ``` 10 | 11 | com.fasterxml.jackson.dataformat 12 | jackson-dataformat-xml 13 | 14 | 15 | ``` 16 | Second Snippet 17 | ``` 18 | 19 | 20 | Question1 21 | Largest Country in the World 22 | Russia 23 | 24 | India 25 | Russia 26 | United States 27 | China 28 | 29 | 30 | 31 | Question2 32 | Most Populus Country in the World 33 | China 34 | 35 | India 36 | Russia 37 | United States 38 | China 39 | 40 | 41 | 42 | Question3 43 | Highest GDP in the World 44 | United States 45 | 46 | India 47 | Russia 48 | United States 49 | China 50 | 51 | 52 | 53 | Question4 54 | Second largest english speaking country 55 | India 56 | 57 | India 58 | Russia 59 | United States 60 | China 61 | 62 | 63 | 64 | ``` 65 | 66 | 67 | 68 | ## Exercises 69 | - Execute other services using xml and see what happens! 70 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step12.md: -------------------------------------------------------------------------------- 1 | ## What You Will Learn during this Step: 2 | - Spring Initializr 3 | - https://start.spring.io 4 | - Create a few projects! 5 | 6 | ## Exercises 7 | - Create more projects with Spring Initializr and play around with it! 8 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step13.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step13.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step14.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step14.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step15.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step15.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step16.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step16.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step17.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step17.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step18.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step18.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step19.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step19.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step20.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step20.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step21.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step21.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step22.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step22.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step23.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step23.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step25.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step25.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step26.md: -------------------------------------------------------------------------------- 1 | ## What You Will Learn during this Step: 2 | - Securing our services with Basic Authentication using Spring Security 3 | - Executing Requests using Basic Authentication with Postman 4 | - default user name is user 5 | - default security password is printed in console 6 | 7 | ## Useful Snippets and References 8 | First Snippet 9 | ``` 10 | 11 | org.springframework.boot 12 | spring-boot-starter-security 13 | 14 | ``` 15 | 16 | Second Snippet 17 | ``` 18 | Using default security password: 19 | ``` 20 | 21 | Third Snippet : Executing a GET to http://localhost:8080/surveys/Survey1/questions/ 22 | ``` 23 | { 24 | "timestamp": 1483514297025, 25 | "status": 401, 26 | "error": "Unauthorized", 27 | "message": "Full authentication is required to access this resource", 28 | "path": "/surveys/Survey1/questions/" 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step27.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step27.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/Step28.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/05.Spring-Boot-Advanced/Step28.zip -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/StepReference.md: -------------------------------------------------------------------------------- 1 | ## What You Will Learn during this Step: 2 | - First 3 | - Second 4 | - Third 5 | 6 | ## Useful Snippets and References 7 | First Snippet 8 | ``` 9 | ``` 10 | Second Snippet 11 | ``` 12 | ``` 13 | 14 | ## Exercises 15 | 16 | ## Files List 17 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.in28minutes.springboot 5 | first-springboot-project 6 | 0.0.1-SNAPSHOT 7 | 8 | 9 | org.springframework.boot 10 | spring-boot-starter-parent 11 | 2.7.0 12 | 13 | 14 | 15 | 17 16 | 3.1.1 17 | 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-security 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-data-jpa 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-data-rest 38 | 39 | 40 | 41 | com.h2database 42 | h2 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-devtools 48 | true 49 | 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-starter-actuator 54 | 55 | 56 | 57 | org.springframework.data 58 | spring-data-rest-hal-explorer 59 | 60 | 61 | 62 | org.springframework.boot 63 | spring-boot-starter-test 64 | test 65 | 66 | 67 | 68 | org.springframework.security 69 | spring-security-test 70 | test 71 | 72 | 73 | 74 | 75 | 76 | 77 | org.springframework.boot 78 | spring-boot-maven-plugin 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/java/com/in28minutes/springboot/Application.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.ApplicationContext; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Profile; 8 | 9 | @SpringBootApplication 10 | public class Application { 11 | 12 | public static void main(String[] args) { 13 | ApplicationContext ctx = SpringApplication.run(Application.class, args); 14 | 15 | } 16 | 17 | @Profile("prod") 18 | @Bean 19 | public String dummy() { 20 | return "something"; 21 | } 22 | } -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/java/com/in28minutes/springboot/WelcomeController.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | import com.in28minutes.springboot.configuration.BasicConfiguration; 11 | 12 | @RestController 13 | public class WelcomeController { 14 | 15 | //Auto wiring 16 | @Autowired 17 | private WelcomeService service; 18 | 19 | @Autowired 20 | private BasicConfiguration configuration; 21 | 22 | @RequestMapping("/welcome") 23 | public String welcome() { 24 | return service.retrieveWelcomeMessage(); 25 | } 26 | 27 | @RequestMapping("/dynamic-configuration") 28 | public Map dynamicConfiguration() { 29 | Map map = new HashMap(); 30 | map.put("message", configuration.getMessage()); 31 | map.put("number", configuration.getNumber()); 32 | map.put("value", configuration.isValue()); 33 | 34 | return map; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/java/com/in28minutes/springboot/WelcomeService.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.stereotype.Component; 5 | 6 | //Spring to manage this bean and create an instance of this 7 | @Component 8 | public class WelcomeService { 9 | 10 | @Value("${welcome.message}") 11 | private String welcomeMessage; 12 | 13 | public String retrieveWelcomeMessage() { 14 | //Complex Method 15 | return welcomeMessage; 16 | } 17 | } -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/java/com/in28minutes/springboot/configuration/BasicConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.configuration; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | @ConfigurationProperties("basic") 8 | public class BasicConfiguration { 9 | private boolean value; 10 | private String message; 11 | private int number; 12 | 13 | public boolean isValue() { 14 | return value; 15 | } 16 | 17 | public void setValue(boolean value) { 18 | this.value = value; 19 | } 20 | 21 | public String getMessage() { 22 | return message; 23 | } 24 | 25 | public void setMessage(String message) { 26 | this.message = message; 27 | } 28 | 29 | public int getNumber() { 30 | return number; 31 | } 32 | 33 | public void setNumber(int number) { 34 | this.number = number; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/java/com/in28minutes/springboot/controller/SurveyController.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.controller; 2 | 3 | import java.net.URI; 4 | import java.util.List; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.web.bind.annotation.GetMapping; 9 | import org.springframework.web.bind.annotation.PathVariable; 10 | import org.springframework.web.bind.annotation.PostMapping; 11 | import org.springframework.web.bind.annotation.RequestBody; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder; 14 | 15 | import com.in28minutes.springboot.model.Question; 16 | import com.in28minutes.springboot.service.SurveyService; 17 | 18 | @RestController 19 | class SurveyController { 20 | @Autowired 21 | private SurveyService surveyService; 22 | 23 | @GetMapping("/surveys/{surveyId}/questions") 24 | public List retrieveQuestions(@PathVariable String surveyId) { 25 | return surveyService.retrieveQuestions(surveyId); 26 | } 27 | 28 | // GET "/surveys/{surveyId}/questions/{questionId}" 29 | @GetMapping("/surveys/{surveyId}/questions/{questionId}") 30 | public Question retrieveDetailsForQuestion(@PathVariable String surveyId, 31 | @PathVariable String questionId) { 32 | return surveyService.retrieveQuestion(surveyId, questionId); 33 | } 34 | 35 | // /surveys/{surveyId}/questions 36 | @PostMapping("/surveys/{surveyId}/questions") 37 | public ResponseEntity addQuestionToSurvey( 38 | @PathVariable String surveyId, @RequestBody Question newQuestion) { 39 | 40 | Question question = surveyService.addQuestion(surveyId, newQuestion); 41 | 42 | if (question == null) 43 | return ResponseEntity.noContent().build(); 44 | 45 | // Success - URI of the new resource in Response Header 46 | // Status - created 47 | // URI -> /surveys/{surveyId}/questions/{questionId} 48 | // question.getQuestionId() 49 | URI location = ServletUriComponentsBuilder.fromCurrentRequest().path( 50 | "/{id}").buildAndExpand(question.getId()).toUri(); 51 | 52 | // Status 53 | return ResponseEntity.created(location).build(); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/java/com/in28minutes/springboot/jpa/User.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.jpa; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.GenerationType; 6 | import javax.persistence.Id; 7 | 8 | @Entity 9 | public class User { 10 | 11 | @Id 12 | @GeneratedValue(strategy = GenerationType.AUTO) 13 | private Long id; 14 | 15 | private String name; 16 | private String role; 17 | 18 | protected User() { 19 | } 20 | 21 | public User(String name, String role) { 22 | super(); 23 | this.name = name; 24 | this.role = role; 25 | } 26 | 27 | public Long getId() { 28 | return id; 29 | } 30 | 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | public String getRole() { 36 | return role; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "User [id=" + id + ", name=" + name + ", role=" + role + "]"; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/java/com/in28minutes/springboot/jpa/UserCommandLineRunner.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.jpa; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.stereotype.Component; 8 | 9 | @Component 10 | public class UserCommandLineRunner implements CommandLineRunner { 11 | 12 | private static final Logger log = LoggerFactory 13 | .getLogger(UserCommandLineRunner.class); 14 | 15 | @Autowired 16 | private UserRepository repository; 17 | 18 | @Override 19 | public void run(String... args) throws Exception { 20 | 21 | repository.save(new User("Ranga", "Admin")); 22 | repository.save(new User("Ravi", "User")); 23 | repository.save(new User("Satish", "Admin")); 24 | repository.save(new User("Raghu", "User")); 25 | 26 | for (User user : repository.findAll()) { 27 | log.info(user.toString()); 28 | } 29 | 30 | log.info("Admin users are....."); 31 | log.info("____________________"); 32 | for (User user : repository.findByRole("Admin")) { 33 | log.info(user.toString()); 34 | } 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/java/com/in28minutes/springboot/jpa/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.jpa; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.repository.CrudRepository; 6 | 7 | public interface UserRepository extends CrudRepository { 8 | List findByRole(String role); 9 | } 10 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/java/com/in28minutes/springboot/jpa/UserRestRepository.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.jpa; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.repository.PagingAndSortingRepository; 6 | import org.springframework.data.repository.query.Param; 7 | import org.springframework.data.rest.core.annotation.RepositoryRestResource; 8 | 9 | @RepositoryRestResource(path = "users", collectionResourceRel = "users") 10 | public interface UserRestRepository extends 11 | PagingAndSortingRepository { 12 | List findByRole(@Param("role") String role); 13 | } 14 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/java/com/in28minutes/springboot/model/Question.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.model; 2 | 3 | import java.util.List; 4 | 5 | public class Question { 6 | private String id; 7 | private String description; 8 | private String correctAnswer; 9 | private List options; 10 | 11 | // Needed by Caused by: com.fasterxml.jackson.databind.JsonMappingException: 12 | // Can not construct instance of com.in28minutes.springboot.model.Question: 13 | // no suitable constructor found, can not deserialize from Object value 14 | // (missing default constructor or creator, or perhaps need to add/enable 15 | // type information?) 16 | public Question() { 17 | 18 | } 19 | 20 | public Question(String id, String description, String correctAnswer, 21 | List options) { 22 | super(); 23 | this.id = id; 24 | this.description = description; 25 | this.correctAnswer = correctAnswer; 26 | this.options = options; 27 | } 28 | 29 | public String getId() { 30 | return id; 31 | } 32 | 33 | public void setId(String id) { 34 | this.id = id; 35 | } 36 | 37 | public String getDescription() { 38 | return description; 39 | } 40 | 41 | public String getCorrectAnswer() { 42 | return correctAnswer; 43 | } 44 | 45 | public List getOptions() { 46 | return options; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return String 52 | .format("Question [id=%s, description=%s, correctAnswer=%s, options=%s]", 53 | id, description, correctAnswer, options); 54 | } 55 | 56 | @Override 57 | public int hashCode() { 58 | final int prime = 31; 59 | int result = 1; 60 | result = prime * result + ((id == null) ? 0 : id.hashCode()); 61 | return result; 62 | } 63 | 64 | @Override 65 | public boolean equals(Object obj) { 66 | if (this == obj) 67 | return true; 68 | if (obj == null) 69 | return false; 70 | if (getClass() != obj.getClass()) 71 | return false; 72 | Question other = (Question) obj; 73 | if (id == null) { 74 | if (other.id != null) 75 | return false; 76 | } else if (!id.equals(other.id)) 77 | return false; 78 | return true; 79 | } 80 | 81 | } -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/java/com/in28minutes/springboot/model/Survey.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.model; 2 | 3 | import java.util.List; 4 | 5 | public class Survey { 6 | private String id; 7 | private String title; 8 | private String description; 9 | private List questions; 10 | 11 | public Survey(String id, String title, String description, 12 | List questions) { 13 | super(); 14 | this.id = id; 15 | this.title = title; 16 | this.description = description; 17 | this.questions = questions; 18 | } 19 | 20 | public String getId() { 21 | return id; 22 | } 23 | 24 | public void setId(String id) { 25 | this.id = id; 26 | } 27 | 28 | public String getTitle() { 29 | return title; 30 | } 31 | 32 | public void setTitle(String title) { 33 | this.title = title; 34 | } 35 | 36 | public String getDescription() { 37 | return description; 38 | } 39 | 40 | public void setDescription(String description) { 41 | this.description = description; 42 | } 43 | 44 | public List getQuestions() { 45 | return questions; 46 | } 47 | 48 | public void setQuestions(List questions) { 49 | this.questions = questions; 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return "Survey [id=" + id + ", title=" + title + ", description=" 55 | + description + ", questions=" + questions + "]"; 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/java/com/in28minutes/springboot/security/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.security; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 5 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 6 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 7 | 8 | @Configuration 9 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 10 | // Authentication : User --> Roles 11 | protected void configure(AuthenticationManagerBuilder auth) 12 | throws Exception { 13 | auth.inMemoryAuthentication().passwordEncoder(org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance()).withUser("user1").password("secret1") 14 | .roles("USER").and().withUser("admin1").password("secret1") 15 | .roles("USER", "ADMIN"); 16 | } 17 | 18 | // Authorization : Role -> Access 19 | // survey -> USER 20 | protected void configure(HttpSecurity http) throws Exception { 21 | http.httpBasic().and().authorizeRequests().antMatchers("/surveys/**") 22 | .hasRole("USER").antMatchers("/users/**").hasRole("USER") 23 | .antMatchers("/**").hasRole("ADMIN").and().csrf().disable() 24 | .headers().frameOptions().disable(); 25 | } 26 | 27 | } -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/java/com/in28minutes/springboot/service/SurveyService.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.springboot.service; 2 | 3 | import java.math.BigInteger; 4 | import java.security.SecureRandom; 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | import org.springframework.stereotype.Component; 10 | 11 | import com.in28minutes.springboot.model.Question; 12 | import com.in28minutes.springboot.model.Survey; 13 | 14 | @Component 15 | public class SurveyService { 16 | private static List surveys = new ArrayList<>(); 17 | static { 18 | Question question1 = new Question("Question1", 19 | "Largest Country in the World", "Russia", Arrays.asList( 20 | "India", "Russia", "United States", "China")); 21 | Question question2 = new Question("Question2", 22 | "Most Populus Country in the World", "China", Arrays.asList( 23 | "India", "Russia", "United States", "China")); 24 | Question question3 = new Question("Question3", 25 | "Highest GDP in the World", "United States", Arrays.asList( 26 | "India", "Russia", "United States", "China")); 27 | Question question4 = new Question("Question4", 28 | "Second largest english speaking country", "India", Arrays 29 | .asList("India", "Russia", "United States", "China")); 30 | 31 | List questions = new ArrayList<>(Arrays.asList(question1, 32 | question2, question3, question4)); 33 | 34 | Survey survey = new Survey("Survey1", "My Favorite Survey", 35 | "Description of the Survey", questions); 36 | 37 | surveys.add(survey); 38 | } 39 | 40 | public List retrieveAllSurveys() { 41 | return surveys; 42 | } 43 | 44 | public Survey retrieveSurvey(String surveyId) { 45 | for (Survey survey : surveys) { 46 | if (survey.getId().equals(surveyId)) { 47 | return survey; 48 | } 49 | } 50 | return null; 51 | } 52 | 53 | public List retrieveQuestions(String surveyId) { 54 | Survey survey = retrieveSurvey(surveyId); 55 | 56 | if (survey == null) { 57 | return null; 58 | } 59 | 60 | return survey.getQuestions(); 61 | } 62 | 63 | public Question retrieveQuestion(String surveyId, String questionId) { 64 | Survey survey = retrieveSurvey(surveyId); 65 | 66 | if (survey == null) { 67 | return null; 68 | } 69 | 70 | for (Question question : survey.getQuestions()) { 71 | if (question.getId().equals(questionId)) { 72 | return question; 73 | } 74 | } 75 | 76 | return null; 77 | } 78 | 79 | private SecureRandom random = new SecureRandom(); 80 | 81 | public Question addQuestion(String surveyId, Question question) { 82 | Survey survey = retrieveSurvey(surveyId); 83 | 84 | if (survey == null) { 85 | return null; 86 | } 87 | 88 | String randomId = new BigInteger(130, random).toString(32); 89 | question.setId(randomId); 90 | 91 | survey.getQuestions().add(question); 92 | 93 | return question; 94 | } 95 | } -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | logging.level.org.springframework= TRACE 2 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | logging.level.org.springframework= INFO 2 | -------------------------------------------------------------------------------- /05.Spring-Boot-Advanced/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | logging.level.org.springframework=INFO 2 | app.name=in28Minutes 3 | welcome.message=Welcome message from property file! Welcome to ${app.name} 4 | 5 | basic.value=true 6 | basic.message=Welcome to in28minutes 7 | basic.number=200 8 | spring.datasource.url=jdbc:h2:mem:testdb;NON_KEYWORDS=USER -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/06.JPA-Introduction-In-10-Steps/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip 2 | -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/code-21July2017.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/06.JPA-Introduction-In-10-Steps/code-21July2017.zip -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/notes.txt: -------------------------------------------------------------------------------- 1 | ## JPA and in memory database H2 2 | 3 | Questions 4 | - Where is the database created? 5 | - What schema is used to create the tables? 6 | - Where are the tables created? 7 | - Can I see the data in the database? 8 | - Where is Hibernate coming in from? 9 | - How is a datasource created? 10 | 11 | Magic of Spring Boot and in Memory Database 12 | - Zero project setup or infrastructure 13 | - Zero Configuration 14 | - Zero Maintainance 15 | - Easy to use for Learning and Unit Tests 16 | - Simple Configuration to switch to a real database 17 | 18 | # Restrictions of using in-memory database 19 | - Data is not persisted between restarts 20 | 21 | Spring Boot chooses a default value for you based on whether it thinks your database is embedded (default create-drop) or not (default none). 22 | 23 | HibernateJpaAutoConfiguration matched: 24 | - @ConditionalOnClass found required classes 'org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean', 'javax.persistence.EntityManager'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition) 25 | - HibernateEntityManager found class 'org.hibernate.ejb.HibernateEntityManager' (HibernateJpaAutoConfiguration.HibernateEntityManagerCondition) 26 | 27 | DataSourceAutoConfiguration matched: 28 | - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition) 29 | 30 | JpaBaseConfiguration#entityManagerFactory matched: 31 | - @ConditionalOnMissingBean (types: org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean,javax.persistence.EntityManagerFactory; SearchStrategy: all) did not find any beans (OnBeanCondition) 32 | 33 | JpaBaseConfiguration#transactionManager matched: 34 | - @ConditionalOnMissingBean (types: org.springframework.transaction.PlatformTransactionManager; SearchStrategy: all) did not find any beans (OnBeanCondition) 35 | -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.in28minutes.learning.jpa 7 | jpa-in-10-steps 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | jpa-in-10-steps 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.7.0 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 17 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-data-jpa 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-web 37 | 38 | 39 | 40 | com.h2database 41 | h2 42 | runtime 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-test 48 | test 49 | 50 | 51 | 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-maven-plugin 57 | 58 | 59 | 60 | 61 | 62 | 63 | spring-snapshots 64 | Spring Snapshots 65 | https://repo.spring.io/snapshot 66 | 67 | true 68 | 69 | 70 | 71 | spring-milestones 72 | Spring Milestones 73 | https://repo.spring.io/milestone 74 | 75 | false 76 | 77 | 78 | 79 | 80 | 81 | 82 | spring-snapshots 83 | Spring Snapshots 84 | https://repo.spring.io/snapshot 85 | 86 | true 87 | 88 | 89 | 90 | spring-milestones 91 | Spring Milestones 92 | https://repo.spring.io/milestone 93 | 94 | false 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/src/main/java/com/in28minutes/learning/jpa/jpain10steps/JpaIn10StepsApplication.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learning.jpa.jpain10steps; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class JpaIn10StepsApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(JpaIn10StepsApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/src/main/java/com/in28minutes/learning/jpa/jpain10steps/UserDaoServiceCommandLineRunner.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learning.jpa.jpain10steps; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.stereotype.Component; 8 | 9 | import com.in28minutes.learning.jpa.jpain10steps.entity.User; 10 | import com.in28minutes.learning.jpa.jpain10steps.service.UserDAOService; 11 | 12 | @Component 13 | public class UserDaoServiceCommandLineRunner implements CommandLineRunner{ 14 | 15 | private static final Logger log = 16 | LoggerFactory.getLogger(UserDaoServiceCommandLineRunner.class); 17 | 18 | @Autowired 19 | private UserDAOService userDaoService; 20 | 21 | @Override 22 | public void run(String... arg0) throws Exception { 23 | User user = new User("Jack", "Admin"); 24 | //New User is created : User [id=1, name=Jack, role=Admin] 25 | long insert = userDaoService.insert(user); 26 | log.info("New User is created : " + user); 27 | } 28 | } -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/src/main/java/com/in28minutes/learning/jpa/jpain10steps/UserRepositoryCommandLineRunner.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learning.jpa.jpain10steps; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.CommandLineRunner; 10 | import org.springframework.stereotype.Component; 11 | 12 | import com.in28minutes.learning.jpa.jpain10steps.entity.User; 13 | import com.in28minutes.learning.jpa.jpain10steps.service.UserRepository; 14 | 15 | @Component 16 | public class UserRepositoryCommandLineRunner implements CommandLineRunner{ 17 | 18 | private static final Logger log = 19 | LoggerFactory.getLogger(UserRepositoryCommandLineRunner.class); 20 | 21 | @Autowired 22 | private UserRepository userRepository; 23 | 24 | @Override 25 | public void run(String... arg0) throws Exception { 26 | User user = new User("Jill", "Admin"); 27 | userRepository.save(user); 28 | log.info("New User is created : " + user); 29 | 30 | Optional userWithIdOne = userRepository.findById(1L); 31 | log.info("User is retrieved : " + userWithIdOne); 32 | 33 | List users = userRepository.findAll(); 34 | log.info("All Users : " + users); 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/src/main/java/com/in28minutes/learning/jpa/jpain10steps/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learning.jpa.jpain10steps.entity; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.Id; 6 | import javax.persistence.Table; 7 | 8 | //Table - User 9 | @Entity 10 | public class User { 11 | 12 | @Id 13 | @GeneratedValue 14 | private long id; 15 | 16 | private String name; 17 | 18 | private String role; 19 | 20 | protected User() { 21 | 22 | } 23 | 24 | public User(String name, String role) { 25 | super(); 26 | this.name = name; 27 | this.role = role; 28 | } 29 | 30 | public long getId() { 31 | return id; 32 | } 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public String getRole() { 39 | return role; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return String.format("User [id=%s, name=%s, role=%s]", id, name, role); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/src/main/java/com/in28minutes/learning/jpa/jpain10steps/service/UserDAOService.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learning.jpa.jpain10steps.service; 2 | 3 | import javax.persistence.EntityManager; 4 | import javax.persistence.PersistenceContext; 5 | import javax.transaction.Transactional; 6 | 7 | import org.springframework.stereotype.Repository; 8 | 9 | import com.in28minutes.learning.jpa.jpain10steps.entity.User; 10 | 11 | @Repository 12 | @Transactional 13 | public class UserDAOService { 14 | 15 | @PersistenceContext 16 | private EntityManager entityManager; 17 | 18 | public long insert(User user){ 19 | entityManager.persist(user); 20 | return user.getId(); 21 | } 22 | } 23 | 24 | /* 25 | * Spring Data JPA 26 | * 27 | * 28 | * 29 | */ 30 | -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/src/main/java/com/in28minutes/learning/jpa/jpain10steps/service/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learning.jpa.jpain10steps.service; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | import com.in28minutes.learning.jpa.jpain10steps.entity.User; 6 | 7 | public interface UserRepository extends JpaRepository{ 8 | 9 | } 10 | -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.jpa.show-sql=true 2 | spring.h2.console.enabled=true 3 | logging.level.org.springframework=debug 4 | spring.datasource.url=jdbc:h2:mem:testdb;NON_KEYWORDS=USER -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/src/test/java/com/in28minutes/learning/jpa/jpain10steps/JpaIn10StepsApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learning.jpa.jpain10steps; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.junit.jupiter.api.extension.ExtendWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit.jupiter.SpringExtension; 7 | 8 | // replaced @RunWith with @ExtendWith 9 | // replaced SpringRunner.class with SpringExtension.class 10 | @ExtendWith(SpringExtension.class) 11 | @SpringBootTest 12 | public class JpaIn10StepsApplicationTests { 13 | 14 | @Test 15 | public void contextLoads() { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/step-completed.sh: -------------------------------------------------------------------------------- 1 | java -cp /ProgrammingExcellence/Workspaces/Rithus.com/ListDirectoryContentInGitFormat/bin test.ListDirectoryContentInGitFormat $PWD >> $1.md 2 | zip -r $1.zip . -x "target/*" -x ".*/*" -x ".*" -x "*.md" -x "mvn*" -x "*.zip" 3 | git add *; git commit -m "$1"; git push; 4 | -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/step21.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/06.JPA-Introduction-In-10-Steps/step21.zip -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/step22.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/06.JPA-Introduction-In-10-Steps/step22.zip -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/step23.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/in28minutes/spring-boot-master-class/3b69ddaf30619c22d87df4b5c006c4e741f3bfb2/06.JPA-Introduction-In-10-Steps/step23.zip -------------------------------------------------------------------------------- /06.JPA-Introduction-In-10-Steps/take-step-backup.sh: -------------------------------------------------------------------------------- 1 | java -cp /ProgrammingExcellence/Workspaces/Rithus.com/ListDirectoryContentInGitFormat/bin test.ListDirectoryContentInGitFormat $PWD >> $1.md 2 | zip -r $1.zip . -x "target/*" -x ".*/*" -x ".*" -x "*.md" -x "mvn*" -x "*.zip" -------------------------------------------------------------------------------- /09.Spring-Introduction-In-10-Steps/HELP.md: -------------------------------------------------------------------------------- 1 | # Read Me First 2 | The following was discovered as part of building this project: 3 | 4 | * The original package name 'com.in28minutes.learn-spring-framework' is invalid and this project uses 'com.in28minutes.learnspringframework' instead. 5 | 6 | # Getting Started 7 | 8 | ### Reference Documentation 9 | For further reference, please consider the following sections: 10 | 11 | * [Official Apache Maven documentation](https://maven.apache.org/guides/index.html) 12 | * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.4.4/maven-plugin/reference/html/) 13 | * [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.4.4/maven-plugin/reference/html/#build-image) 14 | 15 | -------------------------------------------------------------------------------- /09.Spring-Introduction-In-10-Steps/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.7.0 9 | 10 | 11 | com.in28minutes 12 | learn-spring-framework 13 | 0.0.1-SNAPSHOT 14 | learn-spring-framework 15 | Demo project for Spring Boot 16 | 17 | 11 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-web 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-test 34 | test 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-maven-plugin 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /09.Spring-Introduction-In-10-Steps/src/main/java/com/in28minutes/learnspringframework/LearnSpringFrameworkApplication.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learnspringframework; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.ConfigurableApplicationContext; 6 | 7 | import com.in28minutes.learnspringframework.game.GameRunner; 8 | 9 | @SpringBootApplication 10 | //@ComponentScan({"com.in28minutes.learnspringframework", "com.in28minutes.dummy"}) 11 | public class LearnSpringFrameworkApplication { 12 | 13 | public static void main(String[] args) { 14 | 15 | ConfigurableApplicationContext context = 16 | SpringApplication.run(LearnSpringFrameworkApplication.class, args); 17 | 18 | //MarioGame,GameRunner 19 | GameRunner runner = context.getBean(GameRunner.class); 20 | 21 | // MarioGame game = new MarioGame(); 22 | //SuperContraGame game = new SuperContraGame(); 23 | // GameRunner runner = new GameRunner(game); 24 | 25 | runner.runGame(); 26 | 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /09.Spring-Introduction-In-10-Steps/src/main/java/com/in28minutes/learnspringframework/game/GameRunner.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learnspringframework.game; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | public class GameRunner { 8 | 9 | @Autowired 10 | private GamingConsole game; 11 | 12 | public GameRunner(GamingConsole game) { 13 | System.out.println("Using Constructor"); 14 | this.game = game; 15 | } 16 | 17 | 18 | // public void setGame(GamingConsole game) { 19 | // System.out.println("Using Setter"); 20 | // this.game = game; 21 | // } 22 | 23 | 24 | 25 | public void runGame() { 26 | game.up(); 27 | game.down(); 28 | game.left(); 29 | game.right(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /09.Spring-Introduction-In-10-Steps/src/main/java/com/in28minutes/learnspringframework/game/GamingConsole.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learnspringframework.game; 2 | 3 | public interface GamingConsole { 4 | 5 | void up(); 6 | 7 | void down(); 8 | 9 | void left(); 10 | 11 | void right(); 12 | 13 | } -------------------------------------------------------------------------------- /09.Spring-Introduction-In-10-Steps/src/main/java/com/in28minutes/learnspringframework/game/MarioGame.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learnspringframework.game; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | @Component 6 | public class MarioGame implements GamingConsole { 7 | 8 | @Override 9 | public void up() { 10 | System.out.println("jump"); 11 | } 12 | 13 | @Override 14 | public void down() { 15 | System.out.println("go into a hole"); 16 | } 17 | 18 | @Override 19 | public void left() { 20 | System.out.println("stop"); 21 | } 22 | 23 | @Override 24 | public void right() { 25 | System.out.println("go faster"); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /09.Spring-Introduction-In-10-Steps/src/main/java/com/in28minutes/learnspringframework/game/PacManGame.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learnspringframework.game; 2 | 3 | import org.springframework.context.annotation.Primary; 4 | import org.springframework.stereotype.Component; 5 | 6 | @Component 7 | @Primary 8 | public class PacManGame implements GamingConsole{ 9 | 10 | public void up() { 11 | System.out.println("PacManGame up"); 12 | } 13 | 14 | public void down() { 15 | System.out.println("down"); 16 | } 17 | 18 | public void left() { 19 | System.out.println("left"); 20 | } 21 | 22 | public void right() { 23 | System.out.println("right"); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /09.Spring-Introduction-In-10-Steps/src/main/java/com/in28minutes/learnspringframework/game/SuperContraGame.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learnspringframework.game; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | @Component 6 | //@Primary 7 | public class SuperContraGame implements GamingConsole{ 8 | 9 | public void up() { 10 | System.out.println("SuperContraGame up"); 11 | } 12 | 13 | public void down() { 14 | System.out.println("down"); 15 | } 16 | 17 | public void left() { 18 | System.out.println("left"); 19 | } 20 | 21 | public void right() { 22 | System.out.println("right"); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /09.Spring-Introduction-In-10-Steps/src/main/java/com/in28minutes/learnspringframework/sample/enterprise/flow/business/BusinessService.java: -------------------------------------------------------------------------------- 1 | //Business Logic 2 | package com.in28minutes.learnspringframework.sample.enterprise.flow.business; 3 | 4 | import java.util.List; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Component; 8 | 9 | import com.in28minutes.learnspringframework.sample.enterprise.flow.data.DataService; 10 | 11 | @Component 12 | public class BusinessService { 13 | 14 | @Autowired 15 | private DataService dataService; 16 | 17 | public long calculateSum() { 18 | List data = dataService.retrieveData(); 19 | return data.stream().reduce(Integer::sum).get(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /09.Spring-Introduction-In-10-Steps/src/main/java/com/in28minutes/learnspringframework/sample/enterprise/flow/data/DataService.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learnspringframework.sample.enterprise.flow.data; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | public class DataService { 10 | public List retrieveData() { 11 | return Arrays.asList(12,34,56,78,90); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /09.Spring-Introduction-In-10-Steps/src/main/java/com/in28minutes/learnspringframework/sample/enterprise/flow/web/Controller.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learnspringframework.sample.enterprise.flow.web; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import com.in28minutes.learnspringframework.sample.enterprise.flow.business.BusinessService; 8 | 9 | //Sending response in the right format 10 | @RestController 11 | public class Controller { 12 | 13 | @Autowired 14 | private BusinessService businessService; 15 | 16 | //"/sum" => 100 17 | @GetMapping("/sum") 18 | public long displaySum() { 19 | return businessService.calculateSum(); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /09.Spring-Introduction-In-10-Steps/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # logging.level.org.springframework=DEBUG 2 | -------------------------------------------------------------------------------- /09.Spring-Introduction-In-10-Steps/src/test/java/com/in28minutes/learnspringframework/LearnSpringFrameworkApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.in28minutes.learnspringframework; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class LearnSpringFrameworkApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /announcements.md: -------------------------------------------------------------------------------- 1 | Excited to announce new updates to this course. (More updates coming soon!) 2 | 3 | Following sections of the course are now updated: 4 | - Section 2: Introduction to Spring Boot in 10 Steps (Actually 12) 5 | - https://github.com/in28minutes/spring-boot-master-class/tree/master/01.Spring-Boot-Introduction-In-10-Steps 6 | - Section 3: Web Application with Spring Boot (Recorded with Spring Boot 3 - M3) 7 | - https://github.com/in28minutes/spring-boot-master-class/tree/master/02.Spring-Boot-Web-Application-V2 8 | - Section 8: Introduction to Functional Programming Basics 9 | 10 | Highlights: 11 | - Section 3 uses the latest version of Spring Boot, BootStrap and JQuery 12 | - Section 3 is updated to include JPA and connects to both H2 and MySQL database 13 | - MySQL database is launched as a Docker container 14 | - New approach using a mix of slides and hands-on 15 | - We are enhancing our courses to use Functional Programming where needed 16 | 17 | What should learners do? 18 | 19 | - If you are in the early part of the first section "Web Application with Spring Boot", we recommend you to restart the course and benefit from the new updates! 20 | - If you are in a later stage of the course, continue and complete the course. Watch the new sections in 2X speed to get knowledge of the new updates. 21 | 22 | 23 | What's Next? 24 | 25 | We will be re-recording these sections with Spring Boot 3 next: 26 | - Introduction to JUnit in 5 Steps 27 | - Introduction to Mockito in 5 Steps 28 | - Introduction to JPA in 10 Steps -------------------------------------------------------------------------------- /spring-boot-3.2.x-changes.md: -------------------------------------------------------------------------------- 1 | ## Spring Boot 3.2.x Changes 2 | 3 | Using JSPs in web applications need a few changes (details below) 4 | - Change 01: Use `jakarta.servlet.jsp.jstl` instead of `glassfish-jstl` 5 | - Change 02: Use `jakarta.tags.core` instead of `http://java.sun.com/jsp/jstl/core` as taglib 6 | - Change 03: Run `mvn clean install` to update libraries 7 | 8 | ### Change 01: Use `jakarta.servlet.jsp.jstl` instead of `glassfish-jstl` 9 | 10 | **_Spring Boot 3.2.x and greater_** 11 | 12 | ```xml 13 | 14 | org.glassfish.web 15 | jakarta.servlet.jsp.jstl 16 | 17 | ``` 18 | 19 | `jakarta.servlet.jsp.jstl` replaces `glassfish-jstl` (recommended for **_Spring Boot <= 3.1.x_**) 20 | 21 | ```xml 22 | 23 | org.eclipse.jetty 24 | glassfish-jstl 25 | 26 | ``` 27 | 28 | ## Change 02: Use `jakarta.tags.core` instead of `http://java.sun.com/jsp/jstl/core` as taglib 29 | 30 | ### Spring Boot 3.2.X and greater 31 | 32 | Use 33 | ```jsp 34 | <%@ taglib prefix="c" uri="jakarta.tags.core" %> 35 | ``` 36 | 37 | ### Spring Boot 3.1.X and lower 38 | Use 39 | ```jsp 40 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 41 | ``` 42 | 43 | ### Change 03: Run `mvn clean install` to update libraries 44 | 45 | And then execute the `mvn clean install` command 46 | 47 | 48 | 49 | 50 | Thank you! 51 | 52 | in28minutes team (Maahi and Ranga) --------------------------------------------------------------------------------