Posts tagged "Rockstar"

April 19, 2018

Brett Birschbach #AEMRockstar 2018

It’s a wrap! Adobe Summit NA 2018 is done, and we are excited to announce the winner of this year’s #AEMRockstar competition:


Brett Birschbach from HS2 Solutions


This year brought more outstanding submissions than ever, resulting in a fantastic field of semi-finalists. Congratulations to Brett and our other finalists, Bryan Williams, Joost van Dun, and Conrad Woeltge, who competed in front of an audience of 300 AEM enthusiasts! 

Brett (a previous CM guest blogger) has written a great post about his winning Rockstar Tip & Trick. He is the lead Adobe Marketing Cloud Solutions Architect for HS2 Solutions, a digital transformation company based in Chicago. He is a hands-on problem solver with experience leading large multinational, multi-site platform projects. Read on below: 


AEM Remote Assets –

Sync What You Need, When You Need It


Have you ever wanted to use AEM Assets on one server from AEM Sites on another? I bet you have, even if you don’t realize it. Until now, options to do so would have been custom and/or manual, so you may have simply blinded yourself to the idea. Here are some common uses cases that you’ve probably run into:


Use Case: Enterprise AEM Assets Instance

Ok, I admit this is probably not the most “common” use case, but for large enterprises in the digital age, it’s a critical use case. An enterprise DAM is a key part of an enterprise technology stack, often calling for a dedicated AEM server with DAM as its sole purpose. But then how do you use those assets for your AEM sites?


Use Case: Migrating Assets from Production to Non-Production Environments

Does your organization have Dev/QA/Stage AEM environments? Of course, it does. Are those environments consistently up to date with the latest set of assets from production? For almost everyone I talk to, the answer is almost invariably a resounding “No.” How can this be done in a way that is both automated and disk efficient?


Use Case: Site Assets for Local Developer Servers (i.e., localhost:4502)

Pulling down a copy of the production site pages to a local server is easy. Pulling down all of the assets associated with that site? Not so much. How can this be done in a way that leaves behind assets that are not applicable to the site?

A simplistic, brute-force solution might be to use AEM’s package manager to bundle up the entire DAM, copy it down to the Sites server, and call it a day, right? Not exactly. Assets are big…and numerous… Last I checked, numerous big things is rarely a simple situation. Copying the entire DAM can be problematic in terms of disk space, network transfer, and effective package sizes. And even if you can do it manually, as soon the first asset on the remote server changes, you’re out of date!

Ok, so why not just reference the assets directly from their remote location? This would be a nightmare for your authors and developers, no longer able to leverage simple OOTB tools like image components, DAM search, and the authoring sidebar. Ultimately, you’d no longer be able to leverage the full power of AEM sites.

In short, you need a solution that achieves all of the following objectives:

  • Access to all remote AEM Assets from the AEM Sites instance
  • Remote AEM Assets stored locally in AEM Sites for seamless authoring w/OOTB features
  • Copies of just the required remote AEM Assets, not the entire DAM
  • All accomplished in an automated fashion


Sync What You Need, When You Need It

AEM Remote Assets tackles this tricky problem in a unique way. The seemingly opposed objectives of “Access to all remote AEM Assets” and “Copy of just the required remote AEM Assets” are achieved by a “sync what you need, when you need it” strategy. What this means is the automated asset sync first copies the entire node structure from the remote DAM, pulling in the tags and metadata of all of the remote assets but leaving behind the large binary files in the source DAM. If and when any of these assets are requested for a real use case, only then does Remote Assets copy the binary files “just in time” via a second sync, leaving behind all of the other asset binary files that are not needed.

Let’s see how this works in practice. AEM Remote Assets first syncs in the node structure of the remote AEM Assets, substituting in a small, temporary binary file to keep all unused assets very small compared to their real counterparts.

Admin user viewing folder of remote assets on an AEM Sites instance.

As an admin user on the AEM Sites instance, I can see all of the “remote” assets that have been synchronized from the remote AEM Assets server. And though an asset may say it is 500+ KB in size, in actuality it is far smaller due to the temporary binary file.

Now the true magic begins. Because we have synchronized in all of the remote asset nodes and tags, we have everything we need as an author to search and use those assets, and AEM will take care of pulling over the binary files for the ones I want to use. Say for example I open a browser and search for “Bike” assets. The system finds the two assets, but as the request is being processed it first pulls over the associated binary files from the remote Assets server, making those two assets now “real” on the Sites server.

