Multifield Component in Sightly with Sling Models

Starting AEM 6.0, new templating language Sightly now known as HTL is introduced. It offers highly productive enterprise-level web framework that increases security and allows HTML developers without Java knowledge to better participate in AEM projects.

Adobe recommends any new components to be developed using Sightly. Speaking of components, one of the vital components of any AEM application is a multifield component. More often than not, you will come across a requirement where you would have to create a multifield component, be it a social link component or a custom carousel component etc.  This post will talk about creating a multifield component in Sightly using Sling Models.

Infrastructure Used:

  • AEM Instance : 6.2
  • OS: Windows 10

Follow the below Steps to create the multifield component:

  1. Firstly Create a sample AEM project using the maven archetype 10.
  2. Create a new Sightly component. You can take reference from this article. Create the structure like below for multifield componentmultifield (I would be sharing the complete code, don’t worry).
  3. The links get saved in the below format.links
  4. Write a Sling Model to parse these links. Read my earlier post about the issue with sling models in 6.2.
</pre>
<pre>@Model(adaptables = Resource.class)
public class DemoMultiFieldModel {

    Logger logger = LoggerFactory.getLogger(DemoMultiFieldModel.class);

    @Inject
    @Named("links")
    private String[] links;

    private List<Link> list;

    @PostConstruct
    protected void init() throws JSONException {
        logger.info("links" + links);
        this.list = new ArrayList<Link>();
        for (String linkString : links) {
            JSONObject jsonObject = new JSONObject(linkString);
            logger.info("json object is " + jsonObject);
            list.add(new Link(jsonObject.getString("linktext"), jsonObject.getString("linkURL")));
        }
        logger.info("linkList is" + list);
    }

    public List<Link> getList() {
        return list;
    }
}</pre>
<pre>
  1.  Now, invoke this model in your Sightly file.
Demo MultifieldPanel component
<p data-sly-test="${properties.heading}"> ${properties.heading}</p>
<p data-sly-test="${properties.desc}"> ${properties.desc}</p>

<div data-sly-use.linkModel="aem.bootstrap.core.models.DemoMultiFieldModel">
${linkModel.message}
<div data-sly-test="${linkModel.list}" data-sly-list.list="${linkModel.list}">
<b>page:</b> ${list.linktext}
<b>path:</b> ${list.linkURL}
</div>
</div>
  1. You also have to add the nested-multifield.js since nested multifield is not supported OOTB. You can find it in the code repository below.

If everything is fine, your sightly component should look like below:

sightly page

You can clone the code from here.

References :

https://helpx.adobe.com/experience-manager/using/creating-sightly-component.html

https://sling.apache.org/documentation/bundles/models.html

https://helpx.adobe.com/experience-manager/using/domparser.html

Hope it helps !! 🙂

Managing Community Users in AEM | Tunnel Service

The trend of having the interactive websites is more common these days. Users can interact through forums, by posting comments, by participating in quizzes etc. AEM Communities provides a rich framework to have such interactive websites. Users can either come from LDAP/AEM or you can allow Social logins as well. But, with this increases the need of managing such users in a highly interactive website.

Recently, we encountered a serious issue in one of our projects.

Problem/Use Case: 

Usually, the logins happen on a Publish instance which makes the users being created on the Publish instance itself. Now, in an interactive community site, users are added to Community Groups so that they can interact. Now, there are two options to add these users to the groups:

  1. Have some trusted users who can use the useradmin console and assign the users to the particular Community groups.Users who gets assigned to such community groups are called members on the publish instance.
  2. Have the same users on author instance, add them to appropriate Community groups and activate it.

Now, the first option imposes some of the security risks, so we were using the 2nd option. But lately, we realized that as the number of users increases the performance of author instance starts degrading.

Solution:

Adobe has provided a way to have these users in the publish instance and yet manage it from the author instance. You can use the tunnel service to have the publish users available in the author instance. Follow the below steps:

  1. Go to Configuration Manager on author instance and look for the AEM Communities Publish Tunnel Service  and click on enable. This service needs to be enabled on the author instance only.tunnel service
  2. Now, Go to the members console on author instance. You should be able to see all the users now. members console
  3. Clicking on create button will allow you to add a new member into the publish instance and assign it to particular Community Site and Community Groups.
  4. Similarly, Groups console will allow you to manage the Community Groups.

Troubleshooting:

  1. Make sure both the author and publish instance will have the same configuration i.e. Both should be on AEM 6.1 (SP1+FP4) or above. In FP3, tunnel service does not allow the management of members from author instance. This feature was added in FP4.
  2. Make sure the bundles are up and running in both the instances. Otherwise,you will not be able to see any users in the members console.
  3. If you are not able to see the default users, make sure you are not running on nosamplecontent runmode.

References:

https://docs.adobe.com/docs/en/aem/6-1/administer/communities/users.html

https://docs.adobe.com/docs/en/aem/6-1/administer/communities/consoles/members.html

Hope it helps !! 🙂

Issue using Sling Models in AEM 6.2 | Dependency Not found

Sling Models is a way to create model objects which are automatically mapped from Sling objects, typically resources but also request objects.

This article explains how to use sling models in AEM. But, If you want to use Sling models with AEM 6.2, you might encounter some dependency issues.

Recently I faced a problem when my AEM project stopped working. The project was created using Maven archetype 10. It was working fine until I was on AEM 6.1. When I tried deploying it to AEM 6.2, the bundle was not coming to Active state. Later while debugging, I found out that it was not able to find a particular dependency. I was seeing something like below in the console.

javax.inject,version=[0.0,1) -- Cannot be resolved

After some debugging, I was able to resolve the issue. If you are facing the similar issue, you need to add the below dependency to your pom file.

<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-atinject_1.0_spec</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>

 

This is it. Sling Models code should work on AEM 6.2 now.

Hope it helps !!  🙂

Talend : Passing values from Parent to Child Job

In the previous post, I discussed automating the Content Migration using Talend. As the power of Talend lies with creating meaningful Jobs which solves a business problem. More often than not, one job has to talk to another job.

Use case:

While working on a migration project, I had a use case where I wanted to pass a value from a Parent Job to a Child Job.

Problem:

globalMap is a useful way to pass values, but it can only be used to pass the values within the same Job. For Instance, If I have a Job A like below:

job1

where tJava_1 is setting a key in globalMap,

globalMap.put("testVal","Test Value 1");

and tJava_2 is trying to retrieve its value.

System.out.println("testVal in the same job is "+(String)globalMap.get("testVal"));

Its value can be retrieved from the components defined in the same Job but if we try to access those values outside this Job, we’ll get the null value.

Solution:

This problem can be solved by utilizing the power of “Context Variables”.Create a Job 2 like as shown below and define a context variable “testValue”

job 3

Create a Job B like as shown below:  (Job 2 is a tRunJob component which is calling the above Job)

job2

Here tJava_1 is setting a key in globalMap,

globalMap.put("testVal","Test Value 1");

To access the above value in Job 2 , define this component’s properties as below. Note the “Context Param” definition, this is how we can set the value in the context variable and retrieve it in the child job.

final job

tJava_1 in Child Job can simply retrieve its value :

System.out.println("testVal in theanother job is "+context.testValue);

Hope it helps !! 🙂