Skip to content

Logging 2#26

Merged
jesperlarsson1910 merged 19 commits intomainfrom
logging-2
Jan 14, 2026
Merged

Logging 2#26
jesperlarsson1910 merged 19 commits intomainfrom
logging-2

Conversation

@jesperlarsson1910
Copy link
Copy Markdown

@jesperlarsson1910 jesperlarsson1910 commented Jan 14, 2026

Summary by CodeRabbit

  • New Features

    • Added persistent, database-backed application logging and broader runtime logging across components.
  • Bug Fixes

    • More informative logging and improved error handling and input validation across API, persistence, and UI paths.
  • Chores

    • Build configuration and logging setup updated; general formatting and cleanup applied.
  • Tests

    • Test setup extended to initialize additional repository components for broader coverage.

✏️ Tip: You can customize this high-level summary in your review settings.

Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
# Conflicts:
#	src/main/java/org/example/ItunesPlayList.java
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 14, 2026

Warning

Rate limit exceeded

@jesperlarsson1910 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 1 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between c72d3ac and 4c4edc0.

📒 Files selected for processing (4)
  • pom.xml
  • src/main/java/org/example/entity/LogEntry.java
  • src/main/java/org/example/logging/LoggingConnection.java
  • src/main/resources/log4j2.xml
📝 Walkthrough

Walkthrough

Adds Log4j2 and commons-dbcp2 to the build, configures a Log4j2 Console + JDBC appender, introduces SLF4J loggers across services and repositories, adds a LoggingConnectionFactory and LogEntry JPA entity, and includes minor interface, formatting, and test adjustments.

Changes

Cohort / File(s) Summary
Build & Logging config
pom.xml, src/main/resources/log4j2.xml
Adds Log4j dependencies and commons-dbcp2 to pom; adds Log4j2 config with Console and JDBC (app_logs) appenders.
DB Connection helper
src/main/java/org/example/logging/LoggingConnectionFactory.java
New public class exposing public static Connection getConnection() with hardcoded URL/credentials used by JDBC appender.
Persistence entity for logs
src/main/java/org/example/entity/LogEntry.java
New JPA entity LogEntry mapped to app_logs with id, level, message, errorDetails, timestamp and getters.
Services / UI with logging
src/main/java/org/example/DatabaseInitializer.java, src/main/java/org/example/ItunesApiClient.java, src/main/java/org/example/MyPod.java, src/main/java/org/example/ItunesPlayList.java
Add SLF4J loggers and logging calls in error/info/debug branches; minor GUI field finalization and onUpdateCallback addition.
Repository logging & validation
src/main/java/org/example/repo/PlaylistRepositoryImpl.java, src/main/java/org/example/repo/SongRepositoryImpl.java
Add SLF4J loggers, log on null/invalid inputs, standardize messages and log before throwing or returning empty lists.
Entity & interface cleanup
src/main/java/org/example/entity/DBObject.java, src/main/java/org/example/entity/Playlist.java, src/main/java/org/example/entity/Song.java, src/main/java/org/example/entity/Album.java
Remove explicit public modifiers from DBObject methods, make Playlist.songs final, and apply minor whitespace/formatting edits.
Misc config & tests
src/main/java/org/example/PersistenceManager.java, src/main/resources/ipod_style.css, src/test/java/org/example/RepoTest.java
Remove unused imports/extra brace in PersistenceManager, reformat CSS (no behavior change), initialize playlistRepo in test setup and minor formatting tweaks.

Sequence Diagram

sequenceDiagram
    participant App as Application (services/repos)
    participant SLF4J as SLF4J API
    participant L4J as Log4j2 Core
    participant JDBC as Log4j2 JDBC Appender
    participant Conn as LoggingConnectionFactory
    participant DB as Database (app_logs)
    participant Console as Console Appender

    App->>SLF4J: logger.error/info/debug(event)
    SLF4J->>L4J: forward LogEvent
    L4J->>Console: format & write to stdout
    L4J->>JDBC: prepare DB insert
    JDBC->>Conn: getConnection()
    Conn->>DB: open JDBC connection
    JDBC->>DB: INSERT INTO app_logs(...)
    DB-->>JDBC: ack
    L4J-->>SLF4J: event handled
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Poem

