Expand my Community achievements bar.

SOLVED

How to get the current page path in a servlet mapped to a datasource

Avatar

Level 2

Hi All,

We have a requirement as shown below:

1. A page (PageA) will have two components
2. First component (Component A) is a path browser which allows user to link to another page (Page B).
3.Second component (Component B) has various fields and a multifield.
4. The multifield in Component B has dropdown value field which has to be populated based on the data present in Component A
5. To accomplish this, we created a dynamic dropdown datasource on the multifield item. Datasource is mapped to a servlet.

Problem statement:
The resource path that we are getting in the servlet is the resource path of the component (Component B)
Inorder to get the path of component A, we are trying to get the current page path using
"String resourcePath = (String) request.getAttribute("granite.ui.form.contentpath");"
This will return the complete path upto the first item in the multifield. /content/site/folder/pageA/jcr:content/root/container/component/multifieldItem/item0

From here we are doing a substring to "/content/site/folder/pageA/" and appending the required path i.e /jcr:content/root/container/ComponentA
So now, "/content/site/folder/pageA/jcr:content/root/container/ComponentA" will have a property which has the link to PageB, which we are using for further processing.

While using this approach, on the first time load of the dialog, the dropdown values are not getting populated. Once one multifield item is added, dialog submitted and then reopened the values are getting populated.

We also used the below to get the page path.
Enumeration<?> values = request.getHeaders("Referer"); if (values != null) { while
(values.hasMoreElements()) { String url = (String) values.nextElement();
LOGGER.info("Resource url enumeration*****" + url); } }
As the above is not highly recommended, could any of you suggest how to retrieve the path of the page where the component is authored?

 

Thanks!

 

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hello @ReshmaRaj ,

You can try this,

In your XML, 

<selectComponent
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/coral/foundation/form/select"
        fieldLabel="Select Component"
        multiple="{Boolean}true"
        name="./selectComponent">
    <datasource
            jcr:primaryType="nt:unstructured"
            sling:resourceType="aem-demo/datasource/component/json"/>
</selectComponent>

where aem-demo/datasource/component/json is your servlet path

In your servlet,

@Component(service = Servlet.class,
        property = {
                Constants.SERVICE_DESCRIPTION + "=AEM Demo JSON Datasource Servlet",
                ServletResolverConstants.SLING_SERVLET_METHODS + "=" + HttpConstants.METHOD_GET,
                ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES + "=aem-demo/datasource/component/json"
        })
@Override
    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) {
        ResourceResolver resourceResolver = request.getResourceResolver();
        String currentPagePath = request.getRequestPathInfo().getSuffix().split("/" + JCR_CONTENT)[0];
}

Hope this will help you.

 

View solution in original post

4 Replies

Avatar

Community Advisor

Hi @ReshmaRaj, You can use Sling Model instead of Servlet.

<item jcr:primaryType="nt:unstructured"
  sling:resourceType="granite/ui/components/foundation/form/select"
  fieldLabel="Select an Item"
  name="./item">
  <datasource jcr:primaryType="nt:unstructured"
    sling:resourceType="/apps/aem-demo/datasource/item/item.html"/>
</formElements>

apps/aem-demo/datasource/item/item.html

<sly data-sly-use.data="com.aem.demo.core.components.model.Item"></sly>

com/aem/demo/core/components/model/tem.java

@Model(
  adaptables = { SlingHttpServletRequest.class },
  defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL
)
public class Item {
  @SlingObject
  protected ResourceResolver resourceResolver;

  @ScriptVariable
  protected Page currentPage;

  @PostConstruct
  protected void init() {
    String pageUrl = currentPage.getPath();

    // Construct data resource here
  }
}

 

Avatar

Correct answer by
Community Advisor

Hello @ReshmaRaj ,

You can try this,

In your XML, 

<selectComponent
        jcr:primaryType="nt:unstructured"
        sling:resourceType="granite/ui/components/coral/foundation/form/select"
        fieldLabel="Select Component"
        multiple="{Boolean}true"
        name="./selectComponent">
    <datasource
            jcr:primaryType="nt:unstructured"
            sling:resourceType="aem-demo/datasource/component/json"/>
</selectComponent>

where aem-demo/datasource/component/json is your servlet path

In your servlet,

@Component(service = Servlet.class,
        property = {
                Constants.SERVICE_DESCRIPTION + "=AEM Demo JSON Datasource Servlet",
                ServletResolverConstants.SLING_SERVLET_METHODS + "=" + HttpConstants.METHOD_GET,
                ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES + "=aem-demo/datasource/component/json"
        })
@Override
    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) {
        ResourceResolver resourceResolver = request.getResourceResolver();
        String currentPagePath = request.getRequestPathInfo().getSuffix().split("/" + JCR_CONTENT)[0];
}

Hope this will help you.