Skip to content

refactor(config): remove redundant Spring Boot config and fix injection patterns#314

Merged
balazs-szucs merged 3 commits intogrimmory-tools:developfrom
balazs-szucs:refactor/cleanup-redundant-config
Apr 3, 2026
Merged

refactor(config): remove redundant Spring Boot config and fix injection patterns#314
balazs-szucs merged 3 commits intogrimmory-tools:developfrom
balazs-szucs:refactor/cleanup-redundant-config

Conversation

@balazs-szucs
Copy link
Copy Markdown
Member

@balazs-szucs balazs-szucs commented Mar 31, 2026

Description

Linked Issue: Fixes #

Changes

  • Delete TransactionConfig (Spring Boot auto-configures JpaTransactionManager)
  • Delete MultipartConfig (replaced with spring.servlet.multipart.* properties)
  • Delete BeanConfig (RestTemplate moved to RestClientConfig, WS stats to WebSocketConfig)
  • Remove duplicate @EnableScheduling from TaskSchedulerConfig
  • Fix @ConfigurationProperties: remove @component from AppProperties, change @configuration to @ConfigurationProperties on BookmarkProperties
  • Move RestTemplate bean to RestClientConfig
  • Add WS stats suppression to WebSocketConfig via ApplicationReadyEvent
  • Remove @Autowired from KepubConversionService, GoogleParser, HardcoverBookSearchService (single-constructor injection)
  • Remove redundant two-arg constructor from GoogleParser
  • Fix CbxReaderService pre-existing compile error (transferEntryTo)

Summary by CodeRabbit

  • New Features

    • Enabled multipart file uploads with 1024 MB limits.
    • Added default metadata persistence settings for audiobooks (disabled, 250 MB max).
  • Chores

    • Consolidated configuration property binding and simplified dependency injection across services.
    • Reworked HTTP client/rest template setup and removed a few legacy configuration beans.
    • Adjusted WebSocket broker stats logging behavior and scheduling/bootstrap configuration.

…on patterns

- Delete TransactionConfig (Spring Boot auto-configures JpaTransactionManager)
- Delete MultipartConfig (replaced with spring.servlet.multipart.* properties)
- Delete BeanConfig (RestTemplate moved to RestClientConfig, WS stats to WebSocketConfig)
- Remove duplicate @EnableScheduling from TaskSchedulerConfig
- Fix @ConfigurationProperties: remove @component from AppProperties, change
  @configuration to @ConfigurationProperties on BookmarkProperties
- Move RestTemplate bean to RestClientConfig
- Add WS stats suppression to WebSocketConfig via ApplicationReadyEvent
- Remove @Autowired from KepubConversionService, GoogleParser,
  HardcoverBookSearchService (single-constructor injection)
- Remove redundant two-arg constructor from GoogleParser
- Fix CbxReaderService pre-existing compile error (transferEntryTo)
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6fe32856-4c43-4438-a63b-0e9492b3af42

📥 Commits

Reviewing files that changed from the base of the PR and between 256e68d and 75df78b.

📒 Files selected for processing (2)
  • booklore-api/src/main/java/org/booklore/config/RestClientConfig.java
  • booklore-api/src/main/java/org/booklore/service/appsettings/SettingPersistenceHelper.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • booklore-api/src/main/java/org/booklore/config/RestClientConfig.java
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test Suite / Backend Tests
  • GitHub Check: Test Suite / Frontend Tests
  • GitHub Check: Analyze (java-kotlin)
🧰 Additional context used
📓 Path-based instructions (1)
booklore-api/src/**/*.java

📄 CodeRabbit inference engine (AGENTS.md)

booklore-api/src/**/*.java: Use 4-space indentation in Java files and match surrounding Java style
Prefer constructor injection via Lombok patterns already used in the codebase. Do not introduce @Autowired field injection
Use MapStruct for entity/DTO mapping

Files:

  • booklore-api/src/main/java/org/booklore/service/appsettings/SettingPersistenceHelper.java
🔀 Multi-repo context grimmory-tools/grimmory-docs

