Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Support String inputs for import service methods #39337

Merged
merged 4 commits into from
Feb 21, 2025

Conversation

sharat87
Copy link
Member

@sharat87 sharat87 commented Feb 18, 2025

Description

This is so that these service methods can be used by other services for higher-order functionality. In such cases, passing the JSON content as a String is much more convenient than to build a Part implementation instance.

Automation

/test sanity ImportExport

🔍 Cypress test results

Tip

🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
Workflow run: https://github.com/appsmithorg/appsmith/actions/runs/13440118520
Commit: e382050
Cypress dashboard.
Tags: @tag.Sanity, @tag.ImportExport
Spec:


Thu, 20 Feb 2025 17:15:00 UTC

Communication

Should the DevRel and Marketing teams inform users about this change?

  • Yes
  • No

Summary by CodeRabbit

  • New Features
    • Expanded artifact and resource import options, enabling data ingestion both via file uploads and direct JSON input.
    • Introduced new methods for reading file contents as strings, enhancing flexibility in resource handling.
  • Bug Fixes
    • Improved input validation and error messaging, offering clearer feedback for missing or invalid data.
  • Refactor
    • Streamlined the import process to ensure a more consistent and reliable user experience by simplifying method signatures and reducing dependencies.

These updates enhance the flexibility and robustness of our import functionality, providing a smoother and more intuitive experience when working with artifacts and resources.

This is so that these service methods can be used by other
services for higher-order functionality. In such
cases, passing the JSON content as a `String` is
much more convenient than to build a `Part` implementation
instance.
Copy link
Contributor

coderabbitai bot commented Feb 18, 2025

Walkthrough

The changes update artifact import functionality by introducing methods to convert a file part to a string and altering method signatures to accept JSON string inputs instead of file parts. Both core and partial import service interfaces and implementations are updated accordingly. Test cases have been revised to reflect these new signatures and conversion flows. Dependencies such as ActionCollectionService are removed, and file-based resource handling in tests is replaced by string-based processing.

Changes

File(s) Change Summary
app/.../imports/internal/ImportServiceCE.java
app/.../imports/internal/ImportServiceCEImpl.java
Added readFilePartToString(Part file) and an overloaded extractArtifactExchangeJsonAndSaveArtifact(String jsonContents,…); updated method documentation and internal logic to convert file parts to strings for JSON processing.
app/.../imports/internal/partial/PartialImportServiceCE.java
app/.../imports/internal/partial/PartialImportServiceCEImpl.java
app/.../imports/internal/partial/PartialImportServiceImpl.java
Added new importResourceInPage method that accepts file contents as a string; updated existing method signatures to facilitate file conversion to string; removed the ActionCollectionService dependency.
app/.../controllers/ApplicationControllerTest.java
app/.../git/ServerSchemaMigrationEnforcerTest.java
app/.../imports/internal/ImportServiceTests.java
app/.../solutions/PartialImportServiceTest.java
Updated test cases to use string-based file handling; modified Mockito stubbing to match updated method parameters and replaced file part creation with direct resource reading.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant PartialImportService as PI
    participant ImportService as IS

    Client->>PI: importResourceInPage(wsId, appId, pageId, branch, file Part)
    Note over PI: Check input type and convert if needed
    PI->>IS: readFilePartToString(file Part)
    IS-->>PI: file contents (String)
    PI->>IS: extractArtifactExchangeJsonAndSaveArtifact(file contents, wsId, artifactId)
    IS-->>PI: ArtifactImportDTO
    PI-->>Client: Application
Loading

Possibly related PRs

Suggested labels

Task, Bug, Production

Suggested reviewers

  • nidhi-nair

Poem

Code transforms with every line,
File parts to strings, logic refined.
Methods reborn in a vivid display,
New flows emerge in a seamless way.
Cheers to functions dancing in tune 🎶!
A small change making the system bloom.

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added the skip-changelog Adding this label to a PR prevents it from being listed in the changelog label Feb 18, 2025
Copy link

Failed server tests

  • com.appsmith.server.controllers.ApplicationControllerTest#whenFileUploadedWithShortHeader_thenVerifySuccessStatus

@sharat87 sharat87 added the ok-to-test Required label for CI label Feb 18, 2025
@sharat87 sharat87 marked this pull request as ready for review February 18, 2025 15:07
@sharat87 sharat87 requested a review from a team as a code owner February 18, 2025 15:07
Copy link
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 (4)
app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/PartialImportServiceTest.java (1)

251-255: Consider handling potential IOException explicitly.

While @SneakyThrows works, it's better to handle IOExceptions explicitly in test code for better error messages and debugging.

