Skip to content

Refactor: Modularize ApiResponseHelper#createUsageResponse - #13490

Open
PrashantBhanage wants to merge 10 commits into
apache:mainfrom
PrashantBhanage:fix-11635-refactor-usage
Open

Refactor: Modularize ApiResponseHelper#createUsageResponse#13490
PrashantBhanage wants to merge 10 commits into
apache:mainfrom
PrashantBhanage:fix-11635-refactor-usage

Conversation

@PrashantBhanage

@PrashantBhanage PrashantBhanage commented Jun 25, 2026

Copy link
Copy Markdown

Fixes #11635

Description

This PR addresses the technical debt in ApiResponseHelper#createUsageResponse(Usage) by modularizing the 530-line method.

  • Extracted the 500+ line switch/if-else block into a main dispatcher method populateUsageTypeSpecificDetails.
  • Created 18 individual private helper methods for each specific UsageType to improve maintainability and readability.
  • Introduced a UsageResourceDetails container class to safely manage and return resourceId and resourceType state for tag lookups.
  • Verified zero business logic changes; strictly structural refactoring.

Additional Changes

  • Added JUnit Jupiter, JUnit Vintage, and mockito-junit-jupiter test dependencies to server/pom.xml to support JUnit 5 tests.
  • Migrated ApiResponseHelperTest from JUnit 4 to JUnit 5 and added unit tests for the 18 extracted helper methods.
  • Fixed sonar-check.yml end-of-file formatting (pre-commit hook).
  • Fixed indentation and added proper java.security.cert imports in handleCertificateResponse.

Types of changes

  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • Test (unit or integration test code)

How Has This Been Tested?

  • All 41 unit tests pass locally via mvn -pl server -Dtest=ApiResponseHelperTest test
  • Full server test suite passes: 3256 tests, 0 failures
  • Checkstyle passes with 0 violations
  • Packaging verified on el8, el9, el10, debian, suse15

@boring-cyborg

boring-cyborg Bot commented Jun 25, 2026

Copy link
Copy Markdown