🐰 I hopped through code with ears held high,

I stitched soft logs that now explain why,
From SLF4J whispers to JDBC’s song,
App_logs collect each line all day long,
A carrot-cheer — small logs, proud and strong!

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Logging 2' is vague and does not clearly convey the specific nature or scope of the changes made in this pull request. Use a more descriptive title that summarizes the main objective, such as 'Add SLF4J logging integration with Log4j2 JDBC appender' or 'Implement comprehensive logging with database persistence'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/org/example/PersistenceManager.java (1)

10-12: Hardcoded credentials pose a security risk.

While these appear to be local development credentials, hardcoding database connection details (URL, username, password) is a security concern and makes configuration inflexible across environments. Consider externalizing these to environment variables or a configuration file.

String url = System.getenv("DB_URL");
String user = System.getenv("DB_USER");
String pass = System.getenv("DB_PASS");
🤖 Fix all issues with AI agents
In `@src/main/java/org/example/logging/LoggingConnectionFactory.java`:
- Around line 9-11: The constants URL, USER, and PASSWORD in
LoggingConnectionFactory are hardcoded credentials; change them to be read from
external configuration (e.g., environment variables or system properties)
instead of literals. Replace the static PASSWORD/USER/URL usage with lookups
like System.getenv("DB_PASSWORD") or System.getProperty("db.password") (and
similar keys for USER/URL), provide sensible defaults or fail-fast behavior if
missing, and update any code that references URL/USER/PASSWORD to use the new
retrieval methods so credentials are not stored in source.

In `@src/main/java/org/example/MyPod.java`:
- Around line 807-809: The catch block in MyPod.java currently calls
logger.error("Kunde inte ladda data: {}", e.getMessage()) which drops the
exception stack trace; update the catch to pass the exception object to the
logger (e.g., logger.error("Kunde inte ladda data: {}", e.getMessage(), e) or
logger.error("Kunde inte ladda data", e)) so the full stack trace is preserved
when logging the error in the MyPod class catch block.
- Around line 778-779: In the catch block in MyPod (the catch(Exception e)
handling preview playback), change the logger.error call to include the
exception object so the full stack trace is preserved; pass the exception
variable e as the throwable argument to logger.error (instead of only
e.getMessage()) so the log records both the message and stack trace.
- Line 580: The log call uses e.getMessage() which drops the stack trace; change
the logger.error invocation in MyPod (the failing refresh playlists log) to pass
the Throwable as the last parameter so the stack trace is preserved, e.g.
replace the current logger.error("Failed to refresh playlists: {}",
e.getMessage()); with a call that includes the exception object as the last
argument (either logger.error("Failed to refresh playlists", e); or
logger.error("Failed to refresh playlists: {}", e.getMessage(), e);).

In `@src/main/java/org/example/repo/PlaylistRepositoryImpl.java`:
- Around line 90-93: The log message contains a typo—`insongInPlaylist`—but the
method is named isSongInPlaylist; update the logger call in the null-check
inside isSongInPlaylist to reference the correct method name (e.g.,
"isSongInPlaylist: playlist or song is null") so the message matches the actual
method and aids debugging.
- Around line 78-81: The log message in PlaylistRepositoryImpl incorrectly
references the method name "findsongsInPlaylist" (lowercase 's'); update the
logger.error call inside findSongsInPlaylist to use the correct method name
"findSongsInPlaylist" so logs match the actual method, e.g., change the message
string passed to logger.error to "findSongsInPlaylist: playlist is null" and
leave the IllegalArgumentException as-is.