Right: Author user viewing two searched assets; Left: Admin user viewing folder with searched assets now made “real.”

The same thing happens if I pull up the page authoring sidebar to add an image to my page.

Right: Author user choosing asset from page authoring sidebar; Left: Admin user viewing folder with referenced asset now made “real.”

This is amazing for the “Enterprise Remote AEM Assets” use case, where authoring sites with remote assets is a critical business function. But what about the use cases of “Migrating Assets from Production to Non-Production Environments” and “Site Assets for Local Developer Servers” where largely we just want to be able to browse the site with all assets. Turns out that scenario (and any others you can think of) works as well.

Right: Web page as seen by an author user, all assets being made “real” simply by browsing to the page; Left: Web page with remote assets before access by an author user.


This is Awesome! Can I Has AEM Remote Assets Too?

You absolutely can! HS2 Solutions has contributed AEM Remote Assets to ACS AEM Commons, the most prominent open source feature library for AEM in the industry. You’re probably using this library already! We look forward to the community pitching in with their ideas on configuration options, additional functionality, and even direct code contributions!

For more on AEM Remote Assets, including a video demonstration, view my article on You may also contact me via LinkedIn or email at

All opinions are Brett Birschbach’s own and are not Adobe’s.

4:31 PM Permalink
May 5, 2017

Generate Rockstar AEM Logs Metrics with R Programming Utility

Today’s Tips & Tricks guest post comes from Atish Jain, who is a Senior AEM Developer at SapientRazorfish (Publicis.Sapient) with over seven years of experience working with CMS based applications. Atish was a semi-finalist in this year’s AEM Rockstar competition. 

The tool I’m sharing is an R programming based utility to find gaps in renditions versus assets uploaded. This can be helpful in asserting the Bulk Migration, Longevity Tests success, Upload Activities, and Comparative Analysis in your AEM instance.

For those unfamiliar with R programming, it is a free open-source language and environment used for data manipulation, calculations, statistical computing, and graphical techniques useful to statisticians, analysts, data miners, and other researchers.  To learn more about R, visit

Trend analysis for upload vs. workflow completion and systems experience an increase in slowness with time. The stats can be analyzed to find missing assets reports and degradation in AEM server performance under continuous load. It works on the logs that are produced under crx-quickstart folder of AEM. Hence, there is no direct performance impact on the AEM instance. Also, reports can be generated over historical log files to produce and find comparative results, and do an analysis.

The utility helps you:

  • Analyze the exact count of missing Assets Renditions with the upload path that has been missed.
  • Conduct trend analysis for uploaded assets versus renditions generation. The pace of renditions generation can be calibrated for better insights for estimating activity timings and degradation factors.

The AEM logs are powerful and transformable to produce vital statistics. This utility, based on R programming language utilizes this power and generates metrics.

Here is how the utility works:

Step1: parses error.log(s) to subset log lines with date time – A

Step2: parses A to find log lines for upload trigger –B

Step3: parses A to find log lines for last rendition – C

Step4: merges B & C to create reports.

The concept detailed above can be enhanced into a more exhaustive application that can create extensive reports from AEM logs.

For example, the utility can be extended to generate more detailed graphical reports via the graphical plugin API available for R.

If you have any questions, you can contact Atish at All opinions expressed by Atish Jain and are his own and not Adobe’s.


