├── 01-hello-world-rest-api
├── pom.xml
├── readme.md
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── rest
│ │ │ └── webservices
│ │ │ └── restfulwebservices
│ │ │ ├── HelloWorldBean.java
│ │ │ ├── HelloWorldController.java
│ │ │ └── RestfulWebServicesApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── in28minutes
│ └── rest
│ └── webservices
│ └── restfulwebservices
│ └── RestfulWebServicesApplicationTests.java
├── 02-todo-web-application-h2
├── Dockerfile
├── pom.xml
├── readme.md
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── springboot
│ │ │ └── web
│ │ │ ├── EnvironmentConfigurationLogger.java
│ │ │ ├── SpringBootFirstWebApplication.java
│ │ │ ├── controller
│ │ │ ├── ErrorController.java
│ │ │ ├── LogoutController.java
│ │ │ ├── TodoController.java
│ │ │ └── WelcomeController.java
│ │ │ ├── model
│ │ │ └── Todo.java
│ │ │ ├── security
│ │ │ └── SecurityConfiguration.java
│ │ │ └── service
│ │ │ └── TodoRepository.java
│ ├── resources
│ │ ├── application.properties
│ │ └── data.sql
│ └── webapp
│ │ └── WEB-INF
│ │ └── jsp
│ │ ├── common
│ │ ├── footer.jspf
│ │ ├── header.jspf
│ │ └── navigation.jspf
│ │ ├── error.jsp
│ │ ├── list-todos.jsp
│ │ ├── todo.jsp
│ │ └── welcome.jsp
│ └── test
│ └── java
│ └── com
│ └── in28minutes
│ └── springboot
│ └── web
│ └── SpringBootFirstWebApplicationTests.java
├── 03-todo-web-application-mysql
├── pom.xml
├── readme.md
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── springboot
│ │ │ └── web
│ │ │ ├── EnvironmentConfigurationLogger.java
│ │ │ ├── SpringBootFirstWebApplication.java
│ │ │ ├── controller
│ │ │ ├── ErrorController.java
│ │ │ ├── LogoutController.java
│ │ │ ├── TodoController.java
│ │ │ └── WelcomeController.java
│ │ │ ├── model
│ │ │ └── Todo.java
│ │ │ ├── security
│ │ │ └── SecurityConfiguration.java
│ │ │ └── service
│ │ │ ├── TodoRepository.java
│ │ │ └── TodoService.java
│ ├── resources
│ │ └── application.properties
│ └── webapp
│ │ └── WEB-INF
│ │ └── jsp
│ │ ├── common
│ │ ├── footer.jspf
│ │ ├── header.jspf
│ │ └── navigation.jspf
│ │ ├── error.jsp
│ │ ├── list-todos.jsp
│ │ ├── todo.jsp
│ │ └── welcome.jsp
│ └── test
│ ├── java
│ └── com
│ │ └── in28minutes
│ │ └── springboot
│ │ └── web
│ │ └── SpringBootFirstWebApplicationTests.java
│ └── resources
│ └── application.properties
├── 04-spring-boot-react-full-stack-h2
├── frontend
│ └── todo-app
│ │ ├── Dockerfile
│ │ ├── build
│ │ ├── .azure
│ │ │ └── config
│ │ ├── asset-manifest.json
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── manifest.json
│ │ ├── precache-manifest.761a421da099d8debfc4c14fcfc2a75b.js
│ │ ├── service-worker.js
│ │ └── static
│ │ │ ├── css
│ │ │ ├── main.e593cbc2.chunk.css
│ │ │ └── main.e593cbc2.chunk.css.map
│ │ │ └── js
│ │ │ ├── 2.3f64e426.chunk.js
│ │ │ ├── 2.3f64e426.chunk.js.map
│ │ │ ├── main.dec38524.chunk.js
│ │ │ ├── main.dec38524.chunk.js.map
│ │ │ ├── runtime~main.c5541365.js
│ │ │ └── runtime~main.c5541365.js.map
│ │ ├── package-lock.json
│ │ ├── package.json
│ │ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ └── manifest.json
│ │ └── src
│ │ ├── App.css
│ │ ├── App.js
│ │ ├── App.test.js
│ │ ├── Constants.js
│ │ ├── api
│ │ └── todo
│ │ │ ├── HelloWorldService.js
│ │ │ └── TodoDataService.js
│ │ ├── bootstrap.css
│ │ ├── components
│ │ ├── counter
│ │ │ ├── Counter.css
│ │ │ └── Counter.jsx
│ │ ├── learning-examples
│ │ │ ├── FirstComponent.jsx
│ │ │ ├── SecondComponent.jsx
│ │ │ └── ThirdComponent.jsx
│ │ └── todo
│ │ │ ├── AuthenticatedRoute.jsx
│ │ │ ├── AuthenticationService.js
│ │ │ ├── ErrorComponent.jsx
│ │ │ ├── FooterComponent.jsx
│ │ │ ├── HeaderComponent.jsx
│ │ │ ├── ListTodosComponent.jsx
│ │ │ ├── LoginComponent.jsx
│ │ │ ├── LogoutComponent.jsx
│ │ │ ├── TodoApp.jsx
│ │ │ ├── TodoComponent.jsx
│ │ │ └── WelcomeComponent.jsx
│ │ ├── index.css
│ │ ├── index.js
│ │ ├── logo.svg
│ │ ├── serviceWorker.js
│ │ └── web.config
└── restful-web-services
│ ├── pom.xml
│ ├── react_00_architecture.png
│ ├── readme.md
│ └── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── rest
│ │ │ ├── basic
│ │ │ └── auth
│ │ │ │ ├── AuthenticationBean.java
│ │ │ │ ├── BasicAuthenticationController.java
│ │ │ │ └── SpringSecurityConfigurationBasicAuth.java
│ │ │ └── webservices
│ │ │ └── restfulwebservices
│ │ │ ├── RestfulWebServicesApplication.java
│ │ │ ├── helloworld
│ │ │ ├── HelloWorldBean.java
│ │ │ └── HelloWorldController.java
│ │ │ ├── jwt
│ │ │ ├── JWTWebSecurityConfig.java
│ │ │ ├── JwtInMemoryUserDetailsService.java
│ │ │ ├── JwtTokenAuthorizationOncePerRequestFilter.java
│ │ │ ├── JwtTokenUtil.java
│ │ │ ├── JwtUnAuthorizedResponseAuthenticationEntryPoint.java
│ │ │ ├── JwtUserDetails.java
│ │ │ ├── JwtUserDetailsService.java
│ │ │ ├── User.java
│ │ │ ├── UserRepository.java
│ │ │ └── resource
│ │ │ │ ├── AuthenticationException.java
│ │ │ │ ├── JwtAuthenticationRestController.java
│ │ │ │ ├── JwtTokenRequest.java
│ │ │ │ └── JwtTokenResponse.java
│ │ │ └── todo
│ │ │ ├── Todo.java
│ │ │ ├── TodoJpaRepository.java
│ │ │ └── TodoJpaResource.java
│ └── resources
│ │ ├── application.properties
│ │ └── data.sql
│ └── test
│ └── java
│ └── com
│ └── in28minutes
│ └── rest
│ └── webservices
│ └── restfulwebservices
│ └── RestfulWebServicesApplicationTests.java
├── 05-todo-rest-api-h2-containerized
├── Dockerfile
├── pom.xml
├── readme.md
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── rest
│ │ │ └── webservices
│ │ │ └── restfulwebservices
│ │ │ ├── RestfulWebServicesApplication.java
│ │ │ ├── helloworld
│ │ │ ├── HelloWorldBean.java
│ │ │ └── HelloWorldController.java
│ │ │ └── todo
│ │ │ ├── Todo.java
│ │ │ ├── TodoJpaRepository.java
│ │ │ └── TodoJpaResource.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── in28minutes
│ └── rest
│ └── webservices
│ └── restfulwebservices
│ └── RestfulWebServicesApplicationTests.java
├── 06-todo-rest-api-mysql-containerized
├── .ebextensions
│ └── sg-extensions.config
├── Dockerfile
├── docker-compose.yaml
├── pom.xml
├── readme.md
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── rest
│ │ │ └── webservices
│ │ │ └── restfulwebservices
│ │ │ ├── RestfulWebServicesApplication.java
│ │ │ ├── helloworld
│ │ │ ├── HelloWorldBean.java
│ │ │ └── HelloWorldController.java
│ │ │ └── todo
│ │ │ ├── Todo.java
│ │ │ ├── TodoJpaRepository.java
│ │ │ └── TodoJpaResource.java
│ └── resources
│ │ └── application.properties
│ └── test
│ ├── java
│ └── com
│ │ └── in28minutes
│ │ └── rest
│ │ └── webservices
│ │ └── restfulwebservices
│ │ └── RestfulWebServicesApplicationTests.java
│ └── resources
│ └── application.properties
├── 07-hello-world-rest-api
├── pom.xml
├── readme.md
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── in28minutes
│ │ │ └── rest
│ │ │ └── webservices
│ │ │ └── restfulwebservices
│ │ │ ├── HelloWorldBean.java
│ │ │ ├── HelloWorldController.java
│ │ │ ├── InstanceInformationService.java
│ │ │ └── RestfulWebServicesApplication.java
│ └── resources
│ │ └── application.properties
│ └── test
│ └── java
│ └── com
│ └── in28minutes
│ └── rest
│ └── webservices
│ └── restfulwebservices
│ └── RestfulWebServicesApplicationTests.java
└── README.md
/01-hello-world-rest-api/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 | 4.0.0
7 | com.in28minutes.rest.webservices
8 | 01-hello-world-rest-api
9 | 0.0.1-SNAPSHOT
10 | jar
11 | Demo project for Spring Boot
12 | hello-world-rest-api
13 |
14 | org.springframework.boot
15 | spring-boot-starter-parent
16 | 2.1.7.RELEASE
17 |
18 |
19 |
20 |
21 | UTF-8
22 | UTF-8
23 | 1.8
24 | 3.1.1
25 |
26 | ${project.build.directory}/${project.build.finalName}.jar
27 |
28 |
29 |
30 | org.springframework.boot
31 | spring-boot-starter-web
32 |
33 |
34 | org.springframework.boot
35 | spring-boot-devtools
36 | runtime
37 |
38 |
39 | org.springframework.boot
40 | spring-boot-starter-test
41 | test
42 |
43 |
44 |
45 | hello-world-rest-api
46 |
47 |
48 | org.springframework.boot
49 | spring-boot-maven-plugin
50 |
51 |
56 |
57 |
58 |
59 |
60 | spring-snapshots
61 | Spring Snapshots
62 | https://repo.spring.io/snapshot
63 |
64 | true
65 |
66 |
67 |
68 | spring-milestones
69 | Spring Milestones
70 | https://repo.spring.io/milestone
71 |
72 | false
73 |
74 |
75 |
76 |
77 |
78 | spring-snapshots
79 | Spring Snapshots
80 | https://repo.spring.io/snapshot
81 |
82 | true
83 |
84 |
85 |
86 | spring-milestones
87 | Spring Milestones
88 | https://repo.spring.io/milestone
89 |
90 | false
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/01-hello-world-rest-api/readme.md:
--------------------------------------------------------------------------------
1 | # Hello World Rest API
2 |
3 | ### Running the Application
4 |
5 | Run com.in28minutes.rest.webservices.restfulwebservices.RestfulWebServicesApplication as a Java Application.
6 |
7 | - http://localhost:8080/hello-world
8 |
9 | ```txt
10 | Hello World
11 | ```
12 |
13 | - http://localhost:8080/hello-world-bean
14 |
15 | ```json
16 | {"message":"Hello World"}
17 | ```
18 |
19 | - http://localhost:8080/hello-world/path-variable/in28minutes
20 |
21 | ```json
22 | {"message":"Hello World, in28minutes"}
23 | ```
24 |
25 | ### Plugin configuration
26 |
27 | ```
28 |
29 | com.microsoft.azure
30 | azure-webapp-maven-plugin
31 | 1.7.0
32 |
33 | ```
34 |
35 | ### Azure CLI
36 |
37 | - https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest
38 |
39 | ### Final Plugin Configuration
40 | ```
41 |
42 | com.microsoft.azure
43 | azure-webapp-maven-plugin
44 | 1.7.0
45 |
46 | V2
47 | hello-world-rest-api-rg
48 | hello-world-rest-api-in28minutes
49 | B1
50 | westeurope
51 |
52 |
53 | JAVA_OPTS
54 | -Dserver.port=80
55 |
56 |
57 |
58 | linux
59 | java11
60 | java11
61 |
62 |
63 |
64 |
65 | ${project.basedir}/target
66 |
67 | *.jar
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | ```
76 | ### Logging Configuration
77 |
78 | ```
79 | -Dlogging.level.org.springframework=DEBUG
80 | ```
--------------------------------------------------------------------------------
/01-hello-world-rest-api/src/main/java/com/in28minutes/rest/webservices/restfulwebservices/HelloWorldBean.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.rest.webservices.restfulwebservices;
2 |
3 | public class HelloWorldBean {
4 |
5 | private String message;
6 |
7 | public HelloWorldBean(String message) {
8 | this.message = message;
9 | }
10 |
11 | public String getMessage() {
12 | return message;
13 | }
14 |
15 | public void setMessage(String message) {
16 | this.message = message;
17 | }
18 |
19 | @Override
20 | public String toString() {
21 | return String.format("HelloWorldBean [message=%s]", message);
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/01-hello-world-rest-api/src/main/java/com/in28minutes/rest/webservices/restfulwebservices/HelloWorldController.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.rest.webservices.restfulwebservices;
2 |
3 | import org.springframework.web.bind.annotation.GetMapping;
4 | import org.springframework.web.bind.annotation.PathVariable;
5 | import org.springframework.web.bind.annotation.RestController;
6 |
7 | @RestController
8 | public class HelloWorldController {
9 |
10 | @GetMapping(path = "/hello-world")
11 | public String helloWorld() {
12 | return "Hello World";
13 | }
14 |
15 | @GetMapping(path = "/hello-world-bean")
16 | public HelloWorldBean helloWorldBean() {
17 | // throw new RuntimeException("Some Error has Happened! Contact Support at
18 | // ***-***");
19 | return new HelloWorldBean("Hello World");
20 | }
21 |
22 | /// hello-world/path-variable/in28minutes
23 | @GetMapping(path = "/hello-world/path-variable/{name}")
24 | public HelloWorldBean helloWorldPathVariable(@PathVariable String name) {
25 | return new HelloWorldBean(String.format("Hello World, %s", name));
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/01-hello-world-rest-api/src/main/java/com/in28minutes/rest/webservices/restfulwebservices/RestfulWebServicesApplication.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.rest.webservices.restfulwebservices;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class RestfulWebServicesApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(RestfulWebServicesApplication.class, args);
11 | }
12 | }
--------------------------------------------------------------------------------
/01-hello-world-rest-api/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | logging.level.org.springframework = debug
2 |
--------------------------------------------------------------------------------
/01-hello-world-rest-api/src/test/java/com/in28minutes/rest/webservices/restfulwebservices/RestfulWebServicesApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.rest.webservices.restfulwebservices;
2 |
3 | import org.junit.Test;
4 | import org.junit.runner.RunWith;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.test.context.junit4.SpringRunner;
7 |
8 | @RunWith(SpringRunner.class)
9 | @SpringBootTest
10 | public class RestfulWebServicesApplicationTests {
11 |
12 | @Test
13 | public void contextLoads() {
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/02-todo-web-application-h2/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM tomcat:8.0.51-jre8-alpine
2 | EXPOSE 8080
3 | RUN rm -rf /usr/local/tomcat/webapps/*
4 | COPY target/*.war /usr/local/tomcat/webapps/ROOT.war
5 | CMD ["catalina.sh","run"]
--------------------------------------------------------------------------------
/02-todo-web-application-h2/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 | 4.0.0
7 | com.in28minutes.springboot.web
8 | 02-todo-web-application-h2
9 | 0.0.1-SNAPSHOT
10 | war
11 | todo-web-application-h2
12 | Demo project for Spring Boot
13 |
14 | org.springframework.boot
15 | spring-boot-starter-parent
16 | 2.1.7.RELEASE
17 |
18 |
19 |
20 |
21 | UTF-8
22 | UTF-8
23 | 1.8
24 | 3.1.1
25 |
26 |
27 |
28 | org.springframework.boot
29 | spring-boot-starter-web
30 |
31 |
32 | org.springframework.boot
33 | spring-boot-starter-data-jpa
34 |
35 |
36 | com.h2database
37 | h2
38 | runtime
39 |
40 |
41 | org.springframework.boot
42 | spring-boot-starter-security
43 |
44 |
45 | javax.servlet
46 | jstl
47 |
48 |
49 | org.webjars
50 | bootstrap
51 | 3.3.6
52 |
53 |
54 | org.webjars
55 | bootstrap-datepicker
56 | 1.0.1
57 |
58 |
59 | org.webjars
60 | jquery
61 | 1.9.1
62 |
63 |
64 | org.apache.tomcat.embed
65 | tomcat-embed-jasper
66 | provided
67 |
68 |
69 | org.springframework.boot
70 | spring-boot-starter-tomcat
71 | provided
72 |
73 |
74 | org.springframework.boot
75 | spring-boot-devtools
76 | runtime
77 |
78 |
79 | org.springframework.boot
80 | spring-boot-starter-test
81 | test
82 |
83 |
84 |
85 | todo-web-application-h2
86 |
87 |
88 | org.springframework.boot
89 | spring-boot-maven-plugin
90 |
91 |
92 |
97 |
98 |
99 |
100 | spring-milestones
101 | Spring Milestones
102 | https://repo.spring.io/milestones
103 |
104 |
105 |
106 |
107 | spring-milestones
108 | Spring Milestones
109 | https://repo.spring.io/milestones
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/02-todo-web-application-h2/readme.md:
--------------------------------------------------------------------------------
1 | # Todo Web Application using Spring Boot and H2 In memory database
2 |
3 | Run com.in28minutes.springboot.web.SpringBootFirstWebApplication as a Java Application.
4 |
5 | Runs on default port of Spring Boot - 8080
6 |
7 | ## Can be run as a Jar or a WAR
8 |
9 | `mvn clean install` generate a war which can deployed to your favorite web server.
10 |
11 | ## Web Application
12 |
13 | - http://localhost:8080/login with in28minutes/dummy as credentials
14 | - You can add, delete and update your todos
15 | - Spring Security is used to secure the application
16 | - `com.in28minutes.springboot.web.security.SecurityConfiguration` contains the in memory security credential configuration.
17 |
18 | ## H2 Console
19 |
20 | - http://localhost:8080/h2-console
21 | - Use `jdbc:h2:mem:testdb` as JDBC URL
22 |
23 |
24 | ## Plugin Initial Configuration
25 | ```
26 |
27 | com.microsoft.azure
28 | azure-webapp-maven-plugin
29 | 1.7.0
30 |
31 |
32 | ```
33 |
34 | ## Plugin Final Configuration
35 | ```
36 |
37 | com.microsoft.azure
38 | azure-webapp-maven-plugin
39 | 1.7.0
40 |
41 | V2
42 | todo-web-application-h2-rg
43 | todo-web-application-h2-in28minutes
44 | B1
45 | westeurope
46 |
47 | windows
48 | 11
49 | tomcat 9.0
50 |
51 |
52 |
53 |
54 | ${project.basedir}/target
55 |
56 | *.war
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | ```
--------------------------------------------------------------------------------
/02-todo-web-application-h2/src/main/java/com/in28minutes/springboot/web/EnvironmentConfigurationLogger.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.springboot.web;
2 |
3 | import java.util.Arrays;
4 | import java.util.stream.StreamSupport;
5 |
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.context.event.ContextRefreshedEvent;
9 | import org.springframework.context.event.EventListener;
10 | import org.springframework.core.env.AbstractEnvironment;
11 | import org.springframework.core.env.EnumerablePropertySource;
12 | import org.springframework.core.env.Environment;
13 | import org.springframework.core.env.MutablePropertySources;
14 | import org.springframework.stereotype.Component;
15 |
16 | @Component
17 | public class EnvironmentConfigurationLogger {
18 |
19 | private static final Logger LOGGER = LoggerFactory.getLogger(EnvironmentConfigurationLogger.class);
20 |
21 | @SuppressWarnings("rawtypes")
22 | @EventListener
23 | public void handleContextRefresh(ContextRefreshedEvent event) {
24 | final Environment environment = event.getApplicationContext().getEnvironment();
25 | LOGGER.debug("====== Environment and configuration ======");
26 | LOGGER.debug("Active profiles: {}", Arrays.toString(environment.getActiveProfiles()));
27 | final MutablePropertySources sources = ((AbstractEnvironment) environment).getPropertySources();
28 | StreamSupport.stream(sources.spliterator(), false).filter(ps -> ps instanceof EnumerablePropertySource)
29 | .map(ps -> ((EnumerablePropertySource) ps).getPropertyNames()).flatMap(Arrays::stream).distinct()
30 | .forEach(prop -> LOGGER.debug("{}", prop));// environment.getProperty(prop)
31 | LOGGER.debug("===========================================");
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/02-todo-web-application-h2/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.boot.builder.SpringApplicationBuilder;
6 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
7 | import org.springframework.context.annotation.ComponentScan;
8 |
9 | @SpringBootApplication
10 | @ComponentScan("com.in28minutes.springboot.web")
11 | public class SpringBootFirstWebApplication extends SpringBootServletInitializer {
12 |
13 | @Override
14 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
15 | return application.sources(SpringBootFirstWebApplication.class);
16 | }
17 |
18 | public static void main(String[] args) {
19 | SpringApplication.run(SpringBootFirstWebApplication.class, args);
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/02-todo-web-application-h2/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-todo-web-application-h2/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-todo-web-application-h2/src/main/java/com/in28minutes/springboot/web/controller/TodoController.java:
--------------------------------------------------------------------------------
1 | package com.in28minutes.springboot.web.controller;
2 |
3 | import java.text.SimpleDateFormat;
4 | import java.util.Date;
5 |
6 | import javax.validation.Valid;
7 |
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.beans.propertyeditors.CustomDateEditor;
10 | import org.springframework.security.core.context.SecurityContextHolder;
11 | import org.springframework.security.core.userdetails.UserDetails;
12 | import org.springframework.stereotype.Controller;
13 | import org.springframework.ui.ModelMap;
14 | import org.springframework.validation.BindingResult;
15 | import org.springframework.web.bind.WebDataBinder;
16 | import org.springframework.web.bind.annotation.InitBinder;
17 | import org.springframework.web.bind.annotation.RequestMapping;
18 | import org.springframework.web.bind.annotation.RequestMethod;
19 | import org.springframework.web.bind.annotation.RequestParam;
20 |
21 | import com.in28minutes.springboot.web.model.Todo;
22 | import com.in28minutes.springboot.web.service.TodoRepository;
23 |
24 | @Controller
25 | public class TodoController {
26 |
27 | @Autowired
28 | TodoRepository repository;
29 |
30 | @InitBinder
31 | public void initBinder(WebDataBinder binder) {
32 | // Date - dd/MM/yyyy
33 | SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
34 | binder.registerCustomEditor(Date.class, new CustomDateEditor(
35 | dateFormat, false));
36 | }
37 |
38 | @RequestMapping(value = "/list-todos", method = RequestMethod.GET)
39 | public String showTodos(ModelMap model) {
40 | String name = getLoggedInUserName(model);
41 | model.put("todos", repository.findByUser(name));
42 | //model.put("todos", service.retrieveTodos(name));
43 | return "list-todos";
44 | }
45 |
46 | private String getLoggedInUserName(ModelMap model) {
47 | Object principal = SecurityContextHolder.getContext()
48 | .getAuthentication().getPrincipal();
49 |
50 | if (principal instanceof UserDetails) {
51 | return ((UserDetails) principal).getUsername();
52 | }
53 |
54 | return principal.toString();
55 | }
56 |
57 | @RequestMapping(value = "/add-todo", method = RequestMethod.GET)
58 | public String showAddTodoPage(ModelMap model) {
59 | model.addAttribute("todo", new Todo(0, getLoggedInUserName(model),
60 | "Default Desc", new Date(), false));
61 | return "todo";
62 | }
63 |
64 | @RequestMapping(value = "/delete-todo", method = RequestMethod.GET)
65 | public String deleteTodo(@RequestParam int id) {
66 |
67 | //if(id==1)
68 | //throw new RuntimeException("Something went wrong");
69 | repository.deleteById(id);
70 | //service.deleteTodo(id);
71 | return "redirect:/list-todos";
72 | }
73 |
74 | @RequestMapping(value = "/update-todo", method = RequestMethod.GET)
75 | public String showUpdateTodoPage(@RequestParam int id, ModelMap model) {
76 | Todo todo = repository.findById(id).get();
77 | //Todo todo = service.retrieveTodo(id);
78 | model.put("todo", todo);
79 | return "todo";
80 | }
81 |
82 | @RequestMapping(value = "/update-todo", method = RequestMethod.POST)
83 | public String updateTodo(ModelMap model, @Valid Todo todo,
84 | BindingResult result) {
85 |
86 | if (result.hasErrors()) {
87 | return "todo";
88 | }
89 |
90 | todo.setUser(getLoggedInUserName(model));
91 |
92 | repository.save(todo);
93 | //service.updateTodo(todo);
94 |
95 | return "redirect:/list-todos";
96 | }
97 |
98 | @RequestMapping(value = "/add-todo", method = RequestMethod.POST)
99 | public String addTodo(ModelMap model, @Valid Todo todo, BindingResult result) {
100 |
101 | if (result.hasErrors()) {
102 | return "todo";
103 | }
104 |
105 | todo.setUser(getLoggedInUserName(model));
106 | repository.save(todo);
107 | /*service.addTodo(getLoggedInUserName(model), todo.getDesc(), todo.getTargetDate(),
108 | false);*/
109 | return "redirect:/list-todos";
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/02-todo-web-application-h2/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-todo-web-application-h2/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-todo-web-application-h2/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.Configuration;
5 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
8 |
9 | @Configuration
10 | public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
11 | //Create User - in28Minutes/dummy
12 | @Autowired
13 | public void configureGlobalSecurity(AuthenticationManagerBuilder auth)
14 | throws Exception {
15 | auth.inMemoryAuthentication().withUser("in28minutes").password("{noop}dummy")
16 | .roles("USER", "ADMIN");
17 | }
18 |
19 | @Override
20 | protected void configure(HttpSecurity http) throws Exception {
21 | http.authorizeRequests().antMatchers("/login", "/h2-console/**").permitAll()
22 | .antMatchers("/", "/*todo*/**").access("hasRole('USER')").and()
23 | .formLogin();
24 |
25 | http.csrf().disable();
26 | http.headers().frameOptions().disable();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/02-todo-web-application-h2/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 user);
11 | }
--------------------------------------------------------------------------------
/02-todo-web-application-h2/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.h2.console.settings.web-allow-others=true
--------------------------------------------------------------------------------
/02-todo-web-application-h2/src/main/resources/data.sql:
--------------------------------------------------------------------------------
1 | insert into TODO
2 | values(10001, 'Learn Spring Boot', false, sysdate(), 'in28minutes');
3 | insert into TODO
4 | values(10002, 'Learn Angular JS', false, sysdate(), 'in28minutes');
5 | insert into TODO
6 | values(10003, 'Learn to Dance', false, sysdate(), 'in28minutes');
7 |
--------------------------------------------------------------------------------
/02-todo-web-application-h2/src/main/webapp/WEB-INF/jsp/common/footer.jspf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
10 |
11 |