grimmory-tools/grimmory-docs

  • docs/tools/global-preferences.md: mentions "file upload limits" and global settings for file uploads (documentation for multipart / upload limits) — may need updating to reflect new application.yaml behavior [::grimmory-tools/grimmory-docs::docs/tools/global-preferences.md:1-40].

  • No occurrences found for AppProperties, BookmarkProperties, TransactionConfig, MultipartConfig, BeanConfig, RestClientConfig, WebSocketConfig, KepubConversionService, GoogleParser, HardcoverBookSearchService, CbxReaderService, spring.servlet.multipart.enabled, max-file-size, or max-request-size in this repo (search output returned no hits) [::grimmory-tools/grimmory-docs::search].

🔇 Additional comments (1)
booklore-api/src/main/java/org/booklore/service/appsettings/SettingPersistenceHelper.java (1)

262-272: LGTM!

The audiobook settings addition follows the established pattern for other formats (epub, pdf, cbx) with consistent default values (enabled(false), maxFileSizeInMb(250)). The SaveToOriginalFile class already declares the audiobook field and includes it in isAnyFormatEnabled(), so this change correctly provides the default configuration. Backward compatibility with existing stored settings is ensured by @JsonIgnoreProperties(ignoreUnknown = true) on the DTO.


📝 Walkthrough

Walkthrough

Consolidated Spring configuration: multiple config classes removed or relocated, property classes un-annotated and enabled via @EnableConfigurationProperties, multipart handling enabled via application YAML, several beans moved/added, and constructor injection adopted in multiple services.

Changes

Cohort / File(s) Summary
Application bootstrap & properties
booklore-api/src/main/java/org/booklore/BookloreApplication.java, booklore-api/src/main/java/org/booklore/config/AppProperties.java, booklore-api/src/main/java/org/booklore/config/BookmarkProperties.java
Main app now enables both AppProperties and BookmarkProperties via @EnableConfigurationProperties. @Component removed from AppProperties and @Configuration removed from BookmarkProperties.
Rest client & bean relocation
booklore-api/src/main/java/org/booklore/config/RestClientConfig.java, booklore-api/src/main/java/org/booklore/config/BeanConfig.java
New @Primary RestTemplate bean added in RestClientConfig using injected HttpClient and 15s read timeout; the old BeanConfig providing a RestTemplate and init logic was removed.
Multipart & application config
booklore-api/src/main/java/org/booklore/config/MultipartConfig.java, booklore-api/src/main/resources/application.yaml
MultipartConfig config class removed. application.yaml now enables servlet multipart handling with max-file-size: 1024MB, max-request-size: 1024MB, and file-size-threshold: 0.
Transaction & scheduling configs
booklore-api/src/main/java/org/booklore/config/TransactionConfig.java, booklore-api/src/main/java/org/booklore/config/TaskSchedulerConfig.java
Transaction configuration class (transaction manager) deleted. @EnableScheduling removed from TaskSchedulerConfig; existing post-start initialization method remains.
WebSocket stats suppression
booklore-api/src/main/java/org/booklore/config/WebSocketConfig.java
Added @EventListener(ApplicationReadyEvent.class) method that sets WebSocketMessageBrokerStats.loggingPeriod to 30 * 24 * 60 * 60 * 1000L on startup.
Dependency injection refactors
booklore-api/src/main/java/org/booklore/service/kobo/KepubConversionService.java, booklore-api/src/main/java/org/booklore/service/metadata/parser/GoogleParser.java, booklore-api/src/main/java/org/booklore/service/metadata/parser/hardcover/HardcoverBookSearchService.java
Field @Autowired injection removed in favor of constructor injection / Lombok @RequiredArgsConstructor; removed unused @Autowired constructors/annotations and a 2‑arg GoogleParser overload.
Reader service internal change
booklore-api/src/main/java/org/booklore/service/reader/CbxReaderService.java
readEntryDimension now calls archiveService.transferEntryTo(cbxPath, entryName, baos) instead of streamEntryFromArchive(..., metadata), removing reliance on metadata in that call.
Settings update
booklore-api/src/main/java/org/booklore/service/appsettings/SettingPersistenceHelper.java
Added audiobook format settings (enabled(false), maxFileSizeInMb(250)) to default metadata persistence settings.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • zachyale

Poem