QUICKSTART_LOGS_DIR <- "D:/Atish/aem-rock/output/logs"
OUTPUT_DIR <- "D:/Atish/aem-rock/results/day1"
print_renditions_gap_flag <- TRUE
upload_report_print_flag <- TRUE
RENDITION_LOG_TXT_PATTERN<- "jcr:content/renditions/cq5dam.web.1280.1280.jpeg"
ERROR_LOGS_FILE_PATTERN <- "error\\.log\\.\\d\\d\\d\\d*"
renditions_gap <- 0
error_log_files_list <- function(QUICKSTART_LOGS_DIR) {
error_file_list <- list.files(pattern = ERROR_LOGS_FILE_PATTERN)
error_file_list <- unlist(list(error_file_list,list.files(pattern = "error.log$")))

upload_report_calculation <- function(logs_dir){
dataset_upload <-NULL
dataset_workflowstart <-NULL
error_log_combined <- NULL
for (file in error_file_list){
print(paste("Analysing log file : ", file, sep=""))
error_log_full_dataset <- NULL
error_log_subsetdate_dataset <- NULL
dataset_x <- NULL
error_log_full_dataset <- read.table(file, header=FALSE, quote="", fill=TRUE)
colnames(error_log_full_dataset) <- c("date", "time", "level", "type", "class" , "logtext1", "logtext2", "logtext3", "assetPath")
#Filter rows which contains date only and assign it to error_log_subsetdate_dataset
error_log_subsetdate_dataset <- subset(error_log_full_dataset, grepl("\\d\\d.\\d\\d.\\d\\d\\d\\d", date))
write.csv(file="dataset.csv", x=error_log_subsetdate_dataset)
#Filter rows which contains *EXECUTE_START* and */content/dam/*
#Refine the above dataframe to contain only asset upload trigger log.
upload_trigger <- subset(error_log_subsetdate_dataset, grepl(UPLOAD_TRIGGER_TXT_PATTERN, logtext2))
upload_trigger <- subset(upload_trigger, grepl("*/content/dam/*", class))
#Filter rows which contains string:jcr:content/renditions/cq5dam.web.1280.1280.jpeg.
rendition_generation <- subset(error_log_subsetdate_dataset, grepl(RENDITION_LOG_TXT_PATTERN, assetPath))
#concatenate the data and time columns of subset data frames
upload_trigger$datetime <- paste(as.Date(upload_trigger$date,format='%d.%m.%Y'), upload_trigger$time, sep=" ")
rendition_generation$datetime <- paste(as.Date(rendition_generation$date,format='%d.%m.%Y'), rendition_generation$time, sep=" ")
renditions_gap <- renditions_gap + (nrow(upload_trigger) - nrow(rendition_generation))
upload_trigger_df <- data.frame(sub('.*:','',sub('/jcr.*', '', upload_trigger$class)), upload_trigger$datetime)
colnames(upload_trigger_df) <- c("assetPath","upload_trigger.datetime")
write.csv(file="upload_trigger_df.csv", x=upload_trigger_df)
#Prepare renditions generation dataframe
rendition_gen_df <- data.frame(gsub('.{49}$', '', rendition_generation$assetPath), rendition_generation$datetime)
colnames(rendition_gen_df) <- c("assetPath","rendition_generation.datetime")
write.csv(file="rendition_gen_df.csv", x=rendition_gen_df)
dataset_x <- merge(upload_trigger_df,rendition_gen_df,'assetPath',all.x=TRUE)
#Create a new data frame with assetPath, upload, rendition generation timings
dataset_x$timeDiff <- as.POSIXlt(dataset_x$rendition_generation.datetime, "%d-%m-%Y %H:%M:%S") - as.POSIXlt(dataset_x$upload_trigger.datetime, "%d-%m-%Y %H:%M:%S")
filename <- paste(file, ".csv", sep="")
dataset_upload <- rbind(dataset_upload,dataset_x) 
print_rendtions_gap_report <- function(renditions_gap, print_renditions_gap_flag) {
temp_var <- paste("Renditions gap vs uploaded assets: ", renditions_gap, sep="")

upload_report_print <- function(dataset_upload,upload_report_print_flag){
setwd(OUTPUT_DIR) <- apply(dataset_upload, 1, function(x){any(})
uploadAsset <- dataset_upload[!,]
write.csv(file="uploadAsset.csv", x=uploadAsset)
missingRenditions <- dataset_upload[,]
write.csv(file="missingRenditions.csv", x=missingRenditions)
barplot(as.matrix(uploadAsset$timeDiff), main="Time-Diff Report", xlab="AssetsUploaded", ylab= "timeLag(sec)", beside=TRUE, col=rainbow(1))
dev.copy2pdf(file = "TimeDiffReport.pdf")
# Functions Execution
error_file_list <- error_log_files_list(QUICKSTART_LOGS_DIR)
dataset_upload <- upload_report_calculation(QUICKSTART_LOGS_DIR)
print_rendtions_gap_report(renditions_gap, print_renditions_gap_flag)


4:52 PM Permalink
April 18, 2017

Be an #AEMRockstar: Use AEM DataLayer

Today’s guest post features the winner of our first AEM Rockstar Competition, Dan Klco of Perficient. Dan rocked Summit attendees with his presentation, so we asked him to share his DataLayer demo. In the coming weeks, we’ll share more AEM Rockstar posts and preview one semi-finalist’s IMMERSE presentation. Stay tuned!

Dan is an experienced Adobe Digital Marketing Technical Lead, Solution Architect, Consultant and Advisor. Through his career, he has become viewed as a valued thought leader in the industry, with solid skills in leading teams to implement successful digital marketing programs in the Adobe ecosystem. Dan is also a PMC Member of the Apache Sling project, which is the basis for Adobe’s Experience Manager product, this allows him unique insight into the AEM platform.

During the AEM Rockstar session at Adobe Summit, I had a chance to talk about Digital Marketing DataLayers in AEM. I discussed how this important design pattern can help simplify Adobe Experience Manager and Adobe Marketing Cloud integrations, and introduced AEM DataLayer, a new Open Source library for creating DataLayers in AEM.

I was thrilled to be awarded first prize for my presentation and would like to share some more with information with you about how to use the AEM DataLayer library on your project.

Step 1: Identifying Data to Track

In my talk, I discussed analyzing designs in the discovery phase, to identify what data you might need to capture for Digital Marketing. It is important to focus on the might rather than the need to ensure that your DataLayer will not require significant changes during the course of the implementation.

Given the page above, you may want to track some of the following information as an example:


Track Time




On Load


Page URL

On Load


Page Path


On Load


Site Section


On Load




On Load




On Load


Page Title

About Us

On Load






Video Play



Video Complete

Step 2: Configure AEM DataLayer

The AEM DataLayer is available as a downloadable AEM Package and is easy to install and incorporate into your project. Click here to watch my Spark video demo.

The steps to install and configure the AEM DataLayer are:

  1. Install the AEM DataLayer package
  2. Setup a Cloud Configuration for AEM DataLayer
  3. Add the Cloud Configuration on your site

Step 3: Add Your Custom DataLayer Code

To create your own DataLayer code, create a simple Bundle project and add the dependencies:













You can then create Sling Model classes implementing the ComponentDataElement interface:


@Model(adaptables = Resource.class, resourceType = {"myapp/components/myresource" }, adapters = ComponentDataElement.class)
public class CustomDataElement implements ComponentDataElement {

For every class, you will need to specify the annotation parameters “resourceType” and “adapters”. You can specify any number of resource types, and when AEM encounters a resource of the type specified, it will call your Sling Model.

The WeRetail Reference project contains a number of examples ComponentDataElement classes you can use as a base for your custom implementations. For example, if you wanted to track the video displayed in every instance of the video component you scoped in Step 1, you could create a class like the one below:

*  Copyright 2017 - Perficient
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  See the License for the specific language governing permissions and
*  limitations under the License.
package com.perficient.aem.weretail.datalayer;

import com.perficient.aem.datalayer.api.Component;
import com.perficient.aem.datalayer.api.ComponentDataElement;
import com.perficient.aem.datalayer.api.DataLayer;

* Adds in the video details for the AEM Mobile Video component into the
* AEMDataLayer
* @author danklco
@Model(adaptables = Resource.class, resourceType = {
"mobileapps/components/mobilevideo" }, adapters = ComponentDataElement.class)
public class MobileVideoComponent implements ComponentDataElement {

private final Resource resource;

public MobileVideoComponent(Resource resource) {
this.resource = resource;

public void updateDataLayer(DataLayer dataLayer) {

Component component = new Component();

ValueMap properties = resource.getValueMap();

component.addAttribute("video", properties.get("fileReference", String.class));


This Gist brought to you by gist-it.view rawweretail-reference/src/main/java/com/perficient/aem/weretail/datalayer/

Further Support

If you have any questions or comments about the AEM DataLayer, please open an issue on GitHub or message me on Twitter at @klcodanr. As the library matures, I will be building out more documentation and use cases on GitHub so please keep tuned!


2:26 PM Permalink
March 28, 2017

Dan Klco: #AEMRockstar 2017

If you haven’t heard already, Adobe Summit NA 2017 is in the books! As a result, we have the inaugural #AEMRockstar winner: Dan Klco from Perficient Digital.

The recorded session should be on the Summit online site for those that attended, with the presentations available for download as a PDF. Each finalist will also share their presentation in an upcoming guest post.

Final Results:

  1. Dan Klco, Perficient Digital
  2. Ruben Reusser,, Inc.
  3. Rima Mittal, Sapient
  4. Martin Fitch, Kaiser Permanente
    (tied) Robert Langridge, Dixons Carphone

Looking forward to next year.

1:29 PM Permalink
March 20, 2017

AEM Rockstar Tips & Tricks Blog Series

Our First AEM Rockstar Tips & Tricks Guest Blog!

Late last year we launched our first AEM Rockstar competition, where we asked for tips & tricks from you, the Rockstar AEM marketers and technologists who create and innovate within Adobe Experience Manager. Winners won a free pass to Summit and will present their tips & tricks to an audience of over 500 attendees and a panel of judges, who will award the best tip & trick winner with a cool prize! 

Thanks again to all the Rockstars who competed this year. If you are at Summit and want to attend the Rockstar session, on Wednesday, March 22, click here:!   We’ll see you at Summit!

We were rocked by the response to the Rockstar contest, but ultimately we could only choose five finalists to present at the 2017 Adobe Summit. However, we received so many impressive submissions from the AEM community that we decided to feature a series of guest blog posts, written by the runners-up. These tips & tricks range from favorite ways to use Forms, to more technical examples that can help you better synchronize content, use new tools, and much more.

Our first guest post comes from Sagar Sane, who is a Technical Architect at iCiDIGITAL (, a digital agency that specializes in AEM. He has over four years of experience working with AEM / CQ5; primarily focused on server-side development and integrations of AEM with other systems, and over five years of web development experience. He is based at the iCiDIGITAL location in Raleigh, North Carolina.

Grabbit – A Rockstar  Tool for Content Sync in AEM

Suppose you have an enterprise-scale AEM implementation with an author and multiple publishers in production. There is a staging environment mirroring closely to production from an infrastructure point of view, and you might even have development and UAT environments used for development and testing, respectively. The business stakeholders of your AEM implementation prefer that you keep the content synchronized as much as possible between these environments. Generally, you would use tools like Package Manager or vlt rcp to achieve this.

However, these tools do not scale well enough for large implementations where your AEM environments are geographically far away, or that have very large amounts of content to be synchronized. At the core, both these tools use the WebDAV protocol. WebDAV uses XML for serialization and deserialization and uses HTTP handshakes for every node that is synchronized between two AEM instances. This means that any latency on the network will hurt the content sync performance, in terms of time and space efficiency.

Grabbit: A Different Approach

The name Grabbit refers to this grabbing of content from one CQ/AEM instance and copying it to another. However, it also refers to Jackrabbit, the reference JCR 283 implementation that the content is being copied to and from. Grabbit is installed as any other AEM application and is available on bintray for anyone to download.

Grabbit takes a different approach to solve the problem of content synchronization. Grabbit’s goal is to make it easier and faster to sync content from one AEM instance (Grabbit Server) to another (Grabbit Client). Grabbit was developed as a content sync solution for one of our clients, with iCiDIGITAL members the primary contributors. Upon the success of the initial releases of the tool, Grabbit was ultimately open sourced by our client couple years ago.

How does it Work?

Unlike the other tools mentioned above that use HTTP handshakes for each node to be synced, Grabbit creates a stream of data over HTTP(s) from the Grabbit Server (source) to the Grabbit Client (destination). For serialization, Grabbit uses Google’s Protocol Buffers. Better than XML- based serialization, Protocol Buffers is extremely space efficient in transferring the data over the network. As its core underlying technology, Grabbit uses Spring Batch. Some of the core features of Spring Batch that Grabbit uses are Chunk-Based processing, Declarative I/O, start/stop a job and job processing statistics.

Grabbit needs to be installed on both the AEM instances; the instance that requests content to be copied to (the Grabbit Client) and the other one from which the content is copied from (the Grabbit Server). You initiate the request to copy content from Grabbit Server to Grabbit Client by providing a Configuration File to the client. For each path in the configuration file that needs to be synced, a new Grabbit Job is created on the Grabbit Client. Each job then opens only one HTTP(s) connection to the server and uses Protocol Buffers for data transfer marshaling / unmarshalling. There are several configuration parameters that can be set in the configuration file. You can find details about that here.

Grabbit also allows you to monitor the jobs on the client. The monitoring API provides basic information like the job start time/end time, current path, the number of nodes written, etc. Under the covers, Grabbit uses Spring Batch’s querying features for this. The job status is represented in JSON format as below:

To summarize, the basic sequence of Grabbit usage can be illustrated as below:

Why Use Grabbit?

Grabbit is supported for most of the newer AEM versions and is under active development. We have already received and continue to receive a lot of feedback to improve Grabbit. In our experience, Grabbit has proved to be 2 to 10 times faster than other content sync alternatives in AEM, depending on the network conditions and the amount of content being synchronized. I encourage the users of Grabbit to submit issues, questions, or comments on GitHub. We hope that you give Grabbit a shot and that it proves to be useful for everyone in the AEM Community. Post a comment if you have any questions!

1:18 PM Permalink
  • Authors

  • Archives

  • Developer Resources