Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.
SOLVED

API - Is there a way to retrieve the data of a social component in a structured way?

Avatar

Level 2

Hi,

I have not found how to do what I want in the AEM documentation or in a tutorial...

Is there a way to retrieve the data of a social component in a structured way? I know that I can retrieve specific nodes in the repository, but I need to figure out how the social component is implemented in the repository (nodes structure).

Is it possible to get the forum and its posts for example. What would be the best method to do this (JCR API, Sling, AEM API)?

Thanks,

Matthieu

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi Matthieu,

You can use Query Builder to retrieve all forums.(http://docs.adobe.com/docs/en/aem/6-0/develop/search/querybuilder-api.html)

type=cq:PageContent
property=cq:template
property.value=/apps/aaa/greater/templates/new-community

Would return you paths to the forums within the website.

To find out every component under certain path, again you can use query builder to select certain resources under known path.

e.g. 

type=cq:PageContent
property=cq:template
property.value=/apps/aaa/greater/templates/my-topic
path=/path/to/my-forum

Once you retrieve paths to your individual items(forums, posts or topics) you can call adaptTo method to adapt resource from path to your desired component. You already have adapters for forums and posts provided with out of the box AEM 6. (http://localhost:4502/system/console/status-adapters).

Thanks,

Peter

View solution in original post

12 Replies

Avatar

Employee

what version of AEM and what social components(jsp or handlebars) are you using

Avatar

Community Advisor

Yes, it's possible to view data as strucktured json. Your API in this case would be a wget request to the corresponding component path as json.

For example data displayed on https://communities.adobe.com(who also use social component) can be viewed by adding json selector at the end of the url.

https://communities.adobe.com/content/dam/cush/aem_technologistsdevelopersarchitects/Ask-AEM-Communi... shows you the structure used on the communities website.

Thanks,

Peter

Avatar

Level 2

Hi Kalyanar,

I have the AEM version 6.0 and I currently make my tests with the Geometrixx samples to discover the possibilities.

Matthieu

Avatar

Level 2

Hi Peter,

Thanks for your reply.

I see that I can get the structure in JSON, but the data is very "raw".

There is no way to get this data from an API in a more structured way. For example, to retrieve all forums, and for a specific forum, retrieve all topics and posts?

I need to understand how to parse this JSON to extract what I need? An also need to a the exact path of this forum?

Thanks,

Matthieu

Avatar

Employee

Hi Matthieu, 

Check http://localhost:4502/content/community-components/en/comments/jcr:content/content/comments.social.j...

Community-components is the recommended way to use socos. Some geometrixx soco examples are based on jsps. Please refer to community-components. Also This url gets you a very clean json.

Avatar

Correct answer by
Community Advisor

Hi Matthieu,

You can use Query Builder to retrieve all forums.(http://docs.adobe.com/docs/en/aem/6-0/develop/search/querybuilder-api.html)

type=cq:PageContent
property=cq:template
property.value=/apps/aaa/greater/templates/new-community

Would return you paths to the forums within the website.

To find out every component under certain path, again you can use query builder to select certain resources under known path.

e.g. 

type=cq:PageContent
property=cq:template
property.value=/apps/aaa/greater/templates/my-topic
path=/path/to/my-forum

Once you retrieve paths to your individual items(forums, posts or topics) you can call adaptTo method to adapt resource from path to your desired component. You already have adapters for forums and posts provided with out of the box AEM 6. (http://localhost:4502/system/console/status-adapters).

Thanks,

Peter

Avatar

Level 2

Hi Kalyanar,

I check this link, I see an interesting JSON, but I'm not sure to understand how I can retrieve the forum and its posts for example.

Could you give some hints?

Thanks,

Matthieu

Avatar

Level 2

Thanks Peter,

I will experiment this.

Matthieu

Avatar

Employee

Please find below a sample that queries for posts posted after a given time. This is just a sample that i wrote to explain to you.

package com.adobe.acs.commons.soco.servlets;

import com.adobe.cq.social.commons.client.api.SocialComponent;
import com.adobe.cq.social.commons.client.api.SocialComponentFactory;
import com.adobe.cq.social.commons.client.api.SocialComponentFactoryManager;
import com.adobe.cq.social.ugc.api.*;
import com.adobe.cq.social.ugcbase.SocialResourceUtils;
import com.adobe.cq.social.ugcbase.SocialUtils;
import com.day.cq.search.PredicateGroup;
import com.day.cq.search.Query;
import com.day.cq.search.QueryBuilder;
import com.day.cq.search.result.Hit;
import com.day.cq.search.result.SearchResult;
import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import org.apache.commons.lang3.StringUtils;
import org.apache.felix.scr.annotations.*;
import org.apache.felix.scr.annotations.Properties;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.*;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.JSONObject;

import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Component
@Service
@Properties({
        @Property(name = "service.description",
                value = "com.adobe.acs.commons.servlets.SampleJSONServlet"),
        @Property(name = "sling.servlet.resourceTypes", value = {"sling/servlet/default"}, propertyPrivate = true),
        @Property(name = "sling.servlet.methods", value = {HttpConstants.METHOD_GET}, propertyPrivate = true),
        @Property(name = "sling.servlet.selectors", value = {"sample"}, propertyPrivate = false),
        @Property(name = "sling.servlet.extensions", value = {"json"}, propertyPrivate = false)})
public class SampleJSONServlet extends SlingSafeMethodsServlet {
    @Reference
    private SocialUtils socialUtils;
    @Reference
    private SocialComponentFactoryManager socialComponentFactoryManager;

    @Reference
    private UgcSearch ugcSearch;

    @Override
    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        String lastreloadtime = request.getParameter("lrt");
        if("undefined".equals(lastreloadtime)){
            lastreloadtime=null;
        }

        JSONObject obj = new JSONObject();
        JSONArray arr = new JSONArray();
        final ResourceResolver resolver = request.getResourceResolver();
        final Session session = resolver.adaptTo(Session.class);
        PageManager pageManager = resolver.adaptTo(PageManager.class);
        Page page = pageManager.getContainingPage(request.getResource());
        List<SocialComponent> hits = new ArrayList<SocialComponent>();
        try {
            Resource resource = request.getResource();
            if(request.getParameter("lrt")!=null) {
                final UgcFilter ugcFilter = getFilter(request, page.getPath());
                if (ResourceUtil.isSyntheticResource(resource)) {
                    page = pageManager.getContainingPage(resource);
                } else if (SocialResourceUtils.isSocialResource(resource)) {
                    final ValueMap vm = resource.adaptTo(ValueMap.class);
                    final String rootResource = vm.get(SocialUtils.PN_CS_ROOT, "");
                    page = pageManager.getContainingPage(rootResource);

                }
                final SearchResults<Resource> results = ugcSearch.find("ugc-sc", resolver, ugcFilter, 1, 10000);
                for (final Resource res : results.getResults()) {
                    if (res != null) {
                        try {
                            final SocialComponentFactory factory = socialComponentFactoryManager.getSocialComponentFactory(res);


                            SocialComponent component = (factory != null) ? factory.getSocialComponent(res, request)
                                    : null;
                            if (component != null) {
                                arr.put(new JSONObject(component.toJSONString(false)));
                            }
                        } catch (Exception e) {

                        }
                    }
                }
            }
            obj.put("items", arr);
            SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
            Date date1 = new Date();

            obj.put("lastreloadtime",  dateFormatGmt.format(new Date()));
            response.setContentType("text/json");
            obj.write(response.getWriter());
        } catch (ParseException e) {
            //e.printStackTrace();
        } catch (RepositoryException e) {
           // e.printStackTrace();
        } catch (JSONException e) {
            //e.printStackTrace();
        }catch(Exception e){
           // e.printStackTrace(System.out);
            e.printStackTrace(response.getWriter());
        }
    }

    private UgcFilter getFilter(SlingHttpServletRequest request,String path) throws ParseException {
        final UgcFilter ugcFilter = new UgcFilter();
        final ConstraintGroup pathFilters = new ConstraintGroup();

        PathConstraint pathConstraint = new PathConstraint(path, PathConstraintType.IsDescendantNode,Operator.And);
        pathFilters.and(pathConstraint);
        SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
        dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
        String ltr= request.getParameter("lrt");
        ValueConstraint<Long> valueConstraint  = new ValueConstraint<Long>(SocialUtils.PN_DATE,dateFormatGmt.parse(ltr).getTime(),ComparisonType.GreaterThan);
        pathFilters.and(valueConstraint);
        ugcFilter.and(pathFilters);
        return ugcFilter;
    }
}

Avatar

Level 2

Hi Kalyanar,

Thanks for the sample, I will try it in my environment.

Two questions:

  1. In your sample, I will need to call this servlet by calling something like a PATH.sample.json. What will be the PATH of the resource in this case? For example, in the Geometrixx demo, it will work on what kind of resources?
  2. I don't understand the link between between the selector 'social' (http://localhost:4502/content/community-components/en/comments/jcr:content/content/comments.social.j...)and this sample?

Thanks for your help!

Matthieu

Avatar

Level 2

Hi Kalyanar,

I have tried and modified your sample for my needs. It works! Thanks for your help.

If  I traverse all nodes in the path "mywebsite/content", is it possible to determine if a page or a page content uses a social component?

Thanks,

Matthieu

Avatar

Employee

It will work for any path wiht this selector.