Creating a node in the JCR when a component is rendered | Community
Skip to main content
darren_hoffman
March 18, 2016

Creating a node in the JCR when a component is rendered

  • March 18, 2016
  • 6 replies
  • 13002 views

I am creating a component that contains an image-rendering (Java) servlet as part of its implementation. When the component is first rendered, it does not have a node under /content in the JCR, which is preventing the image from loading. What I think is happening is that since I am requesting an image from AEM based on the location of the instance of my component in the JCR, Sling cannot properly find and invoke the servlet, since no node exists with the given selectors.

Specifically:  <img src="${resource.path}.image.png?key=123" />

I haven't found a way to automatically create the instance node in the JCR, though I can create the node when I save a new instance configuration to the JCR via the component dialog. Is there some way I can have the instance node be created automatically on component render, or, otherwise, configure something on the server so that I can always make a request that will be successfully routed to my image-rendering servlet?

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.

6 replies

smacdonald2008
March 19, 2016

Isn't your component embedded in a page under /content. I am not sure what you mean when you say nothing under / content. All web pages that are rendered in AEM are under /content.

smacdonald2008
March 19, 2016

Or do you mean you want to create a sling servlet that renders an image? You can invoke a servlet without creating a node.

joerghoh
Adobe Employee
Adobe Employee
March 19, 2016

Hi,

so do I understand correctly, that you want to render an image, which is associated with a page, but not necessarily present upon first creation (for example like a screenshot of the page)?

If that's correct, creating the image is probably to way to go. But what if you store that image then only in the dispatcher cache (instead of saving it to the repository) and serving it from there? Of course on every purge of the dispatcher cache you need to recreate it, which takes time. I would save it to the repository only if there's no other option, if rendering takes too much time and occurs to often.
But if you store it in the repo, you probably shouldn't create it on first request, but rather pre-compute it (maybe already when the page is updated). In every case you had to decouple the sessions you use: The (anonymous) session for requesting the image, and a privileged session to save the created image to the repository.

kind regards,
Jörg

darren_hoffman
March 21, 2016

My page has a node under /content when the page is created and rendered, but my embedded component does not. That is, my embedded component does not have its own node in the JCR until I use the dialog to configure its parameters. I don't want to require that an author use the dialog in order to make this component function properly.

The reason I am trying to render an image, rather than simply serving a static image, is that I am creating a Captcha component that developers can embed into their custom forms. I started with the Captcha component in the Form Builder tool, and this component includes an image-rendering servlet that generates a new image on every request. I want a developer to be able to include the resource in their form without forcing them to also author the page. The Captcha should function properly immediately, and any configuration should be entirely at an authors' discretion.

Thanks

joerghoh
Adobe Employee
Adobe Employee
March 21, 2016

Hi,

I don't really understand your requirement. When you want to render a component, there must be a resource (!= NonExistingResource) which the proper ResourceType defined. So rendering a component without the underlying Resource is not possible.

In the opening posting you mentioned the use of a selector for the page component. This is different, because for the page you have a Resource.

kind regards,
Jörg

darren_hoffman
March 21, 2016

When I use "${resource.path}" in my Sightly template, I do get the correct path in the JCR to where the node _should_ be. The node does not exist, however, until I configure it via the component dialog. What I want is for the node to exist without my needing to configure the component via its dialog.

As far as "selectors" go, it is my attempt to describe what is failing to the best of my understanding. To reiterate:

  • I'm requesting an image at the URI "${resource.path}.image.png?key=123" 
  •     I imagine it is Sling that is attempting to route my request to some appropriate handler
  • The request for the image at that URI returns a 404
  •     I guess that Sling is unable to find any handler for my request
  • When I manually a node in the JCR in at the path indicated by "${resource.path}", the 404 is replaced with a 200 that contains the image as expected
  •     Apparently, the existence of a node at the correct path enables Sling to find my custom image-rendering servlet
joerghoh
Adobe Employee
Adobe Employee
March 21, 2016

Ok, I think I got it.

Your problem is indeed the non-existence of the underlying resource. if there's no resource, Sling cannot resolve any script. So it's all based on the existence of this resource.

But you can build it like this:

* ${page}.image.jpg will display the image (if present) or do any other operation you want.

The difference is that you build the "image" selector as a selector the page, and not as a selector to your captcha/image component. Because the page resource is always there, resolving the script for the "image" selector will succeed as well. And then you can register a servlet to react on this selector and implement it as you like.

kind regards,
Jörg

darren_hoffman
March 21, 2016

Thank you, kindly, Jörg. I will try this and see if I can get it to work.

June 1, 2018

If you want your component to have some nodes created automatically you have to make use of cq:template. You create it beside cq:dialog. If you want to have node called image_node created automatically, your cq:template would look something like this:

<jcr:root jcr:primaryType="nt:unstructured" ...>

    <image_node jcr:primaryType="nt:unstructured" sling:resourceType="path/to/component/definition"/>

</jcr:root>

June 3, 2018

Thanks @igorr76272295

For my case. It won't work as expected with data-sly-resource.

Note that there are we have two use case using of a component.

#1: We use sly API to give a component (this is my case)

<div data-sly-resource="${ childField.path @ resourceType=childField.fieldType, description=childField.description, variable=childField.variable, decorationTagName='div'}"></div

>

#2: Content author will drag & drop component from sidekick into the existing pars in a page.

P/S: It works in case we drag & drop component into the parsys.

Regards & Thanks,

Hung Vu

June 3, 2018

As you said, cq:template node of the component has the desired effect only in case author adds the component to page - true. For the first use case, however, you have to include the respective nodes in the template of your page, e.g.,:

<jcr:root jcr:primarytype="cq:Template" ...>

     <jcr:content jcr:primaryType="cq:PageContent" ...>

          <your_component sling:resourceType="path/to/your/component">

               <image_node jcr:primaryType="nt:unstructured" sling:resourceType="path/to/component/definition"/>

          </your_component>

     </jcr:content>

</jcr:root>