Expand my Community achievements bar.

SOLVED

Dynamic Dropdown using datasource

Avatar

Level 2

Hi,

I have a dynamic dropdown that is populated using a datasource. In my servlet, I use a ResourceResolver obtained from a service user instead of the request object(this is done to avoid granting permissions to individual group users.). Although I can successfully retrieve the values on the backend with the service user, they are not displaying in the component dialog on the frontend.
All necessary permissions are granted to the service user, and the datasource object contains values. However, it is not appearing on the frontend.I suspect the issue arises when executing request.setAttribute(DataSource.class.getName(), ds);

It functions correctly when the ResourceResolver is obtained from the current request object.
Below is the code snippet. Any help is appreciated.


try (ResourceResolver resolver = ResourceResolverUtils.getDefaultServiceResourceResolver(resourceResolverFactory)) {

request.getSession().setAttribute(DataSource.class.getName(), EmptyDataSource.instance());
List<String> subGroupList = userGroupRetriever.getUsersAndGroups(resolver, parentGroupName, true);

List<Resource> fakeResourceList = new ArrayList<>();
for (String subGroup : subGroupList) {
ValueMap vm = new ValueMapDecorator(new HashMap<>());
vm.put("value", subGroup.trim().toLowerCase());
vm.put("text", subGroup.trim());
fakeResourceList.add(new ValueMapResource(resolver, new ResourceMetadata(), JcrConstants.NT_UNSTRUCTURED, vm));
}

DataSource ds = new SimpleDataSource(fakeResourceList.iterator());

request.getSession().setAttribute(DataSource.class.getName(), ds);

// request.setAttribute(DataSource.class.getName(), ds);
} catch (Exception e) {
log.error("Exception occurred {}", ExceptionUtils.getStackTrace(e));
}

@EstebanBustamante 

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi, 