-    @SneakyThrows
-    private String readResource(String filePath) {
-        return StreamUtils.copyToString(
-                new DefaultResourceLoader().getResource(filePath).getInputStream(), StandardCharsets.UTF_8);
+    private String readResource(String filePath) throws IOException {
+        try {
+            return StreamUtils.copyToString(
+                    new DefaultResourceLoader().getResource(filePath).getInputStream(), StandardCharsets.UTF_8);
+        } catch (IOException e) {
+            throw new IOException("Failed to read resource: " + filePath, e);
+        }
app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceCE.java (1)

14-15: LGTM! Consider adding Javadoc.

The method overload aligns well with the objective of supporting String inputs. Consider adding Javadoc to clarify the expected JSON format of fileContents.

+    /**
+     * Imports a resource into a page using JSON content provided as a string.
+     * @param workspaceId The ID of the workspace
+     * @param applicationId The ID of the application
+     * @param pageId The ID of the page
+     * @param branchName The name of the branch
+     * @param fileContents JSON string containing the resource configuration
+     * @return A Mono containing the updated Application
+     */
     Mono<Application> importResourceInPage(
             String workspaceId, String applicationId, String pageId, String branchName, String fileContents);
app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java (1)

132-145: Consider extracting charset to a constant.

The implementation looks good, but the charset could be defined as a constant for consistency and maintainability.

+ private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
  // ...
- return new String(data);
+ return new String(data, DEFAULT_CHARSET);
app/server/appsmith-server/src/test/java/com/appsmith/server/git/ServerSchemaMigrationEnforcerTest.java (1)

280-284: Consider explicit exception handling instead of @SneakyThrows.

While @SneakyThrows simplifies the code, explicit exception handling would make error cases more visible and maintainable.

- @SneakyThrows
- private String readResource(String filePath) {
+ private String readResource(String filePath) throws IOException {
      return StreamUtils.copyToString(
              new DefaultResourceLoader().getResource(filePath).getInputStream(), StandardCharsets.UTF_8);
  }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 88d3599 and a685a76.

📒 Files selected for processing (9)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCE.java (2 hunks)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java (1 hunks)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceCE.java (1 hunks)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceCEImpl.java (1 hunks)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceImpl.java (0 hunks)
  • app/server/appsmith-server/src/test/java/com/appsmith/server/controllers/ApplicationControllerTest.java (4 hunks)
  • app/server/appsmith-server/src/test/java/com/appsmith/server/git/ServerSchemaMigrationEnforcerTest.java (5 hunks)
  • app/server/appsmith-server/src/test/java/com/appsmith/server/imports/internal/ImportServiceTests.java (1 hunks)
  • app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/PartialImportServiceTest.java (7 hunks)
💤 Files with no reviewable changes (1)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceImpl.java
🔇 Additional comments (11)
app/server/appsmith-server/src/test/java/com/appsmith/server/controllers/ApplicationControllerTest.java (3)

24-24: LGTM!

The new imports are necessary for the updated test method stubs and follow Java conventions.

Also applies to: 33-33


74-74: LGTM!

The change to use anyString() makes the test more type-safe and aligns with the new service method signature that accepts JSON content as a String input.


105-105: LGTM!

The change to use any(Part.class) makes the test more type-safe while maintaining coverage for the legacy Part-based input path.

app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/PartialImportServiceTest.java (2)

40-40: LGTM! Required imports added for string-based resource handling.

The new imports support the transition from file-based to string-based resource handling.

Also applies to: 49-49, 51-51, 56-56


275-276: LGTM! Test methods updated to use string-based JSON content.

The changes align with the PR objective of supporting String inputs for import service methods. The test cases now:

  1. Read JSON content directly from resource files
  2. Pass JSON strings to the import methods
  3. Maintain the same verification logic

Also applies to: 278-278, 327-328, 332-332, 389-390, 392-394, 444-446, 451-452

app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceCE.java (1)

14-15:

❓ Verification inconclusive

Verify parameter validation in implementation.

Ensure that the implementation validates the fileContents parameter for valid JSON format and required structure.


🏁 Script executed:

#!/bin/bash
# Search for the implementation class to verify parameter validation
ast-grep --pattern 'class $_ implements PartialImportServiceCE {
  $$$
  importResourceInPage($_, $_, $_, $_, String $_) {
    $$$
  }
  $$$
}'

Length of output: 145


Action Required: Please confirm that the implementation of importResourceInPage properly validates the fileContents parameter to ensure it is valid JSON and adheres to the required structure. Our initial automated search did not yield conclusive evidence regarding parameter validation in the implementing class(es) of PartialImportServiceCE. It is strongly recommended to manually verify the validation logic in the implementation to ensure robustness.

app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCE.java (2)

42-44: LGTM! Well-structured interface additions.

The new methods provide a clean abstraction for string-based imports while maintaining consistency with existing patterns.


57-67: LGTM! Well-documented method overload.

The overloaded method maintains API consistency while adding string input support.

app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java (1)

163-168: LGTM! Clean implementation reusing existing logic.

Good use of composition to maintain DRY principle while adding string input support.

app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/partial/PartialImportServiceCEImpl.java (1)

108-114: LGTM! Clean delegation to string-based implementation.

Good separation of concerns while maintaining existing functionality.

app/server/appsmith-server/src/test/java/com/appsmith/server/imports/internal/ImportServiceTests.java (1)

862-863: LGTM! Test updated to use string input instead of FilePart.

The test has been simplified by removing the FilePart mock and using a string argument directly, which aligns with the updated method signature.

mohanarpit
mohanarpit previously approved these changes Feb 20, 2025
@mohanarpit
Copy link
Member

While I'm approving this PR, I'm concerned about the performance impact of this change. Generally, using FilePart is more memory efficient than converting & reading the whole file as a string into memory. Before merging, my suggestion would be to experiment with uploading a large JSON file in the import.

@sharat87
Copy link
Member Author

@mohanarpit, good point. And in that sense, I'm actually not "changing" anything here. The FilePart was being read in as bytes, then converted to String and then passed to gson in the current implementation. The reading and parsing was happening in the same method, so I was unable to hook in the middle, which is what I needed. So I did this refactor.

The actual process isn't changing. I now see how this impression came up. I forgot to remove that old method doing the same thing. I've done that now. Thanks!

Copy link
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: 0

🧹 Nitpick comments (2)
app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCE.java (2)

34-34: Add documentation for readFilePartToString method.

Please add Javadoc to describe the method's purpose, parameters, and return value.

+    /**
+     * Reads the contents of a file part and converts it to a string.
+     *
+     * @param file The file part to be read
+     * @return A Mono containing the file contents as a string
+     */
     Mono<String> readFilePartToString(Part file);

36-36: Add documentation for extractArtifactExchangeJson method.

Please add Javadoc to describe the method's purpose, parameters, and return value.

+    /**
+     * Extracts an ArtifactExchangeJson object from a JSON string.
+     *
+     * @param jsonString The JSON string to parse
+     * @return A Mono containing the parsed ArtifactExchangeJson
+     */
     Mono<? extends ArtifactExchangeJson> extractArtifactExchangeJson(String jsonString);
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a685a76 and aeafffc.

📒 Files selected for processing (3)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCE.java (2 hunks)
  • app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java (1 hunks)
  • app/server/appsmith-server/src/test/java/com/appsmith/server/imports/internal/ImportServiceTests.java (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/server/appsmith-server/src/test/java/com/appsmith/server/imports/internal/ImportServiceTests.java
🧰 Additional context used
🧠 Learnings (2)
app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCE.java (1)
Learnt from: sharat87
PR: appsmithorg/appsmith#39337
File: app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java:154-160
Timestamp: 2025-02-18T15:18:20.927Z
Learning: Specific JSON parsing error handling using try-catch blocks isn't needed in the ImportServiceCEImpl's extractArtifactExchangeJson method as Mono.fromCallable provides adequate error handling.
app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java (1)
Learnt from: sharat87
PR: appsmithorg/appsmith#39337
File: app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java:154-160
Timestamp: 2025-02-18T15:18:20.927Z
Learning: Specific JSON parsing error handling using try-catch blocks isn't needed in the ImportServiceCEImpl's extractArtifactExchangeJson method as Mono.fromCallable provides adequate error handling.
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: perform-test / rts-build / build
  • GitHub Check: perform-test / client-build / client-build
  • GitHub Check: perform-test / server-build / server-unit-tests
  • GitHub Check: server-unit-tests / server-unit-tests
  • GitHub Check: server-spotless / spotless-check
🔇 Additional comments (5)
app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCE.java (1)

49-59: LGTM! Well-documented overloaded method.

The new overloaded method is well-documented and maintains consistency with the existing interface patterns.

app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java (4)

103-117: Well-implemented file content reading logic!

The method correctly handles content type validation and properly manages data buffer resources.


125-132: Clean implementation following previous feedback!

The method correctly uses Mono.fromCallable for JSON parsing, which provides adequate error handling as discussed in previous reviews.


134-140: Successfully implements String input support!

The method elegantly chains the new string-based processing while maintaining compatibility with file-based inputs, fulfilling the PR's objective.


103-117:

❓ Verification inconclusive

Verify performance with large JSON files.

Based on the PR discussion about performance implications, it would be prudent to verify the memory efficiency of the string-based approach with large JSON files.

Consider testing with a large JSON file (e.g., >10MB) to ensure acceptable memory usage:

Also applies to: 134-140


🏁 Script executed:

#!/bin/bash
# Generate a large JSON file and test memory usage
python3 -c '
import json
import sys

# Generate a large JSON object
large_json = {
    "items": [{"id": i, "value": "x" * 1000} for i in range(10000)]
}

json.dump(large_json, sys.stdout)
' > large_test.json

# Find and execute tests that use readFilePartToString
rg -l "readFilePartToString" | grep "Test" | xargs -I {} echo "Found test file: {}"

Length of output: 275


Verify performance with large JSON files.

The current implementation reads the full file content into memory, which might lead to memory inefficiencies with large JSON files (e.g., >10MB). The automated script did not identify any test files targeting this scenario, so please ensure this case is manually verified. Consider adding dedicated performance tests if this functionality will handle large files in production.

@sharat87 sharat87 requested a review from mohanarpit February 20, 2025 17:31
@sharat87 sharat87 merged commit 1db0ad2 into release Feb 21, 2025
43 checks passed
@sharat87 sharat87 deleted the chore/refactor-import-apis branch February 21, 2025 01:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ok-to-test Required label for CI skip-changelog Adding this label to a PR prevents it from being listed in the changelog
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants