Skip to content

DXP:1549: Add support for CFs - #31

Open
ciechanowiec-ds wants to merge 3 commits into
mainfrom
feature/DXP-1549-add-support-for-CFs
Open

DXP:1549: Add support for CFs#31
ciechanowiec-ds wants to merge 3 commits into
mainfrom
feature/DXP-1549-add-support-for-CFs

Conversation

@ciechanowiec-ds

Copy link
Copy Markdown

📋 Type of the Changes

  • Breaking change
  • Non-breaking change
  • Bug fix / minor change

🛠 Changes being made

Add support for Content Fragments.

✅ Checklist

  • My code follows the code standards of this project
  • Changed code is covered with unit tests
  • I have updated READMEs and java docs (if applicable)

@ciechanowiec-ds
ciechanowiec-ds requested a review from a team as a code owner January 22, 2025 13:08
@ciechanowiec-ds
ciechanowiec-ds force-pushed the feature/DXP-1549-add-support-for-CFs branch from 5f02f4c to dc973d5 Compare January 22, 2025 13:11
Comment thread .github/workflows/ci-deploy-snpashot-maven-artifacts.yaml
Comment thread blueprints/pom.xml Outdated
Comment thread blueprints/src/main/java/dev/streamx/aem/connector/blueprints/AssetKey.java Outdated
private final ResourceResolverFactory rrFactory;
private final String nodePath;

AssetKey(ResourceResolverFactory rrFactory, String nodePath) {

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.

why do you use rrFactory here ? Can you just have Resource in constructor ?

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.

Resource and ResourceResolver hold inside an open JCR Session. That Session is usually created inside a try-with-resources block and closed as soon as the execution of that block is finished. What is important, as soon as the Session is closed, the related Resource and ResourceResolver become unusable. Therefore, if we pass Resource or ResourceResolver as constructor parameters to some object, we are creating a tricky coupling. Namely, the behavior and usefulness of such object will be dependent on the execution flow of some other code where the Session was created. As soon as some other code closes that Session, the object that holds the Resource or ResourceResolver will become unusable. For that reason, it is better to pass ResourceResolverFactory, which is detached from any ongoing Session. Thanks to that the object becomes independent and has truly encapsulated behavior instead of being dependent on the execution flow of the code where the Session was initiated.

Yes, opening additional Session requires additional resources, but this performance cost is extremely low and negligible compared to the cost of fixing error-prone code with spread open Sessions here and there.

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.

After an online discussion: decided that the Resource should be passed. Therefor, the code should be changed.

class JSONableNode {

private final String pathToJCRNode;
private final ResourceResolverFactory rrFactory;

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.

I dont get why we need to pass rrFactory all over the place. Once we have resource we have what we need. If you need a resolver why dont you get it from resource itself ?

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.

Resource and ResourceResolver hold inside an open JCR Session. That Session is usually created inside a try-with-resources block and closed as soon as the execution of that block is finished. What is important, as soon as the Session is closed, the related Resource and ResourceResolver become unusable. Therefore, if we pass Resource or ResourceResolver as constructor parameters to some object, we are creating a tricky coupling. Namely, the behavior and usefulness of such object will be dependent on the execution flow of some other code where the Session was created. As soon as some other code closes that Session, the object that holds the Resource or ResourceResolver will become unusable. For that reason, it is better to pass ResourceResolverFactory, which is detached from any ongoing Session. Thanks to that the object becomes independent and has truly encapsulated behavior instead of being dependent on the execution flow of the code where the Session was initiated.

Yes, opening additional Session requires additional resources, but this performance cost is extremely low and negligible compared to the cost of fixing error-prone code with spread open Sessions here and there.

@ciechanowiec-ds ciechanowiec-ds Jan 27, 2025

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.

After an online discussion: decided that the Resource should be passed. Therefore, the code should be changed.

resourceResolver, slingRequestProcessor, resourcePath
)
).map(slingInternalRequest -> slingInternalRequest.withExtension("json"))
.map(slingInternalRequest -> slingInternalRequest.withSelectors("infinity"))

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.

why infinity selector that gives you the whole structure ? Have you considered using .model selector ?

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.

Yes, I considered using model selector and came to the conclusion that it can't be used here. Exporter Framework for Sling Models is supposed to work for Sling Resources that have a specific resourceType (https://sling.apache.org/documentation/bundles/models.html#exporter-framework-1). This is usually a case for Sling Resources that represent components on a page. Here, in turn, we are not dealing with a Sling Resource that has a specific resourceType. We are dealing with a usual dam:Asset node from /content/dam/puresight (more specifically: Content Fragment), which is pure data, without a specific resourceType set. Therefore, the model selector won't and doesn't work here.

I also considered extracting the data from CF via GraphQL, but came to the conclusion that this solution won't be effective, since setting it up will take substantially more time than the current solution without a real necessity.

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.

After an online discussion: probably we will need a different approach than "infinity" + manual cleanup of the output data. To be resolved later.

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.

3 participants