I think you’re right; the issue may be related to the resourceResolver and the permissions granted to it. Try using "your" resourceResolver solely to gather the items you need to display in the dialog. Try something like this:

            try (ResourceResolver resolver = ResourceResolverUtils.getDefaultServiceResourceResolver(resourceResolverFactory)) {

                ResourceResolver originalResolver = request.getResourceResolver();
                request.getSession().setAttribute(DataSource.class.getName(), EmptyDataSource.instance());
                List<String> subGroupList = userGroupRetriever.getUsersAndGroups(resolver, parentGroupName, true);
                
                List<Resource> fakeResourceList = new ArrayList<>();
                for (String subGroup : subGroupList) {
                ValueMap vm = new ValueMapDecorator(new HashMap<>());
                vm.put("value", subGroup.trim().toLowerCase());
                vm.put("text", subGroup.trim());
//Note here the resolver changed
                fakeResourceList.add(new ValueMapResource(originalResolver, new ResourceMetadata(), JcrConstants.NT_UNSTRUCTURED, vm));
            }

 

Ultimately, I think the best way to troubleshoot this is by debugging, adding some breakpoints, and seeing what's happening.

 

Hope this helps

 

 



Esteban Bustamante

View solution in original post

10 Replies

Avatar

Community Advisor

Hi @Divya_T13 
Could you please check if this code is being called on dialog load.

Could you share how did you linked this servelt/datasourcetype with component.

 

Here is the example code using servlet

https://github.com/arunpatidar02/aem63app-repo/blob/master/java/DemoDailogDropdown.java 



Arun Patidar

Avatar

Level 2

Hi @arunpatidar 

Yes, the code is called on dialog load. Attached the screenshot and there is a corresponding java servlet mapped to datasource.It's similar to the example code you've shared in the above github link except for getting the resourceresolver from request. I am using resourceresolver from service userDivya_T13_0-1730890257920.png

 

Avatar

Community Advisor

Hi @Divya_T13 
Can you please check the servlet status, meybe it is not active.
Please check java imports as well i your servelt, you might be using decommissioned one? example, below will not work in AEMaaCS

import com.adobe.cq.commerce.common.ValueMapDecorator;

 

Please check correct imports in this datasource servlet https://github.com/arunpatidar02/aemaacs-aemlab/blob/master/core/src/main/java/com/community/aemlab/...  



Arun Patidar

Avatar

Level 2

Hi @arunpatidar 

Servlet is active, and bundle is also active. All Java imports used in the code match those provided in the GitHub link. We are using AEM 6.5.

I suspect the issue occurs when executing request.setAttribute(DataSource.class.getName(), ds);

When I obtain the ResourceResolver from a service user and use request.setAttribute(DataSource.class.getName(), ds);, the dialog field does not appear in the component.

However, when I obtain the ResourceResolver from a service user and use request.getSession().setAttribute(DataSource.class.getName(), ds);, the dialog field appears, but the dropdown values are not loading.

Avatar

Community Advisor

Hi @Divya_T13 
Yes, could be issue with service user mapping,

Why are you not using request object since this feature will be in Author and author might have read access to /apps folder anyway.



Arun Patidar

Avatar

Level 2

Hi @arunpatidar 

In our scenario, we are utilizing a dynamic dropdown component within a dynamic participant step in a workflow. To load this dropdown when a workflow user is logged in and completing the step, we need to provide read access to both /apps and /home/groups. Since we have multiple workflow users distributed across different groups, our goal is to avoid granting any access to the /home directory for these user groups. Therefore, we are using a service user to obtain the ResourceResolver instead of retrieving it from the request object so that serviceuser session can be used .

Avatar

Community Advisor

Hi @Divya_T13 
Make sure service user is part of useradmin group, otherwise you won't be able to read groups.



Arun Patidar

Avatar

Level 2

Hi @arunpatidar 

Thank you so much.

I've given all permissions to service user. I believe the issue is with the ResourceResolver. It is working with the below code.

 

Thank you @arunpatidar @EstebanBustamante for all your input and help.

Avatar

Correct answer by
Community Advisor

Hi, 

I think you’re right; the issue may be related to the resourceResolver and the permissions granted to it. Try using "your" resourceResolver solely to gather the items you need to display in the dialog. Try something like this:

            try (ResourceResolver resolver = ResourceResolverUtils.getDefaultServiceResourceResolver(resourceResolverFactory)) {

                ResourceResolver originalResolver = request.getResourceResolver();
                request.getSession().setAttribute(DataSource.class.getName(), EmptyDataSource.instance());
                List<String> subGroupList = userGroupRetriever.getUsersAndGroups(resolver, parentGroupName, true);
                
                List<Resource> fakeResourceList = new ArrayList<>();
                for (String subGroup : subGroupList) {
                ValueMap vm = new ValueMapDecorator(new HashMap<>());
                vm.put("value", subGroup.trim().toLowerCase());
                vm.put("text", subGroup.trim());
//Note here the resolver changed
                fakeResourceList.add(new ValueMapResource(originalResolver, new ResourceMetadata(), JcrConstants.NT_UNSTRUCTURED, vm));
            }

 

Ultimately, I think the best way to troubleshoot this is by debugging, adding some breakpoints, and seeing what's happening.

 

Hope this helps

 

 



Esteban Bustamante

Avatar

Level 2

Hi @EstebanBustamante 

Thank you so much. Adding the original ResourceResolver into the ValueMapResource and not the service user resolver worked. I made slight modification: we do not need session if we are adding the original resolver. Instead of using request.getSession().setAttribute(DataSource.class.getName(), EmptyDataSource.instance());, we can use request.setAttribute(DataSource.class.getName(), EmptyDataSource.instance());

Updated code:

try (ResourceResolver resolver = ResourceResolverUtils.getDefaultServiceResourceResolver(resourceResolverFactory)) {

request.setAttribute(DataSource.class.getName(), EmptyDataSource.instance());

ResourceResolver originalResolver = request.getResourceResolver();

List<String> subGroupList = userGroupRetriever.getUsersAndGroups(resolver, parentGroupName, true);

List<Resource> fakeResourceList = new ArrayList<>();
for (String subGroup : subGroupList) {
ValueMap vm = new ValueMapDecorator(new HashMap<>());
vm.put("value", subGroup.trim().toLowerCase());
vm.put("text", subGroup.trim());
fakeResourceList.add(new ValueMapResource(originalResolver, new ResourceMetadata(), JcrConstants.NT_UNSTRUCTURED, vm));
}

DataSource ds = new SimpleDataSource(fakeResourceList.iterator());

request.setAttribute(DataSource.class.getName(), ds);
} catch (Exception e) {
log.error("Exception occurred {}", ExceptionUtils.getStackTrace(e));
}