Skip to content

Commit 90b045d

Browse files
author
gabriele.sisinna
committed
Add enum-based courses and configuration properties example
1 parent a43de3c commit 90b045d

20 files changed

Lines changed: 518 additions & 109 deletions

README.md

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ Full repo learning notes are in [docs/README.md](./docs/README.md).
3434
- JPA + H2 persistence
3535
- basic authentication with Spring Security
3636
- unit, repository, and integration tests
37+
- enums
38+
- `@ConfigurationProperties`
3739

3840
## Start here
3941

@@ -48,7 +50,8 @@ Read these files in order:
4850
7. `src/main/java/com/example/demo/spring/service/StudentService.java`
4951
8. `src/main/java/com/example/demo/spring/persistence/service/CourseService.java`
5052
9. `src/main/java/com/example/demo/spring/persistence/controller/CourseController.java`
51-
10. `src/test/java/com/example/demo/spring/persistence/controller/CourseControllerIntegrationTest.java`
53+
10. `src/main/java/com/example/demo/spring/config/AppLearningProperties.java`
54+
11. `src/test/java/com/example/demo/spring/persistence/controller/CourseControllerIntegrationTest.java`
5255

5356
## Package guide
5457

@@ -76,6 +79,8 @@ Read these files in order:
7679
- request and response models
7780
- `com.example.demo.spring.persistence`
7881
- validation, JPA, H2, and security examples
82+
- `com.example.demo.spring.config`
83+
- OpenAPI config and typed configuration properties
7984

8085
## Run the app
8186

@@ -142,19 +147,44 @@ Get secured courses with basic auth:
142147
curl -u student:password http://localhost:8080/api/courses
143148
```
144149

150+
Show typed configuration properties:
151+
152+
```bash
153+
curl http://localhost:8080/api/learning-info
154+
```
155+
145156
Create a secured database-backed course:
146157

147158
```bash
148159
curl -u student:password -X POST http://localhost:8080/api/courses \
149160
-H "Content-Type: application/json" \
150161
-d '{
151162
"title": "Spring Data JPA",
152-
"level": "intermediate",
163+
"level": "INTERMEDIATE",
153164
"durationInHours": 7,
154165
"published": true
155166
}'
156167
```
157168

169+
Update a course:
170+
171+
```bash
172+
curl -u student:password -X PUT http://localhost:8080/api/courses/1 \
173+
-H "Content-Type: application/json" \
174+
-d '{
175+
"title": "Updated Java Generics",
176+
"level": "ADVANCED",
177+
"durationInHours": 10,
178+
"published": false
179+
}'
180+
```
181+
182+
Delete a course:
183+
184+
```bash
185+
curl -u student:password -X DELETE http://localhost:8080/api/courses/2
186+
```
187+
158188
## Swagger and OpenAPI
159189

160190
After starting the app with `./gradlew bootRun`, open:
@@ -193,7 +223,7 @@ Different test layers in this repo:
193223

194224
- unit tests: small classes without Spring, such as `StudentTest` and `CourseServiceTest`
195225
- repository tests: JPA + H2 with a Spring Boot integration test, such as `CourseRepositoryTest`
196-
- integration tests: full Spring Boot + MockMvc, such as `StudentControllerTest` and `CourseControllerIntegrationTest`
226+
- integration tests: full Spring Boot + MockMvc, such as `StudentControllerTest`, `CourseControllerIntegrationTest`, and `LearningInfoControllerTest`
197227

198228
## GitHub CI
199229

@@ -226,9 +256,11 @@ It runs on every push and pull request, sets up Java 17, and executes:
226256
- Inheritance: `Person`, `LearningStudent`
227257
- Generics: `Box<T>`
228258
- Streams: `StudentAnalytics`
259+
- Enums: `CourseLevel`
229260
- Exceptions: `InvalidScoreException`, `StudentNotFoundException`
230261
- Annotations: `@LearningExample`, `@Service`, `@RestController`, `@RestControllerAdvice`, `@Entity`, `@Valid`
231262
- Dependency injection: `StudentController` gets `StudentService`, `StudentService` gets `InMemoryStudentRepository`
232263
- Validation: `CreateCourseRequest`
233264
- Persistence: `CourseEntity`, `CourseRepository`, H2
234265
- Security: HTTP basic auth for `/api/courses/**` with user `student` / `password`
266+
- Typed configuration: `AppLearningProperties` bound from `application.yml`

docs/java-basics.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,18 @@ Key idea:
159159
- generics let you write reusable classes while keeping type safety
160160
- `Box<String>` and `Box<Integer>` use the same class with different types
161161

162+
## Enums
163+
164+
Example:
165+
166+
- `spring/persistence/model/CourseLevel.java`
167+
168+
Key idea:
169+
170+
- enums model a fixed set of allowed values
171+
- they are safer than raw strings
172+
- they work well for states, levels, and categories
173+
162174
## Streams and lambdas
163175

164176
Example:

docs/spring-boot.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,19 @@ Flow:
107107
3. invalid input triggers an exception
108108
4. `ApiExceptionHandler` turns it into a clean error response
109109

110+
## Configuration properties
111+
112+
Main files:
113+
114+
- `AppLearningProperties`
115+
- `LearningInfoController`
116+
117+
Key idea:
118+
119+
- `@ConfigurationProperties` maps structured YAML into a typed Java object
120+
- this is cleaner than scattering config lookups through the code
121+
- the `/api/learning-info` endpoint makes the bound values visible at runtime
122+
110123
## Exception handling
111124

112125
Main example:
@@ -134,6 +147,7 @@ Key ideas:
134147

135148
- `@Entity` maps a class to a database table
136149
- a `JpaRepository` gives CRUD operations
150+
- `CourseLevel` enum keeps the `level` field restricted to valid values
137151
- H2 provides an in-memory database for easy learning
138152
- `data.sql` seeds example rows at startup
139153

0 commit comments

Comments
 (0)