AEM 61 - Setup Groovy Scripts Debugging in IDEA for Felix Script Console

Goal


This post is on creating Data Sanity Check Scripts for a project's Runbook. There might be cases when you have to check the validity of CRX node structures (created manually or using CURL) before running pretty intensive logic on the node structures. Running such test scripts is to ensure any avoidable mistakes are found in advance, most of the times a simple query is good enough for finding out if the structure was created as expected; for example, to check if the nodes have property eaem:imageURL, the following sql2 query should suffice

SELECT * FROM [sling:OrderedFolder] WHERE ISDESCENDANTNODE('/content/dam/styles') AND [eaem:imageURL] IS NULL

For complex checks, you may have to provide a script to the customer (or run it yourself). One such check is, find if the nested node structure has duplicate nodes; the example discussed in next steps has style number node 1272336 mistakenly added in two places /content/dam/styles/accessories/1272336, /content/dam/styles/bottoms/1272336; These invalid node entries cannot be found using JCR queries (if you can write one, please leave a comment...)

There are many ways to create such a thing, but come with arguable disadvantages...

1) Http Servlet or JSP - Simple, but cannot be part of production packages; if code should be enhanced or bugs fixed, the customer may not be good with adding such packages on production systems, adhoc

2) DavEx Client or RMI Client - Easy to code and very useful for developers, but not all customers may have java installed locally to run it and also watch out for jdk version, linkage errors; gets real messy sometimes

There should be a simple way to create/run random scripts than can do sanity checks, handed over to the customer via email (yes!!) without the code being part of release cycles. Two ways of doing it, that i know of...

1) ACS AEM Tools Fiddle - Extremely useful on Dev, QA & Staging environments; but the Tools Team does not recommend installing it on production systems

2) Groovy Script Console - Lesser of two evils, a relatively secure and easy way to run random scripts; as the console is available to OSGI admins only, chances of doing something nasty corrupting the whole production system are minimal

This post is on adding Groovy Felix Script Console to AEM and creating/debugging the script in IDE Intellij IDEA to Find Duplicate Node Names in CRX

Thank you Chetan Mehrotra for the Groovy bundles and valuable tips

Demo | Groovy Script Console Package Install

Solution


1) Login to CRXDE Lite, install the Groovy Script Console Package or get the bundles here; Bundle for Script Console and Groovy Scripting Support bundle get installed



2) The console should now be accessible at http://localhost:4502/system/console/sc




3) Download the Groovy SDK installer or binary package and install it onto local file system eg. on windows - C:\dev\code\install\groovy-2.4.5

4) Create a plain Java module test-groovy in IntelliJ IDEA IDE and set the Dependencies to Groovy sdk, DavEx jars




5) Create file find-duplicates.groovy in module test-groovy and add the following code

import javax.jcr.*
import org.apache.jackrabbit.commons.JcrUtils

import javax.jcr.query.QueryResult
import javax.jcr.query.Row

import org.apache.sling.jcr.api.SlingRepository

Session session
def styles = [:] as HashMap

try {
    def queryStr = 'SELECT * FROM [sling:OrderedFolder] WHERE ISDESCENDANTNODE("/content/dam/styles")'

    //session = getSlingRepoSession()
    session = getDavExRepoSession()

    def qm = session.workspace.queryManager
    def query = qm.createQuery(queryStr,'JCR-SQL2')

    QueryResult result = query.execute()

    result.rows.each{
        Row r ->

        if (styles.containsKey(r.node.name)){
            println "Duplicate style number $r.node.name, path $r.node.path; Style Exists " + styles.get(r.node.name)
        }else{
            styles.put(r.node.name, r.node.path)
        }
    }
}catch(e){
    println e
}finally{
    session?.logout()
}

def getSlingRepoSession(){
    SlingRepository repo = osgi.getService(SlingRepository.class)
    return repo.loginAdministrative(null)
}

def getDavExRepoSession(){
    def REPO = "http://localhost:4502/crx/server"
    Repository repo = JcrUtils.getRepository(REPO)
    repo.login(new SimpleCredentials("admin", "admin".toCharArray()), "crx.default")
}

6) In the above script there are two ways of getting a JCR session; As shown in demo, uncomment #16, session = getDavExRepoSession() when debugging the script from IDE; Script executed in Felix Script Console (added in Project's Runbook) will have #15, session = getSlingRepoSession() uncommented



7) The script when executed in Felix Script Console for Groovy outputs the duplicate node names (styles) so that customer can correct node structures before initiating some process intensive execution...





No comments:

Post a Comment