🐰 Beans hop into tidy rows,
Properties paired where spring wind blows,
Timeouts set and uploads grow,
Constructors carry what they know,
A happy rabbit twitches its nose.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title follows the conventional commit format with type(scope): description, accurately summarizing the main refactoring effort to remove redundant Spring Boot configuration and fix dependency injection patterns.
Description check ✅ Passed The PR description includes all required template sections (Description and Changes) and provides a comprehensive list of modifications, though the 'Linked Issue' field is empty as none was specified.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
✨ Simplify code
  • Create PR with simplified code

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

Copy link
Copy Markdown
Contributor

@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

🧹 Nitpick comments (3)
booklore-api/src/main/java/org/booklore/service/reader/CbxReaderService.java (1)

115-115: Remove stale metadata parameter from readEntryDimension.

After the switch at Line 128 to archiveService.transferEntryTo(...), the CachedArchiveMetadata metadata argument is unused. Keeping it now is misleading and adds unnecessary coupling.

Proposed cleanup
-                CbxPageDimension dim = readEntryDimension(cbxPath, entryName, metadata, i + 1);
+                CbxPageDimension dim = readEntryDimension(cbxPath, entryName, i + 1);

-    private CbxPageDimension readEntryDimension(Path cbxPath, String entryName, CachedArchiveMetadata metadata, int pageNumber) {
+    private CbxPageDimension readEntryDimension(Path cbxPath, String entryName, int pageNumber) {
         try {
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
             archiveService.transferEntryTo(cbxPath, entryName, baos);

Also applies to: 125-128

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@booklore-api/src/main/java/org/booklore/service/reader/CbxReaderService.java`
at line 115, Remove the now-unused CachedArchiveMetadata parameter from the
readEntryDimension method signature and all its call sites in CbxReaderService:
update the method declaration of readEntryDimension (returning CbxPageDimension)
to drop the metadata argument and change calls like the one using
CbxPageDimension dim = readEntryDimension(cbxPath, entryName, metadata, i + 1);
to pass only the remaining parameters; also review other occurrences (e.g.,
around the archiveService.transferEntryTo transition) and adjust any delegation
or overloads so transferEntryTo and related logic no longer rely on or forward
the stale metadata parameter.
booklore-api/src/main/resources/application.yaml (1)

46-49: Multipart migration looks correct; consider a small threshold instead of 0.

Enabling multipart and migrating the 1024MB limits from the deleted MultipartConfig bean is the right approach for Spring Boot's declarative configuration.

However, file-size-threshold: 0 means every upload—including tiny cover images or metadata files—is immediately written to a temp file on disk. A small threshold (e.g., 2KB or 10KB) keeps small payloads in memory, avoiding unnecessary disk I/O while still protecting against memory pressure from large book uploads.

💡 Optional: set a small threshold to reduce I/O for tiny uploads
       max-file-size: 1024MB
       max-request-size: 1024MB
-      file-size-threshold: 0
+      file-size-threshold: 2KB
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@booklore-api/src/main/resources/application.yaml` around lines 46 - 49, The
multipart configuration currently sets file-size-threshold: 0 which forces all
uploads to be written to disk; change the value to a small non-zero threshold
(e.g., file-size-threshold: 2KB or 10KB) in the application.yaml so small
uploads remain in memory while large uploads still go to temp files; update the
multipart section (keys enabled, max-file-size, max-request-size,
file-size-threshold) to reflect the chosen threshold to reduce unnecessary disk
I/O.
booklore-api/src/main/java/org/booklore/config/WebSocketConfig.java (1)

35-39: LGTM! The migration from @PostConstruct in the deleted BeanConfig to @EventListener(ApplicationReadyEvent.class) is appropriate.

Using ApplicationReadyEvent ensures the WebSocket infrastructure is fully initialized before accessing the stats bean, which is a robust approach.

Consider using TimeUnit for improved readability:

♻️ Optional: Use TimeUnit for clarity
+import java.util.concurrent.TimeUnit;
     `@EventListener`(ApplicationReadyEvent.class)
     public void suppressStatsLogging(ApplicationReadyEvent event) {
         var stats = event.getApplicationContext().getBean(WebSocketMessageBrokerStats.class);
-        stats.setLoggingPeriod(30 * 24 * 60 * 60 * 1000L); // 30 days
+        stats.setLoggingPeriod(TimeUnit.DAYS.toMillis(30));
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@booklore-api/src/main/java/org/booklore/config/WebSocketConfig.java` around
lines 35 - 39, Replace the magic millisecond literal in suppressStatsLogging by
computing the duration with TimeUnit to improve readability: when obtaining the
WebSocketMessageBrokerStats bean in suppressStatsLogging, compute the 30-day
value via TimeUnit.DAYS.toMillis(30) and pass that to
stats.setLoggingPeriod(...) instead of 30 * 24 * 60 * 60 * 1000L.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@booklore-api/src/main/java/org/booklore/config/RestClientConfig.java`:
- Around line 22-27: The restTemplate bean in RestClientConfig creates ambiguity
with existing oidcRestTemplate and noRedirectRestTemplate beans; mark the
restTemplate `@Bean` method (restTemplate(HttpClient)) as `@Primary` so unqualified
RestTemplate injections resolve to it and avoid NoUniqueBeanDefinitionException
in the future; update the restTemplate method to add the `@Primary` annotation
(and import org.springframework.context.annotation.Primary if missing) so Spring
will prefer this bean when multiple RestTemplate candidates exist.

---

Nitpick comments:
In `@booklore-api/src/main/java/org/booklore/config/WebSocketConfig.java`:
- Around line 35-39: Replace the magic millisecond literal in
suppressStatsLogging by computing the duration with TimeUnit to improve
readability: when obtaining the WebSocketMessageBrokerStats bean in
suppressStatsLogging, compute the 30-day value via TimeUnit.DAYS.toMillis(30)
and pass that to stats.setLoggingPeriod(...) instead of 30 * 24 * 60 * 60 *
1000L.

In
`@booklore-api/src/main/java/org/booklore/service/reader/CbxReaderService.java`:
- Line 115: Remove the now-unused CachedArchiveMetadata parameter from the
readEntryDimension method signature and all its call sites in CbxReaderService:
update the method declaration of readEntryDimension (returning CbxPageDimension)
to drop the metadata argument and change calls like the one using
CbxPageDimension dim = readEntryDimension(cbxPath, entryName, metadata, i + 1);
to pass only the remaining parameters; also review other occurrences (e.g.,
around the archiveService.transferEntryTo transition) and adjust any delegation
or overloads so transferEntryTo and related logic no longer rely on or forward
the stale metadata parameter.

In `@booklore-api/src/main/resources/application.yaml`:
- Around line 46-49: The multipart configuration currently sets
file-size-threshold: 0 which forces all uploads to be written to disk; change
the value to a small non-zero threshold (e.g., file-size-threshold: 2KB or 10KB)
in the application.yaml so small uploads remain in memory while large uploads
still go to temp files; update the multipart section (keys enabled,
max-file-size, max-request-size, file-size-threshold) to reflect the chosen
threshold to reduce unnecessary disk I/O.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 277feda2-c82c-490b-9bc7-78656b9dc929

📥 Commits

Reviewing files that changed from the base of the PR and between 014f04a and 256e68d.

📒 Files selected for processing (14)
  • booklore-api/src/main/java/org/booklore/BookloreApplication.java
  • booklore-api/src/main/java/org/booklore/config/AppProperties.java
  • booklore-api/src/main/java/org/booklore/config/BeanConfig.java
  • booklore-api/src/main/java/org/booklore/config/BookmarkProperties.java
  • booklore-api/src/main/java/org/booklore/config/MultipartConfig.java
  • booklore-api/src/main/java/org/booklore/config/RestClientConfig.java
  • booklore-api/src/main/java/org/booklore/config/TaskSchedulerConfig.java
  • booklore-api/src/main/java/org/booklore/config/TransactionConfig.java
  • booklore-api/src/main/java/org/booklore/config/WebSocketConfig.java
  • booklore-api/src/main/java/org/booklore/service/kobo/KepubConversionService.java
  • booklore-api/src/main/java/org/booklore/service/metadata/parser/GoogleParser.java
  • booklore-api/src/main/java/org/booklore/service/metadata/parser/hardcover/HardcoverBookSearchService.java
  • booklore-api/src/main/java/org/booklore/service/reader/CbxReaderService.java
  • booklore-api/src/main/resources/application.yaml
💤 Files with no reviewable changes (8)
  • booklore-api/src/main/java/org/booklore/config/TaskSchedulerConfig.java
  • booklore-api/src/main/java/org/booklore/config/AppProperties.java
  • booklore-api/src/main/java/org/booklore/config/BookmarkProperties.java
  • booklore-api/src/main/java/org/booklore/config/TransactionConfig.java
  • booklore-api/src/main/java/org/booklore/service/metadata/parser/hardcover/HardcoverBookSearchService.java
  • booklore-api/src/main/java/org/booklore/config/MultipartConfig.java
  • booklore-api/src/main/java/org/booklore/config/BeanConfig.java
  • booklore-api/src/main/java/org/booklore/service/metadata/parser/GoogleParser.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Test Suite / Frontend Tests
  • GitHub Check: Test Suite / Backend Tests
  • GitHub Check: Analyze (java-kotlin)
  • GitHub Check: Analyze (javascript-typescript)
🧰 Additional context used
📓 Path-based instructions (1)
booklore-api/src/**/*.java

📄 CodeRabbit inference engine (AGENTS.md)

booklore-api/src/**/*.java: Use 4-space indentation in Java files and match surrounding Java style
Prefer constructor injection via Lombok patterns already used in the codebase. Do not introduce @Autowired field injection
Use MapStruct for entity/DTO mapping

Files:

  • booklore-api/src/main/java/org/booklore/config/RestClientConfig.java
  • booklore-api/src/main/java/org/booklore/config/WebSocketConfig.java
  • booklore-api/src/main/java/org/booklore/service/reader/CbxReaderService.java
  • booklore-api/src/main/java/org/booklore/service/kobo/KepubConversionService.java
  • booklore-api/src/main/java/org/booklore/BookloreApplication.java
🧠 Learnings (2)
📚 Learning: 2026-03-26T01:46:48.863Z
Learnt from: CR
Repo: grimmory-tools/grimmory PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-26T01:46:48.863Z
Learning: Applies to booklore-api/src/**/*.java : Prefer constructor injection via Lombok patterns already used in the codebase. Do not introduce `Autowired` field injection

Applied to files:

  • booklore-api/src/main/java/org/booklore/service/kobo/KepubConversionService.java
  • booklore-api/src/main/java/org/booklore/BookloreApplication.java
📚 Learning: 2026-03-26T01:46:48.863Z
Learnt from: CR
Repo: grimmory-tools/grimmory PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-26T01:46:48.863Z
Learning: Applies to booklore-api/src/test/**/*.java : Prefer focused unit tests; use `SpringBootTest` only when the Spring context is required

Applied to files:

  • booklore-api/src/main/java/org/booklore/BookloreApplication.java
🔇 Additional comments (3)
booklore-api/src/main/java/org/booklore/service/kobo/KepubConversionService.java (1)

4-4: LGTM! Proper use of Lombok constructor injection.

The refactoring correctly replaces @Autowired field injection with @RequiredArgsConstructor and a final field, aligning with the codebase's established dependency injection pattern. As per coding guidelines: "Prefer constructor injection via Lombok patterns already used in the codebase. Do not introduce @Autowired field injection".

Also applies to: 14-14, 17-17

booklore-api/src/main/java/org/booklore/config/WebSocketConfig.java (1)

5-14: LGTM!

The new imports are appropriate for the ApplicationReadyEvent listener pattern used to configure WebSocket stats.

booklore-api/src/main/java/org/booklore/BookloreApplication.java (1)

9-14: LGTM! Clean migration to centralized @EnableConfigurationProperties.

Registering AppProperties and BookmarkProperties via @EnableConfigurationProperties instead of @Component/@Configuration is the idiomatic Spring Boot pattern for @ConfigurationProperties classes.

Tests that depend on AppProperties either already include BookloreApplication.class in their @SpringBootTest(classes = ...) configuration or use focused unit tests with mocked dependencies, so no compatibility issues are expected from this change.

chernesk pushed a commit to chernesk/grimmory that referenced this pull request Apr 1, 2026
Copy link
Copy Markdown
Member

@zachyale zachyale left a comment

Choose a reason for hiding this comment

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

As per our convo, DEFAULT_MAX_UPLOAD_SIZE_MB has always been capping upload request size to 1024mb. This changeset does not change that current behaviour.

#152 Surfaces this existing bug, and following this PR being merged should be picked up to address this hard coded inconsistency

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants