Wednesday, 24 May 2017

AEM Search Suggestions

AEM provides out of the box Suggester API to populate suggestions for a particular keyword. com.day.cq.search.suggest.Suggester API provides methods to fetch suggestions and it provides a spell check feature as well.

An example would be:

import com.day.cq.search.suggest.Suggester;
import com.soh.services.SearchSuggestion;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.commons.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Session;

/**
 * SOH Search Suggester
 */
@Component
@Service(SearchSuggestion.class)
public class SearchSuggestionImpl implements SearchSuggestion {
    /**
     * The Suggester Index
     */
    private static final String INDEX = "oak-cq:Page";

    /**
     * CQ Suggester Reference
     */
    @Reference
    private Suggester suggester;

    /**
     * 
     * @param keyword
     *            to search for
     * @return JSONArray containing search suggestions
     */
    @Override
    public JSONArray getSuggestions(String keyword, int noOfItems, ResourceResolver resourceResolver) {
        final boolean spellCheck = true;
        final JSONArray suggestions = new JSONArray();
        final Session session = resourceResolver.adaptTo(Session.class);
        int counter = 0;
        for (final String suggestion : suggester.getSuggestions(session, INDEX, keyword, spellCheck)) {
            counter++;
            suggestions.put(suggestion);
            if (counter == noOfItems) {
                break;
            }
        }
        if (suggestions.length() < 1) {
            final String spellSuggestion = suggester.spellCheck(session, keyword);
            for (final String suggestion : suggester.getSuggestions(session, INDEX, spellSuggestion, spellCheck)) {
                counter++;
                suggestions.put(suggestion);
                if (counter == noOfItems) {
                    break;
                }
            }
        }

        return suggestions;
    }
}

Further, we can configure our index to specify which JCR properties do we want to include while populating suggestions. useInSuggest="{Boolean}true" is the property that we have to specify. Here is a sample index which includes jcr:title property in the suggestions:


<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:oak="http://jackrabbit.apache.org/oak/ns/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:rep="internal"
    jcr:mixinTypes="[rep:AccessControllable]"
    jcr:primaryType="nt:unstructured">
    <customLuceneIndex
        jcr:primaryType="oak:QueryIndexDefinition"
        async="async"
        evaluatePathRestrictions="{Boolean}true"
        includedPaths="[/content/myproject]"
        reindex="{Boolean}false"
        type="lucene">
        <analyzers jcr:primaryType="nt:unstructured">
            <default
                jcr:primaryType="nt:unstructured"
                class="org.apache.lucene.analysis.standard.StandardAnalyzer">
                <stopwords/>
            </default>
        </analyzers>
        <indexRules jcr:primaryType="nt:unstructured">
            <cq:Page jcr:primaryType="nt:unstructured">
                <properties jcr:primaryType="nt:unstructured">
                    <jcrTitle
                        jcr:primaryType="nt:unstructured"
                        name="jcr:content/jcr:title"
                        nodeScopeIndex="{Boolean}true"
                        ordered="{Boolean}false"
                        propertyIndex="{Boolean}true"
                        type="String"
                        useInSuggest="{Boolean}true"/>
                </properties>
            </cq:Page>
        </indexRules>
    </customLuceneIndex>
</jcr:root>



Hope this helps!

Monday, 22 May 2017

Too Many Calls Excpetion - AEM 6.2

If we have a number of components in our AEM 6.2 Author instance and we are also running samplecontent on our AEM, then we might encounter this error:

org.apache.sling.api.request.TooManyCallsException

This happens to occur when the number of components are typically more than 1000.

An ideal solution would be to restrict the number of components we use in an AEM instance and deleting the geometrixx content. However, there might come a use case where we are bound to deal with it.

Here are the configuration details which are needed to be taken care of:

1. Go to the Felix Configuration Managerh: http://localhost:4502/system/console/configMgr
2. Search for 'Apache Sling Main Servlet'
3. Edit the 'Number of calls per Request' - It should be high enough not to limit request processing and at the same time not too high not to break the mechanism to limit the resources in case of errors.


Tuesday, 4 October 2016

adaptTo() 2016 - Day 3

The third and final day at adaptTo() 2016. Finally the grand finale!

Session Details:
  • Managing Cloud Performance and Large Data sets by Mike Tilburg and Tom Blackford
  • OSGi R7 by Carsten Ziegeler and David Bosschaert
  • Test-driven development with AEM by Jan Wloka
  • Introduction to Sling Pipes by Nicolas Peltier
  • AC tool by Jochen Koschorke and Roland Gruber
  • APM - AEM Permission Management by Mateusz Chromiński
  • Using Thymeleaf for rendering HTML and Text in AEM 6.x by Oliver Lietz
  • Hey Sling, what are you doing? Sling Tracer to the rescue by Chetan Mehrotra
  • Apache Sling and Karaf for Web Sites and Applications by Oliver Lietz
Loved being a part of adaptTo() 2016!

Wednesday, 28 September 2016

adaptTo() 2016 Day 2

Another knowledgeable day at adaptTo() 2016 Berlin. The sessions started a bit early to accommodate all the speaker slots.

Sessions for Day 2:
  • How AEM Communities leverages and extends the power of Sling by Siddharth Palaniswami
  • Let’s run the whole Web on Apache Sling and Oak! by Bertrand Delacretaz and Chetan Mehrotra
  • Sling Http Testing Framework by Valentin Olteanu and Andrei Dulvac
  • Unit Testing with Sling & AEM Mocks by Stefan Seifert
  • Sling Context-Aware Configuration by Stefan Seifert
  • react components in AEM by Stefan Meyer
  • 0 to O(ak) in 30 by Davide Giannella
  • Playground Session featuring:
    1. Sling Core with Carsten Ziegeler & Stefan Seifert about Sling and OSGi in general 
    2. Sling Scripting with Rado Cotescu & Oliver Lietz about Sightly, Thymeleaf 
    3. DevOps with Bertrand Delacretaz & David Bosschaert & Georg Henzler about Sling/AEM Deployment and Automation 
    4. Tooling with Robert Munteanu & Oliver Lietz about Sling IDE, Karaf, Tools 
    5. Testing with Andrei Dulvac & Stefan Seifert about Integration Tests, Unit Tests, Sling Mocks
    6. JCR/Oak with Michael Dürig & Chetan Mehrotra about JCR and Oak
The playground session was indeed an amazing opportunity to get in touch with some of the great minds working on Sling, Oak, DevOps and JCR.

The event wrapped up with an awesome evening buffet and a round table conference for Sling developers.

What an eventful day indeed!

Tuesday, 27 September 2016

adaptTo() 2016 Day 1

2016 is the sixth edition of adaptTo() and this year's event is hosted at the Kulturbrauerei, Berlin, Germany.
The event primarily focuses on Apache Sling Framework, including Apache Jackrabbit and Apache Felix. Adobe Experience Manager Developers also benefit to a very high extent form this 3-day event since it covers details on how AEM is leveraging its underlying architecture.

Day 1 started with a lot of excitement. Developers and Attendees from different parts of the world gathered at the venue for this interactive community event.

Speakers got a red T-shirt and Attendees got a blue one!

Started with Opening notes from Carsten Ziegeler and Stefan Seifert followed by
  • Microservices and IoT with AEM by Carsten Zeigeler and David Bosschaert
  • Get The Flow by Conrad Wöltge and Dominik Süß
  • 5000+ unattended AEM installations in the last four years - is it DevOps? by Georg Henzler
  • Running AEM in Docker by Andrei Darashenka
  • HTL/Sightly Compilers and Tooling by Radu Cotescu
  • Sling IDE Tooling by Robert Munteanu
  • Integrating Apache Mahout with AEM by Rima Mittal and Ankit Gubrani - It was great to share our POC on the topic which can help various AEM clients with user based recommendations. Clone the code at Github.
  • Into the tar pit: a TarMK deep dive by Michael Dürig
  • Remote Resources by Vlad Bailescu











and this is how a knowledge filled Day 1 came to an end!

Looking forward to Day 2 at adaptTo() 2016!

Friday, 17 July 2015

Connecting AEM 6 with Microsoft SQL Server

Some old applications that you might want to migrate to AEM might still use SQL Server databases. Here are the steps to access an external SQL server from AEM 6:

Building the OSGI bundle for the JDBC driver:

1. Download the appropriate driver from here 
2. Unzip the downloaded driver.
3. Open eclipse indigo.
4. Click on File-> New -> Other -> Plugin from existing JAR archive 
5. Click on Add External and enter the path of the downloaded jar
6. Enter Plugin properties as shown here:
7. Observe the MANIFEST.MF, it shall look like this:
8. Save the project.
9. Right click the project --> Export --> Plug-in Development --> Deployable plug-ins and fragments
10. Choose a directory location --> Save.
11. The OSGI jar is available at the given-directory-location/plugins

Uploading the OSGI jar in felix:

1. Go to http://localhost:4502/system/console/bundles
2. Click on Install/Update
3. Upload the jar:
4. The jar should come in Active state. Look for errors in the error log if it still shows "Installed":
5. Error Log might show:
org.osgi.framework.BundleException: Unresolved constraint in bundle com.myproject.jdbc [398]: Unable to resolve 398.0: missing requirement [398.0] osgi.wiring.package; (&(osgi.wiring.package=javax.xml.transform.stream)(version>=1.3.0))
The bundle might also show unresolved dependencies:
6. Edit the MANIFEST.MF to remove the versions for resolving dependencies:
7. Re-install the bundle and it should be active now:


JDBC Connection Pool Factory config:

1. Go to http://localhost:4502/system/console/configMgr
2. click on "+" to add a configuration:
3. The configuration looks like this:





Test Connection:

1. An example code snippet for testing the connection:


Note: You might have to allow your Microsoft SQL server to accept remote connections! Please refer this

Hope this helps!!!






Monday, 18 May 2015

Hide extra component divs in CQ/AEM

This can be really tedious sometimes when, while developing a component in CQ/AEM, the extra CQ generated divs surrounding your component might disturb the HTML structure intended.

A common usecase is a carousel component in which, lets suppose, for every slide we drop in the carousel wrapper, no extra component div is required just to make sure the plugin driving the carousel runs fine.

An ideal structure would be :
<ul>
<li></li>
<li></li> 
<li></li>  
<li></li>
</ul>

If each li comes from a carousel slide component, here is what it looks like in cq:

<ul>
<div class="carousel-slide"><li></li</div>
<div class="carousel-slide"><li></li</div> 
<div class="carousel-slide"><li></li</div>  
<div class="carousel-slide"><li></li</div>
</ul>

This structure sometimes prevents the carousel JS plugins to stop behaving the way they should.

Solution:
One of the alternatives is to use cq:noDecoration="true", but that makes the component un-editable. Neither the editconfig not the dialog is visible.
Thus, an ideal approach would be :

Just before cq including the component, add this code snippet:

 <%
                        IncludeOptions opts = IncludeOptions.getOptions(request, true);
                        opts.setDecorationTagName("");

 %>
This would require an import:
<%@ page import="com.day.cq.wcm.api.components.IncludeOptions" %>

Now cq inlcude your component, for eg:

<cq:include path="slide"> resourceType="/component/content/carousel-slide"/>

Hope this helps!