Skip to content

Commit cea352a

Browse files
authored
feat: adds lesson_25 homework (#777)
* feat: adds lesson_25 homework Signed-off-by: Anthony D. Mays <anthony@morganlatimer.com> * chore: renames lesson28 wording to lesson25 Signed-off-by: Anthony D. Mays <anthony@morganlatimer.com> * chore: adds pr checks for lesson_25 Signed-off-by: Anthony D. Mays <anthony@morganlatimer.com> * chore: fixes build check description Signed-off-by: Anthony D. Mays <anthony@morganlatimer.com> --------- Signed-off-by: Anthony D. Mays <anthony@morganlatimer.com>
1 parent d63ac92 commit cea352a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+3191
-1
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Check Lesson 25 Java Pull Request
2+
3+
on:
4+
pull_request:
5+
branches: [ "main" ]
6+
paths:
7+
- "lesson_25/db/**"
8+
9+
jobs:
10+
build:
11+
12+
runs-on: ubuntu-latest
13+
permissions:
14+
contents: read
15+
pull-requests: write
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Set up JDK
21+
uses: actions/setup-java@v4
22+
with:
23+
java-version: '21'
24+
distribution: 'temurin'
25+
26+
- name: Build Lesson 26 with Java
27+
working-directory: ./lesson_25/db
28+
run: ./gradlew check

lesson_25/README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,27 @@ Please review the following resources before lecture:
1313

1414
## Homework
1515

16-
- TODO(anthonydmays): Add more information.
16+
- [ ] Complete [Loading the Library, Part II](#loading-the-library-part-ii) assignment.
17+
18+
19+
### Loading The Library, Part II
20+
21+
Instead of loading our library data from JSON or CSV files as we did in [lesson_10](/lesson_10/), we now want to load data from a proper database. A new implementation of the `LibraryDbDataLoader` data loader has been provided to accomplish this task and is now the [default data loader][library-app] for the app.
22+
23+
To build familiarity in working with databases, you are charged with the following tasks:
24+
25+
* Write a `.sql` script file that queries the following data. Use a unique name for your file and store it in the [queries][queries-dir] directory of the resources folder.
26+
* A `SELECT` query that returns the counts of media items by type.
27+
* A `SELECT` query that returns the sum of total pages checked out by guests.
28+
* A `SELECT` query that shows all 5 guests and any corresponding records in the `checked_out_items` table.
29+
* Add a new table called `library_users` to the [SQLite database][sqlite-db] that stores a user's id (UUID formatted string), email, first name, last name, and a password (bcrypt encoded string). Add a model and repository that loads the users into the LibraryDataModel (see `LibraryGuestModel` and `LibraryGuestRepository` as examples). Populate the database with a few users.
30+
31+
As before, you can run the app from the console using the following command:
32+
33+
```bash
34+
./gradlew run --console=plain
35+
```
36+
37+
[queries-dir]: ./db/db_app/src/main/resources/queries/
38+
[sqlite-db]: ./db/db_app/src/main/resources/sqlite/
39+
[library-app]: ./db/db_app/src/main/java/com/codedifferently/lesson25/cli/LibraryApp.java#L26

lesson_25/createdb/createdb.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import os
2+
import pandas as pd
3+
import numpy as np
4+
import sqlite3
5+
6+
# Step 1: Load the CSV file into a pandas DataFrame
7+
media_items_df = pd.read_csv('/workspaces/code-society-25-2/lesson_12/io/io_app/src/main/resources/csv/media_items.csv')
8+
guests_df = pd.read_csv('/workspaces/code-society-25-2/lesson_12/io/io_app/src/main/resources/csv/guests.csv')
9+
checked_out_items_df = pd.read_csv('/workspaces/code-society-25-2/lesson_12/io/io_app/src/main/resources/csv/checked_out_items.csv')
10+
checked_out_items_df['due_date'] = pd.to_datetime(checked_out_items_df['due_date']).values.astype(np.int64)
11+
12+
# Step 2: Create a connection to the SQLite database
13+
# Note: This will create the database file if it doesn't exist already
14+
os.makedirs('/workspaces/code-society-25-2/lesson_25/db/db_app/src/main/resources/sqlite/', exist_ok=True)
15+
conn = sqlite3.connect('../db/db_app/src/main/resources/sqlite/data.db')
16+
17+
# Step 3: Write the DataFrame to the SQLite database
18+
media_items_df.to_sql('media_items', conn, if_exists='replace', index=False)
19+
guests_df.to_sql('guests', conn, if_exists='replace', index=False)
20+
checked_out_items_df.to_sql('checked_out_items', conn, if_exists='replace', index=False)
21+
22+
# Don't forget to close the connection
23+
conn.close()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pandas

lesson_25/db/.gitattributes

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#
2+
# https://help.github.com/articles/dealing-with-line-endings/
3+
#
4+
# Linux start script should use lf
5+
/gradlew text eol=lf
6+
7+
# These are Windows script files and should use crlf
8+
*.bat text eol=crlf
9+

lesson_25/db/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Ignore Gradle project-specific cache directory
2+
.gradle
3+
4+
# Ignore Gradle build output directory
5+
build
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
plugins {
2+
// Apply the application plugin to add support for building a CLI application in Java.
3+
application
4+
eclipse
5+
id("com.diffplug.spotless") version "6.25.0"
6+
id("org.springframework.boot") version "3.4.0"
7+
id("com.adarshr.test-logger") version "4.0.0"
8+
}
9+
10+
apply(plugin = "io.spring.dependency-management")
11+
12+
repositories {
13+
// Use Maven Central for resolving dependencies.
14+
mavenCentral()
15+
}
16+
17+
dependencies {
18+
// Use JUnit Jupiter for testing.
19+
testImplementation("com.codedifferently.instructional:instructional-lib")
20+
testImplementation("org.junit.jupiter:junit-jupiter:5.11.3")
21+
testImplementation("org.springframework.boot:spring-boot-starter-test")
22+
testImplementation("org.assertj:assertj-core:3.26.3")
23+
testImplementation("at.favre.lib:bcrypt:0.10.2")
24+
testCompileOnly("org.projectlombok:lombok:1.18.38")
25+
testAnnotationProcessor("org.projectlombok:lombok:1.18.38")
26+
27+
// This dependency is used by the application.
28+
implementation("com.codedifferently.instructional:instructional-lib")
29+
implementation("com.google.guava:guava:33.3.1-jre")
30+
implementation("com.google.code.gson:gson:2.11.0")
31+
implementation("commons-cli:commons-cli:1.6.0")
32+
implementation("org.springframework.boot:spring-boot-starter")
33+
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
34+
implementation("com.fasterxml.jackson.core:jackson-databind:2.13.0")
35+
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.12.3")
36+
implementation("com.opencsv:opencsv:5.9")
37+
implementation("org.apache.commons:commons-csv:1.10.0")
38+
implementation("org.xerial:sqlite-jdbc:3.36.0")
39+
implementation("org.hibernate.orm:hibernate-community-dialects:6.2.7.Final")
40+
compileOnly("org.projectlombok:lombok:1.18.38")
41+
annotationProcessor("org.projectlombok:lombok:1.18.38")
42+
}
43+
44+
application {
45+
// Define the main class for the application.
46+
mainClass.set("com.codedifferently.lesson25.Lesson25")
47+
}
48+
49+
tasks.named<JavaExec>("run") {
50+
standardInput = System.`in`
51+
}
52+
53+
tasks.named<Test>("test") {
54+
// Use JUnit Platform for unit tests.
55+
useJUnitPlatform()
56+
}
57+
58+
59+
configure<com.diffplug.gradle.spotless.SpotlessExtension> {
60+
61+
format("misc", {
62+
// define the files to apply `misc` to
63+
target("*.gradle", ".gitattributes", ".gitignore")
64+
65+
// define the steps to apply to those files
66+
trimTrailingWhitespace()
67+
indentWithTabs() // or spaces. Takes an integer argument if you don't like 4
68+
endWithNewline()
69+
})
70+
71+
java {
72+
// don't need to set target, it is inferred from java
73+
74+
// apply a specific flavor of google-java-format
75+
googleJavaFormat()
76+
// fix formatting of type annotations
77+
formatAnnotations()
78+
}
79+
}

lesson_25/db/db_app/lombok.config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# This file is generated by the 'io.freefair.lombok' Gradle plugin
2+
config.stopBubbling = true
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.codedifferently.lesson25;
2+
3+
import com.codedifferently.lesson25.cli.LibraryApp;
4+
import org.springframework.beans.factory.annotation.Autowired;
5+
import org.springframework.boot.CommandLineRunner;
6+
import org.springframework.boot.SpringApplication;
7+
import org.springframework.boot.autoconfigure.SpringBootApplication;
8+
import org.springframework.context.annotation.Configuration;
9+
10+
@Configuration
11+
@SpringBootApplication(scanBasePackages = "com.codedifferently")
12+
public class Lesson25 implements CommandLineRunner {
13+
14+
@Autowired private LibraryApp libraryApp;
15+
16+
public static void main(String[] args) {
17+
var application = new SpringApplication(Lesson25.class);
18+
application.run(args);
19+
}
20+
21+
@Override
22+
public void run(String... args) throws Exception {
23+
// Don't run as an app if we're running as a JUnit test.
24+
if (isJUnitTest()) {
25+
return;
26+
}
27+
28+
libraryApp.run(args);
29+
}
30+
31+
private static boolean isJUnitTest() {
32+
for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
33+
if (element.getClassName().startsWith("org.junit.")) {
34+
return true;
35+
}
36+
}
37+
return false;
38+
}
39+
}

0 commit comments

Comments
 (0)