In `@src/main/resources/log4j2.xml`:
- Around line 15-20: The Root logger is set to "error" which will suppress
WARN/INFO/DEBUG and the JDBC appender (DBAppender) could break logging if DB is
unreachable; change the Root logger's level to a less restrictive default (e.g.,
"info" or "warn") or make the root level configurable via a property, and update
the DBAppender/JDBC appender configuration to be resilient by adding
ignoreExceptions="true" and/or wrapping it with a Failover appender that points
to the Console appender as a fallback so logging continues if the DBAppender
fails.
🧹 Nitpick comments (7)
src/main/java/org/example/entity/LogEntry.java (1)

6-25: Entity lacks accessors - add getters if logs need to be queried.

The entity is correctly mapped to app_logs and column names are properly quoted for MySQL reserved words. However, if you plan to query logs via JPA (not just write via the JDBC appender), you'll need getter methods. The JDBC appender writes directly via SQL and doesn't use this entity.

♻️ Optional: Add getters for query access
public Long getId() { return id; }
public String getLevel() { return level; }
public String getMessage() { return message; }
public String getErrorDetails() { return errorDetails; }
public LocalDateTime getTimestamp() { return timestamp; }
pom.xml (1)

84-108: Consider using a property for the Log4j version to simplify maintenance.

Log4j 2.25.3 is the latest official release and all dependencies are correctly aligned. To avoid repetition across the four Log4j dependencies and simplify future version updates, define a version property:

♻️ Suggested property definition

Add to <properties>:

<log4j.version>2.25.3</log4j.version>

Then use ${log4j.version} in all Log4j dependencies.

src/main/java/org/example/repo/SongRepositoryImpl.java (1)

54-57: Consider using DEBUG level for expected null/blank inputs.

These null/blank checks appear to be expected code paths rather than exceptional situations. Using INFO level will generate noise in production logs. DEBUG would be more appropriate for tracing purposes.

Additionally, List.of() is more idiomatic for returning an immutable empty list.