Congratulations on your first Pull Request and welcome to the Apache CloudStack community! If you have any issues or are unsure about any anything please check our Contribution Guide (https://github.com/apache/cloudstack/blob/main/CONTRIBUTING.md)
Here are some useful points:

@sureshanaparti

Copy link
Copy Markdown
Contributor

@blueorangutan package

@codecov

codecov Bot commented Jun 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 3.41%. Comparing base (77fbb0f) to head (d731c70).

❗ There is a different number of reports uploaded between BASE (77fbb0f) and HEAD (d731c70). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (77fbb0f) HEAD (d731c70)
unittests 1 0
Additional details and impacted files
@@              Coverage Diff              @@
##               main   #13490       +/-   ##
=============================================
- Coverage     19.73%    3.41%   -16.33%     
=============================================
  Files          6371      487     -5884     
  Lines        575784    41863   -533921     
  Branches      70478     7912    -62566     
=============================================
- Hits         113632     1429   -112203     
+ Misses       449805    40234   -409571     
+ Partials      12347      200    -12147     
Flag Coverage Δ
uitests 3.41% <ø> (ø)
unittests ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@PrashantBhanage

Copy link
Copy Markdown
Author

Added unit tests for all 18 extracted UsageType helper methods to address the coverage concern. Also added the required JUnit Jupiter and mockito-junit-jupiter test dependencies to server/pom.xml. All 41 tests pass locally.

@PrashantBhanage PrashantBhanage left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I don't know where the problem is.

@DaanHoogland

Copy link
Copy Markdown
Contributor

I don't know where the problem is.

what problem are you talking about, @PrashantBhanage ?

I only see an integration test failure which seems unrelated.

@PrashantBhanage

Copy link
Copy Markdown
Author

I don't know where the problem is.

what problem are you talking about, @PrashantBhanage ?

I only see an integration test failure which seems unrelated.

Got it, thanks! I raised #13516 for the flaky test separately. The refactor itself should be good.

@DaanHoogland

Copy link
Copy Markdown
Contributor

@blueorangutan test

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors ApiResponseHelper#createUsageResponse(Usage) by extracting usage-type-specific logic into a dispatcher (populateUsageTypeSpecificDetails) plus multiple private helper methods, introducing a small container (UsageResourceDetails) to carry resourceId/resourceType for tag lookups.

Changes:

  • Modularized usage-response population into dedicated helper methods keyed by UsageTypes.
  • Updated ApiResponseHelperTest to JUnit 5 + Mockito Jupiter and added focused tests for several usage-type helpers.
  • Added JUnit Jupiter / Vintage and Mockito Jupiter test dependencies to the server module POM.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 14 comments.

File Description
server/src/main/java/com/cloud/api/ApiResponseHelper.java Extracts usage-type logic into helper methods and centralizes tag lookup via UsageResourceDetails.
server/src/test/java/com/cloud/api/ApiResponseHelperTest.java Migrates to JUnit 5/Mockito Jupiter and adds unit tests for the new helper methods via reflection.
server/pom.xml Adds JUnit 5 (Jupiter + Vintage) and Mockito Jupiter dependencies to support the test migration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread server/src/main/java/com/cloud/api/ApiResponseHelper.java
Comment thread server/src/main/java/com/cloud/api/ApiResponseHelper.java Outdated
Comment thread server/src/main/java/com/cloud/api/ApiResponseHelper.java Outdated
Comment thread server/src/main/java/com/cloud/api/ApiResponseHelper.java Outdated
Comment thread server/src/main/java/com/cloud/api/ApiResponseHelper.java Outdated
Comment on lines 4504 to +4506
if (tmpl != null) {
usageRecResponse.setUsageId(tmpl.getUuid());
resourceId = tmpl.getId();
}
//Template/ISO Size
usageRecResponse.setSize(usageRecord.getSize());
if (usageRecord.getUsageType() == UsageTypes.ISO) {
usageRecResponse.setVirtualSize(usageRecord.getSize());
resourceType = ResourceObjectType.ISO;
} else {
usageRecResponse.setVirtualSize(usageRecord.getVirtualSize());
resourceType = ResourceObjectType.Template;
}
if (!oldFormat) {
final StringBuilder builder = new StringBuilder();
if (usageRecord.getUsageType() == UsageTypes.TEMPLATE) {
builder.append("Template usage");
} else if (usageRecord.getUsageType() == UsageTypes.ISO) {
builder.append("ISO usage");
}
if (tmpl != null) {
builder.append(" for ").append(tmpl.getName()).append(" (").append(tmpl.getUuid()).append(") ")
.append("with size ").append(toHumanReadableSize(usageRecord.getSize())).append(" and virtual size ").append(toHumanReadableSize(usageRecord.getVirtualSize()));
}
usageRecResponse.setDescription(builder.toString());
builder.append(" for ").append(tmpl.getName()).append(" (").append(tmpl.getUuid()).append(") ")
.append("with size ").append(toHumanReadableSize(usageRecord.getSize())).append(" and virtual size ").append(toHumanReadableSize(usageRecord.getVirtualSize()));
Comment on lines 4527 to +4529
if (snap != null) {
usageRecResponse.setUsageId(snap.getUuid());
resourceId = snap.getId();
}
//Snapshot Size
usageRecResponse.setSize(usageRecord.getSize());
if (!oldFormat) {
final StringBuilder builder = new StringBuilder();
builder.append("Snapshot usage ");
if (snap != null) {
builder.append("for ").append(snap.getName()).append(" (").append(snap.getUuid()).append(") ")
.append("with size ").append(toHumanReadableSize(usageRecord.getSize()));
}
usageRecResponse.setDescription(builder.toString());
builder.append("for ").append(snap.getName()).append(" (").append(snap.getUuid()).append(") ")
.append("with size ").append(toHumanReadableSize(usageRecord.getSize()));
Comment thread server/src/main/java/com/cloud/api/ApiResponseHelper.java Outdated
Comment thread server/src/main/java/com/cloud/api/ApiResponseHelper.java
Comment thread server/src/main/java/com/cloud/api/ApiResponseHelper.java
@PrashantBhanage

Copy link
Copy Markdown
Author

Applied all the Copilot suggestions, null checks for svcOffering, nullable Long values, and removed the unused variable.

@PrashantBhanage

Copy link
Copy Markdown
Author

Fixed the build, replaced the internal X509CertImpl with standard Java API and removed the unused imports that Copilot introduced.

@PrashantBhanage

Copy link
Copy Markdown
Author

I just pushed a quick fix to add the missing EOF newline in ApiResponseHelperTest.java, so the pre-commit check should be green now.

Also, just wanted to give a heads-up that the UI Build and Sonar JaCoCo failures look unrelated to my Java changes. The UI test seems to be timing out on a Vue router test (Status.spec.js), and Sonar is just throwing a 403 permission error right at the end when trying to drop a PR comment.

Let me know if there's anything else I need to tweak!

@PrashantBhanage

Copy link
Copy Markdown
Author

It should be good now!

@DaanHoogland

Copy link
Copy Markdown
Contributor

@blueorangutan test

@Damans227 Damans227 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nit: this "Refactor" PR also carries a .github/workflows/sonar-check.yml change and a server/pom.xml dependency bump (junit-jupiter/vintage/mockito-jupiter), plus a full JUnit4→JUnit5 migration of ApiResponseHelperTest. Worth calling out in the description since none of that is "modularize createUsageResponse".

Comment thread server/src/main/java/com/cloud/api/ApiResponseHelper.java Outdated
Comment thread server/src/main/java/com/cloud/api/ApiResponseHelper.java Outdated
return resourceDetails;
}

private UsageResourceDetails populateNetworkOfferingUsageResponse(Usage usageRecord, UsageRecordResponse usageRecResponse, boolean oldFormat, VMInstanceVO vmInstance) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nit: this method (and populateVpnUsersUsageResponse, populateVolumeSecondaryUsageResponse, populateBucketUsageResponse below) just returns new UsageResourceDetails() directly, while the other populate* methods declare a local resourceDetails, mutate it, and return that. Minor inconsistency in the extraction pattern.

@PrashantBhanage

Copy link
Copy Markdown
Author

@Damans227 Fixed the indentation on handleCertificateResponse, added proper imports for java.security.cert classes instead of using fully-qualified names inline. Will also update the PR description to mention the pom.xml dependency additions and JUnit 5 migration.

@DaanHoogland

Copy link
Copy Markdown
Contributor

@blueorangutan package

@DaanHoogland

Copy link
Copy Markdown
Contributor

@blueorangutan test

@DaanHoogland

Copy link
Copy Markdown
Contributor

thanks @PrashantBhanage , one more, can you rebase the PR to the 4.22 LTS branch?

@PrashantBhanage

Copy link
Copy Markdown
Author

@DaanHoogland I have opened the 4.22 LTS backport PR here: [https://github.com//pull/13695]

Note: I intentionally excluded the JUnit 5 test migration from the backport to avoid framework conflicts with the stable 4.22 testing architecture, but the core backend refactor and the .toString() bug fix are included.

@DaanHoogland

Copy link
Copy Markdown
Contributor

Note: I intentionally excluded the JUnit 5 test migration from the backport to avoid framework conflicts with the stable 4.22 testing architecture, but the core backend refactor and the .toString() bug fix are included.

ok, that would be an argument to go for this version and to abandon #13695

PrashantBhanage and others added 10 commits August 31, 2026 16:21
Fixes apache#11635

- Extracted the 500+ line switch/if-else block into a main dispatcher method `populateUsageTypeSpecificDetails`.
- Created 18 individual private helper methods for each specific `UsageType` to improve maintainability and readability.
- Introduced a `UsageResourceDetails` container class to safely manage and return `resourceId` and `resourceType` state for tag lookups.
- Verified zero business logic changes; strictly structural refactoring.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@DaanHoogland
DaanHoogland force-pushed the fix-11635-refactor-usage branch from da39c45 to d731c70 Compare August 31, 2026 14:21
@DaanHoogland

Copy link
Copy Markdown
Contributor

@blueorangutan shutup

@DaanHoogland

Copy link
Copy Markdown
Contributor

@blueorangutan package

@DaanHoogland DaanHoogland moved this from Backlog to Ready in CloudStack Testing Aug 31, 2026
@blueorangutan

Copy link
Copy Markdown

@DaanHoogland a [SL] Jenkins job has been kicked to build packages. It will be bundled with no SystemVM templates. I'll keep you posted as I make progress.

@blueorangutan

Copy link
Copy Markdown

Packaging result [SF]: ✖️ el8 ✖️ el9 ✖️ debian ✖️ suse15. SL-JID 19031

@DaanHoogland DaanHoogland moved this from Ready to conflict/waiting in CloudStack Testing Sep 1, 2026
@DaanHoogland

Copy link
Copy Markdown
Contributor

@PrashantBhanage can you look at the build errors, please?

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

Projects

Status: conflict/waiting

Development

Successfully merging this pull request may close these issues.

ApiResponseHelper#createUsageResponse(Usage) needs to be modularised (530 lines).

7 participants