Suggested change for one of the methods
     public List<Song> findByArtist(Artist artist) {
         if (artist == null) {
-            logger.info("findByArtist: artist is null");
-            return new ArrayList<>();
+            logger.debug("findByArtist: artist is null");
+            return List.of();
         }

Also applies to: 76-79, 98-101

src/main/java/org/example/ItunesApiClient.java (2)

66-68: Consider using WARN or DEBUG for null artistName.

A null artistName from the API is a data quality issue, not an application error. Using ERROR level suggests something is broken in the application. Since the code gracefully skips these records, WARN (to highlight data issues) or DEBUG (if this is expected) would be more appropriate.

Suggested change
             if (song.artistName() == null) {
-                logger.error("searchSongs: artistName is null");
+                logger.warn("searchSongs: skipping result with null artistName");
                 continue;
             }

55-57: Consider DEBUG level for "no results" scenario.

An empty result set from a search is expected application behavior, not something that typically warrants INFO-level logging. Using DEBUG would reduce log noise in production.

src/main/java/org/example/logging/LoggingConnectionFactory.java (1)

14-18: Explicit driver loading is unnecessary for modern JDBC.

Since JDBC 4.0 (Java 6+), drivers register themselves via ServiceLoader. The Class.forName() call can be removed.

Simplified implementation
     public static Connection getConnection() throws SQLException {
-        try {
-            Class.forName("com.mysql.cj.jdbc.Driver"); // Ensure driver is loaded
-        } catch (ClassNotFoundException e) {
-            throw new SQLException("MySQL JDBC Driver not found", e);
-        }
         return DriverManager.getConnection(URL, USER, PASSWORD);
     }
src/main/java/org/example/MyPod.java (1)

43-44: Logger field placement is unconventional.

The logger is declared at line 94 after instance fields. Convention is to place static final logger fields at the top of the class, right after the class declaration or after static constants. This improves readability and consistency.

Also applies to: 94-95

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c602ad8 and dbf293a.

📒 Files selected for processing (17)
  • pom.xml
  • src/main/java/org/example/DatabaseInitializer.java
  • src/main/java/org/example/ItunesApiClient.java
  • src/main/java/org/example/ItunesPlayList.java
  • src/main/java/org/example/MyPod.java
  • src/main/java/org/example/PersistenceManager.java
  • src/main/java/org/example/entity/Album.java
  • src/main/java/org/example/entity/DBObject.java
  • src/main/java/org/example/entity/LogEntry.java
  • src/main/java/org/example/entity/Playlist.java
  • src/main/java/org/example/entity/Song.java
  • src/main/java/org/example/logging/LoggingConnectionFactory.java
  • src/main/java/org/example/repo/PlaylistRepositoryImpl.java
  • src/main/java/org/example/repo/SongRepositoryImpl.java
  • src/main/resources/ipod_style.css
  • src/main/resources/log4j2.xml
  • src/test/java/org/example/RepoTest.java
🧰 Additional context used
🪛 Biome (2.1.2)
src/main/resources/ipod_style.css

[error] 56-56: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 57-57: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 61-61: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 62-62: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 66-66: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 67-67: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 71-71: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 72-72: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 130-130: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 131-131: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 135-135: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 136-136: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 141-141: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 198-198: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 220-220: Unknown property is not allowed.

See CSS Specifications and browser specific properties for more details.
To resolve this issue, replace the unknown property with a valid CSS property.

(lint/correctness/noUnknownProperty)


[error] 220-220: Unexpected unknown function: innershadow

Use a known function instead.
See MDN web docs for more details.

(lint/correctness/noUnknownFunction)


[error] 221-221: Unexpected unknown function: innershadow

Use a known function instead.
See MDN web docs for more details.

(lint/correctness/noUnknownFunction)


[error] 222-222: Unexpected unknown function: dropshadow

Use a known function instead.
See MDN web docs for more details.

(lint/correctness/noUnknownFunction)

🔇 Additional comments (26)
src/main/java/org/example/entity/DBObject.java (1)

5-11: LGTM! Removing redundant public modifiers from interface methods is valid.

Interface methods in Java are implicitly public, so removing the explicit keyword is a clean stylistic improvement with no behavioral change.

Note: The AI summary incorrectly states these methods become "package-private" — they remain public as per Java language specification.

src/main/java/org/example/entity/Album.java (1)

8-10: Formatting changes look fine.

These are whitespace and formatting adjustments only, with no logic changes. The existing System.err.println calls (lines 175, 196, 210) could be migrated to use the new SLF4J logging infrastructure being added in this PR for consistency, but that can be addressed separately.

Also applies to: 68-68, 149-178, 185-186

src/main/java/org/example/PersistenceManager.java (1)

27-27: Import cleanup acknowledged.

The removal of unused imports is a good hygiene improvement.

pom.xml (1)

120-126: Annotation processor version should match the dependency version.

Good that the annotation processor path uses the same version (2.25.3) as the dependency. If you adopt the suggested version property, update this reference too.

src/main/resources/log4j2.xml (1)

3-10: JDBC appender configuration aligns with LogEntry entity.

The column mappings (level, message, error_details, timestamp) correspond correctly to the LogEntry entity fields mapped to the app_logs table.

src/main/java/org/example/ItunesPlayList.java (4)

18-19: LGTM! Logger setup follows SLF4J best practices.

The logger is correctly defined as private static final with the class-specific factory method.

Also applies to: 28-28


51-59: Good improvement: Making GUI component fields final.

Declaring allPlaylistList, songTable, and sourceList as final ensures these references cannot be accidentally reassigned, improving code safety.


346-349: LGTM! Error handling with logging is well implemented.

The pattern of logging the error with the full exception stack trace while also displaying a user-friendly alert is appropriate for GUI applications.


454-456: Consistent error logging pattern applied throughout.

The error logging at these locations maintains the same good pattern: logging with exception context and displaying user alerts.

Also applies to: 512-514

src/main/java/org/example/entity/Song.java (1)

35-41: Formatting improvement only - no concerns.

The whitespace adjustment in the constructor parameter list improves readability without any semantic change.

src/main/java/org/example/entity/Playlist.java (2)

19-20: Good practice: Making the collection field final.

Declaring songs as final prevents accidental reassignment of the collection reference while still allowing Hibernate to manage the collection contents. This is safe with modern Hibernate versions.


22-23: Formatting changes only - no concerns.

The constructor and getter reformatting improves readability without changing behavior.

Also applies to: 45-47

src/main/resources/ipod_style.css (3)

55-73: JavaFX CSS formatting changes - static analysis warnings are false positives.

The Biome warnings about "unknown properties" like -fx-translate-y, -fx-translate-x, and -fx-font-size are false positives. These are valid JavaFX CSS properties, not standard web CSS. JavaFX has its own CSS specification with -fx- prefixed properties.


129-143: Formatting improvements to LCD and list styles.

The multi-line formatting improves readability. The -fx-font-family and -fx-fill properties flagged by static analysis are valid JavaFX CSS properties.


198-222: Progress bar gradient styling reformatted.

The innershadow() and dropshadow() functions flagged by Biome are valid JavaFX CSS functions (not standard CSS), used for creating depth effects on UI components. The multi-line gradient formatting improves maintainability.

src/test/java/org/example/RepoTest.java (1)

46-50: Good fix: Initializing the previously declared playlistRepo field.

The playlistRepo field was declared at line 21 but never initialized. This change properly initializes it alongside the other repositories, enabling playlist-related test coverage.

src/main/java/org/example/DatabaseInitializer.java (1)

8-9: LGTM!

The SLF4J logging is properly implemented with correct logger declaration pattern and appropriate error-level logging. Including the exception as the third parameter ensures the stack trace is captured.

Also applies to: 15-16, 66-67

src/main/java/org/example/repo/PlaylistRepositoryImpl.java (9)

8-9: LGTM!

Standard SLF4J logger setup following best practices with private static final declaration.

Also applies to: 17-18


27-30: LGTM!

Logging for null argument validation is appropriate and consistent.


53-72: LGTM!

Good use of parameterized logging with placeholder {} to avoid string concatenation overhead. Using EntityNotFoundException for not-found cases is appropriate in JPA context.


105-108: LGTM!

Appropriate validation and logging for null/empty name parameter.


116-127: LGTM!

Consistent logging pattern for both validation failures and not-found scenarios.


132-134: LGTM!


144-160: LGTM!

Comprehensive logging coverage for all failure paths in the method.


167-184: LGTM!

Good logging coverage including the loop iteration for individual song lookup failures.


192-210: LGTM!

Consistent logging pattern matching the addSong method structure.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +9 to +11
private static final String URL = "jdbc:mysql://localhost:3306/myPodDB";
private static final String USER = "user";
private static final String PASSWORD = "pass";
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Hardcoded database credentials are a security risk.

Storing credentials directly in source code exposes them in version control history and prevents environment-specific configuration. This is a common compliance violation (e.g., OWASP, SOC2).

Externalize credentials using one of these approaches:

  • Environment variables: System.getenv("DB_PASSWORD")
  • System properties: System.getProperty("db.password")
  • Configuration file excluded from version control
Example using environment variables
 public class LoggingConnectionFactory {

-    private static final String URL = "jdbc:mysql://localhost:3306/myPodDB";
-    private static final String USER = "user";
-    private static final String PASSWORD = "pass";
+    private static final String URL = System.getenv("MYPOD_DB_URL");
+    private static final String USER = System.getenv("MYPOD_DB_USER");
+    private static final String PASSWORD = System.getenv("MYPOD_DB_PASSWORD");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private static final String URL = "jdbc:mysql://localhost:3306/myPodDB";
private static final String USER = "user";
private static final String PASSWORD = "pass";
private static final String URL = System.getenv("MYPOD_DB_URL");
private static final String USER = System.getenv("MYPOD_DB_USER");
private static final String PASSWORD = System.getenv("MYPOD_DB_PASSWORD");
🤖 Prompt for AI Agents
In `@src/main/java/org/example/logging/LoggingConnectionFactory.java` around lines
9 - 11, The constants URL, USER, and PASSWORD in LoggingConnectionFactory are
hardcoded credentials; change them to be read from external configuration (e.g.,
environment variables or system properties) instead of literals. Replace the
static PASSWORD/USER/URL usage with lookups like System.getenv("DB_PASSWORD") or
System.getProperty("db.password") (and similar keys for USER/URL), provide
sensible defaults or fail-fast behavior if missing, and update any code that
references URL/USER/PASSWORD to use the new retrieval methods so credentials are
not stored in source.

Comment on lines +15 to +20
<Loggers>
<Root level="error">
<AppenderRef ref="DBAppender"/>
<AppenderRef ref="Console"/>
</Root>
</Loggers>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Root log level set to error may be too restrictive.

With the root logger at error level, only ERROR and FATAL messages will be logged. This means WARN, INFO, and DEBUG messages will be silently discarded. Consider using info or warn for production, or make the level configurable.

Additionally, if the database connection fails, the JDBC appender could cause issues. Consider adding a Failover appender or at minimum an ignoreExceptions="true" attribute on the JDBC appender.

🤖 Prompt for AI Agents
In `@src/main/resources/log4j2.xml` around lines 15 - 20, The Root logger is set
to "error" which will suppress WARN/INFO/DEBUG and the JDBC appender
(DBAppender) could break logging if DB is unreachable; change the Root logger's
level to a less restrictive default (e.g., "info" or "warn") or make the root
level configurable via a property, and update the DBAppender/JDBC appender
configuration to be resilient by adding ignoreExceptions="true" and/or wrapping
it with a Failover appender that points to the Console appender as a fallback so
logging continues if the DBAppender fails.

jesperlarsson1910 and others added 2 commits January 14, 2026 22:47
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/main/java/org/example/MyPod.java`:
- Around line 777-779: The logger.error call in the catch block of the
playPreview method uses the wrong text and punctuation; update the message
passed to logger.error in the catch for playPreview to read "playPreview: Could
not play preview" (matching the method name and removing the trailing colon
inconsistency) while continuing to pass the exception object (i.e., update the
string only in the logger.error call in the playPreview catch block).
♻️ Duplicate comments (1)
src/main/java/org/example/logging/LoggingConnectionFactory.java (1)

9-11: Hardcoded credentials remain unaddressed.

This security concern was raised in a previous review. Credentials should be externalized via environment variables or configuration files.

🧹 Nitpick comments (3)
src/main/java/org/example/logging/LoggingConnectionFactory.java (1)

13-16: Consider connection pooling for production use.

Each call creates a new database connection. If log volume is high, this could exhaust database connections or degrade performance. Consider using a connection pool (e.g., HikariCP) or verify that the Log4j2 JDBC appender manages connection reuse internally.

src/main/java/org/example/repo/SongRepositoryImpl.java (1)

54-57: Defensive null checks with logging are appropriate.

The early returns for null/blank inputs prevent unnecessary database queries. Consider using List.of() instead of new ArrayList<>() for immutable empty lists, which avoids object allocation.

♻️ Optional: Use immutable empty list
     if (artist == null) {
         logger.debug("findByArtist: artist is null");
-        return new ArrayList<>();
+        return List.of();
     }

Apply similarly to findByAlbum and findByGenre.

Also applies to: 76-79, 98-101

src/main/java/org/example/entity/LogEntry.java (1)

3-3: Prefer explicit imports over wildcards.

Wildcard imports can cause ambiguity and make it harder to track dependencies. Consider importing specific annotations.

♻️ Explicit imports
-import jakarta.persistence.*;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 95a1849 and 28a3bd9.

📒 Files selected for processing (7)
  • src/main/java/org/example/ItunesApiClient.java
  • src/main/java/org/example/MyPod.java
  • src/main/java/org/example/entity/LogEntry.java
  • src/main/java/org/example/logging/LoggingConnectionFactory.java
  • src/main/java/org/example/repo/PlaylistRepositoryImpl.java
  • src/main/java/org/example/repo/SongRepositoryImpl.java
  • src/main/resources/log4j2.xml
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/resources/log4j2.xml
  • src/main/java/org/example/repo/PlaylistRepositoryImpl.java
🔇 Additional comments (9)
src/main/java/org/example/repo/SongRepositoryImpl.java (1)

7-8: LGTM!

Standard SLF4J logger setup following established patterns in the codebase.

Also applies to: 15-16

src/main/java/org/example/ItunesApiClient.java (3)

6-7: LGTM!

Standard SLF4J logger initialization.

Also applies to: 21-22


46-50: LGTM!

Logging the error before throwing the exception aids debugging. The status code provides useful context without exposing sensitive response body data.


55-57: LGTM!

Appropriate use of log levels: debug for expected empty results, warn for unexpected null data that indicates a potential API response anomaly.

Also applies to: 66-69

src/main/java/org/example/entity/LogEntry.java (1)

6-35: Entity is read-only; add setters if JPA-based writes are needed later.

The entity lacks setters and a no-arg constructor (the implicit default constructor exists, but setters are missing). Since the Log4j2 JDBC appender writes directly to the app_logs table bypassing JPA, this works for read-only access. If you later need to persist LogEntry via JPA, you'll need to add setters or use field-based access with reflection.

src/main/java/org/example/MyPod.java (4)

43-44: LGTM!

Standard SLF4J logger setup following best practices with private static final field declaration.

Also applies to: 55-56


146-148: LGTM!

INFO level is acceptable for optional CSS loading. Since missing CSS is a non-critical condition, not including the stack trace here is reasonable.


578-580: LGTM!

Exception object is now properly passed to preserve the stack trace, addressing the previous review feedback.


806-808: LGTM!

Exception object is properly passed to preserve the stack trace, addressing the previous review feedback.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines 777 to 779
} catch (Exception e) {
System.err.println("Could not play preview: " + e.getMessage());
logger.error("playReview: Could not play preview:", e);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Typo in log message: "playReview" should be "playPreview".

The method name is playPreview but the log message incorrectly says "playReview". Also, the trailing colon is inconsistent with other error messages in this file.

Suggested fix
-            logger.error("playReview: Could not play preview:", e);
+            logger.error("playPreview: Could not play preview", e);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (Exception e) {
System.err.println("Could not play preview: " + e.getMessage());
logger.error("playReview: Could not play preview:", e);
}
} catch (Exception e) {
logger.error("playPreview: Could not play preview", e);
}
🤖 Prompt for AI Agents
In `@src/main/java/org/example/MyPod.java` around lines 777 - 779, The
logger.error call in the catch block of the playPreview method uses the wrong
text and punctuation; update the message passed to logger.error in the catch for
playPreview to read "playPreview: Could not play preview" (matching the method
name and removing the trailing colon inconsistency) while continuing to pass the
exception object (i.e., update the string only in the logger.error call in the
playPreview catch block).

Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
@jesperlarsson1910 jesperlarsson1910 merged commit 34063b1 into main Jan 14, 2026
2 checks passed
@jesperlarsson1910 jesperlarsson1910 deleted the logging-2 branch January 14, 2026 22:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant