Quantcast
Channel: AEM – Adobe Experience Manager Podcast
Viewing all 172 articles
Browse latest View live

AEM Podcast: ACS AEM Commons Deep Dive Part 4

0
0

05288_ACS-AEM-Commons-Deep-Dive_4
We continue with our series on ACS AEM Commons. You can check out our previous podcasts in the series here: An Introduction to ACS AEM Commons, An ACS AEM Commons Interview with Justin Edelson pt1, An ACS AEM Commons Interview with Justin Edelson pt2, and ACS AEM Commons Deep Dive Part 3. Joey also wrote up a good explanation of what ACS AEM Commons is. Here is a link to the ACS AEM Commons Github page to see more. In this podcast we talk about the following three features of ACS AEM Commons: System Notifications, Ensure Oak Index, and JCR Compare. If you have any specific features that you would like us to cover, then please don’t hesitate to send us an email at info@aempodcast.com.


Using Client Libraries and Avoiding jQuery Headaches

0
0

05287_Using Client Libraries and Avoiding jQuery Headaches in AEM
AEM provides a feature called client libraries to allow for managing CSS and JavaScript in your site.

  • It allows you to bundle your files into one large file so you have fewer requests on your pages.
  • It allows you to minify them to make the download less expensive and faster.
  • It allows you to “categorize” them so you can define dependencies and control the order in which they are loaded (this is mainly important for JavaScript).
  • It allows you to store the JavaScript that is component specific in the repository location of the components (/apps/projectname/components/componentname/clientlibs). You can then load them by referring to their category from the “dependencies” or “embed” property of the clientlibs in your front-end design under /etc/designs/projectname/clientlibs.

App-specific client library folders
It is a best practice to keep all application-related files in their application folder below /apps. It is also a best practice to deny access for website visitors to the /apps folder. To satisfy both best practices, create a client library folder below the /etc folder that embeds the client library
that is below /apps.

However there is one snag you need to be very wary of…

The front-end designers tend to develop their code based on a recent version of jQuery and forget to mention this as a dependency (sometimes this jQuery library is not even provided together with the front-end design)! What this means is that all the custom JavaScript you received needs this version of jQuery to work properly.

Most of Adobe Experience Manager’s edit functionalities are JavaScript-based and it also uses jQuery! However, AEM 6.0 comes bundled with jQuery version 1.11.0, which is kind of prehistoric.

/etc/clientlibs/foundation/jquery: categories: cq.jquery, dependencies:
granite.jquery
/etc/clientlibs/granite/jquery/granite: categories: granite.jquery, dependencies:
jquery, granite.utils
/etc/clientlibs/granite/jquery: categories: jquery
/etc/clientlibs/granite/jquery/js.txt
#base=source
1.11.0/jquery-1.11.0.js
browser/browser.js

You are loading the jQuery library from AEM itself when you include the following line in a (custom) page component:

as this standard JSP contains the following code:

But even if you don’t load it explicitly this way, if you load other client libraries from Adobe Experience Manager, it is quite possible that some of them depend on “cq.jquery” so the standard jQuery will get loaded after all.

So the extra challenge is:

  1. Make sure the correct jQuery version required by the front-end design is added to the client libraries used by your AEM site (to avoid getting strange design issues that do not occur in the original front-end design)
  2. Make sure it is loaded before any custom code (component-specific JavaScript, front-end design JavaScript)
  3. Make sure it doesn’t conflict with the jQuery functionality of AEM itself

Load correct jQuery version into the client libraries used by the design of your site

  1. Put all CSS and JavaScript of the front-end design into a “clientlibs” folder under “/etc/designs/projectname” and categorize it as “sitename.frontend” (add a multivalue String property “categories”)
  2. Add the correct front-end jQuery library to the client libraries used by the design of your site to make sure it gets loaded, but…
  3. Due to the dependencies of other (standard) client libraries, the old Adobe Experience Manager jQuery library version will still be loaded and this can lead to nasty conflicts.
    1. Do not attempt to categorize your new jQuery client library as cq.jquery in the hopes of preventing the old one from loading. It will still do. The only way this might work is to use the identical folder structure and file names as the standard AEM jQuery library. But it wouldn’t make sense and be very confusing to rename a newer version to “1.11.0/jquery-1.11.0.js”. So just don’t.
    2. Also it may not be a good idea to try to overlay the AEM native jQuery library in the first place as it is part of the platform and we may break native functionality this way. Even if we succeeded to “upgrade” the native jQuery library, all sites running on the server would then be forced to use this version and each site design could depend on another jQuery version.
    3. Do not attempt to create a custom overlay of /libs/foundation/components/page/stats.jsp so it no longer includes cq.jquery, but apps.yourproject.jquery and provide a specific clientlibrary folder under /etc/designs/projectname/clientlibs. As other AEM native client libraries will still mention dependency “cq.jquery”, the AEM native jQuery will keep on getting loaded.
  4. Accept that loading the native AEM jQuery 1.11.0 version is unavoidable.

Load correct jQuery version before any custom JavaScript is loaded (component-specific or general front-end design stuff).

  1. Put the correct jQuery library inside its own “jquery” subfolder in your “clientlibs” folder and categorize it as “sitename.jquery” (add a multivalue String property “categories”).
    1. Put the correct jQuery library inside its own “jquery” subfolder in your “clientlibs” folder and categorize it as “sitename.jquery” (add a multivalue String property “categories”) and make it depend on the AEM native client library “jquery” (add a multivalue String property “dependencies=’[jquery]’”) to make sure this one is loaded before the your custom front-end jQuery library.
      jquery
  2. Categorize all “clientlibs” folders on your custom components as “projectname.components” (add a multivalue String property “categories”). (You can optionally categorize them as “projectname.components.componentname” as well, should you need to load only clientlibs for a specific component somewhere.)
  3. Now the magic words… To the “clientlibs” folder of your site under “/etc/designs/projectname”.
    1. Add a multivalue String property “dependencies=’[sitename.jquery]’” to make sure the jQuery library required by your front-end design is loaded before your own site design client libraries (and therefore before any custom JavaScript).
    2. Add a multivalue String property “embed=’[sitename.components,cq.foundation]’” to make sure the client libraries of your custom components are loaded after the jQuery library of your front-end design but can still be bundled together with your other site design client libraries into one big JavaScript file and minified.
      clientlibs
  4. This still leaves that fact that you are loading two different jQuery versions at the same time and both probably use $, which is a cause for conflicts.

– Replaced all $ with $j in components related .js file which didn’t refer to AEM, CQ, Granite specific .js libraries.

Load correct jQuery version into the client libraries used by the design of your site.

  1. Replace all $ in your custom JavaScript (component-specific clientlibs with JavaScript files, front-end design JavaScript files) with another reference like “$j” to avoid that your custom code uses the native AEM jQuery that is assigned to $ and $CQ.
    1. Also communicate this to your front-end designer so he never ever uses $ in their front-end design for your Adobe Experience Manager project again.
  2. Lift the conflict between your front-end jQuery library and the one native to AEM (https://api.jquery.com/jquery.noconflict/ -> If for some reason two versions of jQuery are loaded (which is not recommended), calling $.noConflict( true ) from the second version will return the globally scoped jQuery variables to those of the first version.)
    1. Add a new JavaScript file “jquery.noconflict.js” to the “source” folder inside the “jquery” clientlib folder (which you created in the first point of the previous topic) in your front-end design “clientlibs” Make sure it gets loaded by mentioning it in the accompanying “js.txt” file. Inside this new JavaScript you put the code.

var $j = jQuery.noConflict(true);

Add debug code to the body of your generic page component to be able to easily
check if the correct jQuery version is being used.  Add code that will:

  1. Print the version of the jQuery libraries assigned to references $ and $CQ (hopefully the native Adobe Experience Manager one)
  2. Then load the custom JavaScript from your front-end design client libraries, which
    1. First loads the native AEM jQuery if it wasn’t already loaded (your front-end design depends on your custom design jQuery, which depends on the native AEM jQuery)
    2. Then loads your custom design jQuery and at the end executes the noConflict code, which assigns it to reference $j
    3. Then adds the custom JavaScript from your custom components
    4. And finally loads all remaining custom JavaScript from your front-end design
  3. Then prints the version of the jQuery libraries assigned to references $, $CQ and $j. Here you should see that $ and $CQ are still assigned to the native AEM jQuery version and the $j to your custom design jQuery version.

Before $.noConflict(true)

--%> var $log = $( "#log" ); $log.append( "

After $.noConflict(true)

" ); $log.append( "jQuery version linked to ($): " + $.fn.jquery + "
" ); $log.append( "jQuery version linked to ($CQ): " + $CQ.fn.jquery + "
" ); $log.append( "jQuery version linked to ($j): " + $j.fn.jquery + "
" ); --%>

For further client libraries debugging tools, check out this other AEM Podcast article on this topic.

ivo_eersels2Author bio
Ivo Eersels is an industrial engineer and has been a software engineer on the Intershop Suite 6 E-commerce platform at Osudio, one of Europe’s largest e-business specialists, since 2007. He has been working with AEM since 2013. Ivo plays a large role in setting up projects, DTAP servers, deployment strategies, guidelines, and development.

The Ins and Outs of Code Package Deployments in AEM

0
0

05287_The-Ins-and-Outs-of-Code-Package-Deployments-in-AEM
This page documents what to include in and what to leave out of Adobe Experience Manager code packages based on past experience. The contents of a code package can be configured in the file src/main/content/META-INF/vault/filter.xml. This file tells the AEM Package Manager which repository paths are included in the package and what to do with them at deployment time.

There are three supported import modes for the Package Manager:

  1. replace: Normal behavior. Existing content is replaced completely by the imported content, i.e., is overridden or deleted accordingly.
  2. merge: Existing content is not modified, i.e., only new content is added and none is deleted or modified.
  3. update: Existing content is only updated but never deleted.

Possible things to include

In case you wish to disable the “Target” context menu item on all components because clicking on it “breaks” the content component involved, then you are required to overlay this file and add line “config.disableTargeting = true;” to function addTargetingActions: function(items, ctrlDef, isTargeted, config).

In case you want to implement a custom 404 page, as described in Customizing errorhandler pages, it is normally located at “/apps/sling/servlet/errorhandler/404.jsp”.

Part that contains the custom code you are running. This should always be in your code package.

By including this node in your code package, you can deploy Dispatcher Flush pages (previously created on a development environment) to all other Adobe Experience Manager (DTAP) environments.

This node contains the active contextstores available to your site.

Here you list the folders that are used by your site’s front-end design.

Possible subfolders to include could be:

  • clientlibs: client libraries used by your site
  • frontend: this folder should always be included in your code package. It should contain an info.html file has a link to the front-end design used on your site. The front-end design itself is hosted on a dedicated front-end server that contains the static html.
  • icons
  • images

Here you can store any mail templates used by custom workflows.

Node containing custom workflow to allow for storing the content entered by the customer and also send it as an email to a specified email address.

Customization of DAM Update Asset workflow (to generate a custom rendition).

Things to exclude

Only add this to your code package in the initial (go-live) release!
In the repository you will find a jcr:content node right under /etc/designs/, which contains content information like the URL to the logo image, settings of which components are allowed in which paragraphs on which templates, which (custom) clientcontext to use, etc… Should you include this repository path in your code package, this means that everything under this level will be overwritten with the content from your package (info not in the package is deleted on the server!).

Of course this is the desired behavior in case you are deploying design changes to the AEM server, but you will lose all the above mentioned information in the process. And as this is all content that can be configured by content authors; you should not store it in source code management and deploy with your package as this content can change over time, even between code releases.

So this is why you should place all front-end design related files in subfolders, allowing you to include these in the code package and avoid deploying to the root level of your design on the Adobe Experience Manager server. (You can’t fix this by adding import mode “merge” to the filter pointing to the root path of your design, as this would mean that only new files are added and existing design files are never deleted NOR MODIFIED.)

However, you do need to make sure the root of the design gets deployed at least once—otherwise the jcr:content node at the root of the /etc/designs/ folder might not be created, and it is under there that all design settings are stored.

This repository node contains all the tags that are created on the AEM server. As these can be created by content authors and used on pages, assets, etc.,you don’t want to have this information in your code package. This tends to change over time between releases, and if you deploy this, all tags not mentioned in the package are deleted!

The clientcontext can also be configured by the content author using clientcontext content components. When including this in the code package, you again risk resetting this content on the AEM server.

ivo_eersels2Author bio
Ivo Eersels is an industrial engineer and has been a software engineer on the Intershop Suite 6 E-commerce platform at Osudio, one of Europe’s largest e-business specialists, since 2007. He has been working with AEM since 2013. Ivo plays a large role in setting up projects, DTAP servers, deployment strategies, guidelines, and development.

Simple Touch UI Dialog Extensions for AEM

0
0

05287_Simple-Touch-UI-Dialog-Extensions-for-AEM
While there are a number of tools at a developer’s disposal to create clean, engaging dialogs within AEM, there are times when you may need to extend dialog functionalities in your Adobe Experience Manager implementation to suit your clients’ needs. Oftentimes, this can be achieved without too much effort.

As an exercise, we’ll use AEM 6.0 to create a Touch UI dialog. This dialog will contain a checkbox that toggles the visibility of a container that holds additional authorable fields.

Setting up the Dialog
There are two nodes that will be required to make our toggleable container in our Touch UI dialog: the toggle and the toggleable container itself. Each has its own important attributes. Let’s take a look at the cq:dialog.

We’ll start with the checkbox toggle:

There are a few key attributes that we want to look at here:

  • The “class” attribute will add that class to the checkbox when the dialog is rendered. This will allow us to target that checkbox later using JavaScript, allowing us to listen for any events on the checkbox. We’re using “showhide” as our class name.
  • The “value” attribute determines what the value of the checkbox will be when the checkbox is toggled.
  • The “showhide-target” will create a “data-showhide-target” attribute in our checkbox’s markup when the dialog is rendered. Our JavaScript will use this value to determine what it is we are trying to show or hide. We’ll target elements with the class name of “.showhide-target” for this example.

Let’s take a look at our toggleable container:


    
        
        
    

Above, we have a container with two textfields inside. We want to be able to show or hide this container dependent on whether or not our checkbox is checked. This container has two important attributes pertaining to our experiment:

  • The container’s “class” attribute will add the “showhide-target” class. Notice that this is the same class name that we are using in the “showhide-target” attribute of the checkbox. The toggle will target this container because of this class.
  • The “showhide-target-value” will create a “data-showhide-target” in our container’s markup when the dialog is rendered. This attribute will be set to the same value as the “value” attribute used in the checkbox. Our logic will check to see that our target container’s value of “true” matches that of the checkbox. If the checkbox is checked, they will match and we’ll show the container. If not, we’ll hide it.

Extending the Component with JavaScript
Our JavaScript will need to be added to a “cq:ClientLibraryFolder” that belongs to the “cq.authoring.dialog” category and depends on the “granite.jquery” client library. Let’s break down some of its functionality.

First, we’ll look at our event listeners.

$(document).on("foundation-contentloaded", function (e) {
  $(".showhide").each(function () {
    showHide($(this));
  });
});

$(document).on("change", ".showhide", function (e) {
  showHide($(this));
});

We’ve set up two listeners here. Our first will listen for the creation of our dialog (the “foundation-contentloaded” event). It will check for any toggle we may have set up and call the showHide function, passing the toggle object as a parameter. (Note: This allows us to see if a toggle is already checked when it is rendered. If it is, we’ll go ahead and show our toggleable container from the get-go.)

The second listener will look for any changes to the toggle. If a change event is triggered, we’ll again call the showHide function, passing the toggle object as a parameter.

Notice that we are looking for the “showhide” class in both listeners, which is the same class we gave to the checkbox toggle.

The showHide function is what is going to do the majority of the work:

function showHide(el) {
  var target = el.data("showhideTarget"),
    value = el.prop("checked") ? el.val() : "";

  // hide all targets by default
  $(target).not(".hide").addClass("hide");

  // show any targets with a matching target value
  $(target).filter("[data-showhide-target-value=\"" + value + "\"]").removeClass("hide");
}

This function will take the value of the checkbox (el) and compare it to the “data-showhide-target-value” of the toggleable container (target). If the values match, we’ll remove any “hide” class associated with the toggleable container. Otherwise, we’ll add that “hide” class to the container, which will hide it.

Here is a look at the JavaScript in its entirety:

(function (document, $) {
  "use strict";

  // listen for dialog injection
  $(document).on("foundation-contentloaded", function (e) {
    $(".showhide").each(function () {
      showHide($(this));
    });
  });

  // listen for toggle change
  $(document).on("change", ".showhide", function (e) {
    showHide($(this));
  });

  // show/hide our target depending on toggle state
  function showHide(el) {
    var target = el.data("showhideTarget"),
      value = el.prop("checked") ? el.val() : "";

    // hide all targets by default
    $(target).not(".hide").addClass("hide");

    // show any targets with a matching target value
    $(target).filter("[data-showhide-target-value=\"" + value + "\"]").removeClass("hide");
  }

})(document, Granite.$);

Through this simple exercise, you can see how easy it can be to build out more complex dialogs, allowing for a much improved authoring experience for your clients. We have talked about how we at Axis41 have extended some simple, out-of-the-box Adobe Experience Manager components in a prior blog post by Peter Nash. If you have other ideas about how to extend components or want to take a crack at sharing your method for extending more complex dialogs, then drop a line to info@aempodcast.com.

AEM 6.1 Service Pack 1 Released

0
0

AEM-6-Service-Pack-1-Released
We’ve been waiting anxiously for Service Pack 1 for AEM 6.1 environments, and are happy to announce that it has been released. This hotfix includes many important updates, including Jackrabbit Oak version 1.2.7 (which brings both stability and performance improvements); a host of Touch-UI updates; and a number of other critical updates.

Customers of Axis41’s AEM Managed Services offering are already receiving this update from their Systems Engineers. We recommend you deploy this hotfix in your pre-production environments and perform a full QA cycle before deploying it to your production environments.

If you have questions about the service pack, or would like help getting it deployed in your own environments, please reach out to us via systems@axis41.com.

JCR Compare: A Quick Review

0
0

05287_JCR-Compare_A-Quick-Review
We did a podcast about the JCR Compare in which we talked about the usefulness of this feature. Here is a written breakdown of that podcast for this specific ACS AEM Commons feature.

What is it?
From the ACS Adobe Experience Manager Commons GitHub page: “Quickly compares the contents of Adobe Experience Manager instances. JCR Compare computes checksums for specified node types (via an aggregated checksum of that node’s descendants) across multiple AEM instances and then compares the checksum results to identify what node (and node sub-systems) are the same or different.

This is a useful tool for checking for content inconsistencies across Adobe Experience Manager instances that would be otherwise difficult to find.”

How it works
You tell an AEM instance where it should find the instance to compare itself to, and define a number of useful comparisons to run, including based on a recursive path crawl, a JCR query, a list of known nodeTypes to include or exclude, and so on. It uses smart aggregate hashing to do the comparison and gives you the ability to drill into results to identify exactly what has changed.

Audience Impact (authors, devs, admins)

  • Devs – Allows them to see if they missed something in the migration or development phase
  • Authors – Allows them to verify what was changed between two environments
  • Admins – Allows them to quickly smoke test auto-scaled instances

Example application
Backup verification for a SysAdmin via curl. Or if you need to have a content author verify/validate two different Author or Publish instances to see if content has gotten out of sync between them (this assumes a clustered environment).

Named Transform Image Servlet: A Quick Review

0
0

05287_Named-Transform-Image-Servlet
We did a podcast about the Named Transform Image Servlet a while ago in which we talked about the usefulness of this feature. Here is a written breakdown of that podcast for this specific ACS AEM Commons feature.

What is it?
From the ACS GitHub page about Named Transform Image Servlet: “Many website designs demands consistency of images based on their use within components. For example, a panoramic spotlight may demand the image be 960 × 400, and bio picture must be 100 × 100 and greyscale.

The ACS AEM Commons Named Transform Image Servlet allows specific image transforms to be defined centrally via OSGi configurations. These image transforms can be easily invoked via parameterized HTTP GET requests to image resources in AEM.”

How it works
You create an OSGi configuration that has a name and a set of predetermined image transformations; examples might include resizing, cropping, rotating, making grayscales, etc. At the time the image is referenced, you can append this named transform to the image just by using the correct Sling selector syntax. The GitHub page gives a lot of default transform options.

Audience impact (authors, devs)

  • Devs – set up the transforms
  • Authors – choose them in the way they do their asset references

Example application
Let’s imagine a site where each article has a “Featured Image”; these images fit well-defined parameters, but the original source images will be uploaded in 4k resolution. Every time a new article is published, we want it to get an equal share to appear in the main page’s carousel. We could require the authors to go in directly and crop the image to the desired dimensions, but since we decided that we’ll have rules around the kinds of images that can be uploaded, we might just want Adobe Experience Manager to do that work for us. In this case, we might define a new transform called “carousel”, and the appropriate component could then reference the article’s “Featured Image” with this transform applied; we now have a usable carousel image for every article, without requiring a human to perform the desired crops and resizes.

Ensure Oak Index: A Quick Review

0
0

05287_Ensure-Oak-Index_A-Quick-Review
We did a podcast about the Ensure Oak Index in which we talked about the usefulness of this feature. Here is a written breakdown of that podcast for this specific ACS Adobe Experience Manager Commons feature.

What is it?
From the ACS GitHub page about Ensure Oak Index: “The Oak repository used by Adobe Experience Manager 6, allows from fine tuning of search performance via the definition of Oak Index definitions. The index definition nodes, usually stored under /oak:index, define the index and also store the index data (in a node structure invisible to the AEM tooling).

Ideally the Oak Index definitions used by an application could be stored with in the application’s content package, however, it is possible (and even likely) that upon deployment the content packages index definition may wipe out the actual index data (again, invisible via Adobe Experience Manager tooling) when updating the node, necessitating a reindex, which depending on the repository size and index configuration can be costly (and generally unnecessary).

Ensure Oak Index is tooling that allows Oak Index Definitions (referred to in this document as Ensure Definitions) to be defined in a content package, and then safely translated to real Oak Indexes.”

Said another way, Oak indexing in Adobe Experience Manager 6.0+ allows tuning performance; however, the control of how and when these indexes are created has only been binary to this point—once the /oak:index nodes are created, you can end up immediately performing a very expensive indexing operation. The Ensure Oak Index feature provides finer-grained control of when—and how—these indexes are rebuilt.

How it works
You create nodes of type oak:Unstructured; other than that, the nodes should emulate the structure of the equivalent /oak:index nodes, but adding new boolean properties to provide the finer-grained control. These new properties are: ignore, delete, forceReindex, and recreateOnUpdate.

Audience impact (devs, admins)

  • Admins – Gives better control over when packages can cause potentially disruptive reindexing
  • Devs – Define Ensure indexes as part of their process

Example Application
This is a good tool for the cases when it may take a long time for your indexes to stabilize. While that process is taking place, your production site can run slow, so you can use this tool to let those indexes stabilize in a separate environment and then deploy those stabilized indexes to your production environment with a smaller impact.


AEM Podcast: Java Deserialization Bug

0
0

AEM-Podcast_Java-Deserialization-Bug
Back on January 20, 2016, Adobe released a critical security hotfix to correct a vulnerability/flaw regarding Java deserialization. The day it was released, Joey wrote up a blog post about it (and made me post it up before I could go home), urging everyone to get it installed as quickly as possible. In the post we linked to some documentation explaining the issue, but we felt that it would be a good idea to discuss it via the podcast as well because this is such an important fix. In this podcast we get a little more in depth about:

  • what the issue is
  • why it is such a big deal
  • problems that might occur if you put it in your Adobe Experience Manager environment
  • how to ensure it was installed correctly
  • what you should do if you run into problems

This fix has been rolled into the Service Pack 1 release, but at this point in time Adobe is not yet shipping AEM with SP1 pre-installed. My guess is that Adobe Experience Manager 6.2 will have it baked in.

The AEM Podcast Team Is Attending Adobe Summit 2016

0
0

05287_AEM-Podcast-Team-is-Attending-Adobe-Summit-2016
The AEM Podcast team is coming to Adobe Summit 2016 in Las Vegas, Nevada, March 21–24. We will be at the convention every day to answer questions about Adobe Experience Manager, and other Adobe Marketing Cloud solutions, at the Axis41 booth. Please stop by and say hi to us (Joey and Peter). We would love to hear how you are doing your AEM implementation and discuss possible ideas for future podcasts.

For the fourth year in a row, Axis41 is a major sponsor for Summit (twice Gold and twice Platinum), and as such will be presenting at one of the breakout sessions with our partner/customer Pacific Dental. Our presentation is titled: 495 customizable websites, all on brand, in less than 100 days? Here’s how.

The Adobe Summit Axis41 Presentation:

Pacific Dental Services® has a unique business model. It supports dentist-owned practices in expressing their own style while still maintaining a unified brand image. So how do you apply this same “flexibility within a brand framework” to the office websites? How do you coordinate a large number of websites that are simultaneously similarly branded and unique? And how do you launch all of this in a short time?

By leveraging Adobe Experience Manager, Pacific Dental Services and Axis41® did what experts said couldn’t be done: 495 customized sites in 100 days.

In this session you will learn about:

  • Building and managing 495 independent-domain website properties under one platform and brand
  • Offering creative flexibility to make each site customizable within a unified brand framework
  • Leveraging Adobe Experience Manager and Axis41 to do what technology and market research experts said they hadn’t seen an implementation partner achieve before: execute this, and do it in record time

Presenters:
Kem Elbrader – Chief Software Architect, Axis41
Matt Hall – Vice President of Marketing, Pacific Dental Services

AEM Podcast: AEM Mobile – What, Why, and How, with Klaasjan Tukker and Nick Bogaty

0
0

AEMPodcast_AEM-Mobile_WhatWhyHow_KlaasjanTukker_NickBogaty
We recently had the opportunity to attend a workshop put on by Adobe in San Jose, California, for various Partners, about the new Adobe Experience Manager Mobile. Adobe then followed up with an onsite visit to Axis41, and Klaasjan Tukker, Senior Manager for the AEM Mobile Technical Marketing Team, and Nick Bogaty, General Manager for AEM Mobile, were gracious enough to sit down with us to discuss the new AEM Mobile. Don’t worry, it wasn’t a sales pitch. We discussed:

  • What exactly is contained in this new AEM Capability
  • Why it was combined with DPS
  • Is PhoneGap no longer available to use?
  • What do you need to deploy this?
  • The feature release schedule

And lastly, both Klaasjan and Nick were very eager to hear from people using the product with possible feature requests. In the podcast they shared their email address and encouraged people to contact them. For spam reasons, I won’t be writing it out here. :) And if you are interested, here is a link to where you can sign up for a trial program of AEM Mobile.

image2_revised_smaller
From left to right: Peter Nash, Nick Bogaty, Klaasjan Tukker, and Joey Smith

Deactivate and then Delete

0
0

05287_Deactivate-then-Delete

TLDR; This is a Public Service Announcement to all Adobe Experience Manager users: don’t just delete content from the Author instance. Make sure you deactivate/unpublish it first.

When I first started working with Adobe Experience Manager, I frequently made the mistake of just deleting a page or asset or tag. Deleting just makes everything go away, right? Wrong! I would then have to go to a developer or server admin when I couldn’t figure out why my piece of content was still on the Dispatcher end of the site. After a while, we figured out that the problem came when I would delete something that had been activated. I needed to deactivate the content first, and then I could delete it.

The reason for this is because of the structure of the servers in Adobe Experience Manager. You have an Author server that sends data, ready for the live site, up to a Publish server. The Publish server then serves it up through the Dispatcher. Deactivating something will remove it from the Publish server. It helps to understand that the Publish server only holds those things (pieces of content/assets) that belong on the live site. They are not the staging area for your content; that’s what the Author server does. Publish only wants to hold those things that a front-end user should be able to access. Deactivation is deletion for the Publish server.

Some people have said that if I hit delete then it should deactivate it for me and then remove it from the Publish server. It’s hard to argue against this. I struggle to come up with a legitimate reason to argue for this “feature”. I’m not even going to waste time trying to be the apologist and come up with a legitimate reason for this. Quite simply, it’s bad. Hopefully this will be something that Adobe fixes in future releases. As of Adobe Experience Manager 6.1, it is still an issue.

A Workaround
Ok, so what happens if you get stuck and you don’t have access to the Publish server (most of the time your Publish instance should be locked down anyway)? And let’s assume that this isn’t the first time that this has happened and you don’t want to go talk to the server admin who controls the Publish instance. In our scenario, you have just deleted a page that had previously been activated. A solution is to create a new page on Author with the same name. Then activate/publish it. And lastly, deactivate/unpublish it. Viola, your orphaned page is removed from the Publish server. What happens is that the Publish server looks at the node name and at the node type that is requested to be deactivated. So, if it matches, then it will be removed. This only works if you know what the exact name and type (asset or page type) was. It doesn’t really care about anything else. What is happening here is that you are trying to reconnect the communication between Author and Publish because the deletion severed that connection. Truthfully, I would just bite the bullet and go talk to the server admin.

It’s annoying that this is the procedure that has to be used. But in honesty, I learned about it and now it is part of my normal routine, and I make sure it is part of my customer’s routine too. I know better than to make this mistake anymore. So, let this be your mantra when working with content authors: Deactivate and THEN Delete. And since the name changed in the Touch UI, Unpublish and then Delete. Annoying, yes, but a much better option than having to get a server admin or a developer to go into the Publish instance to remove your piece of content. If you know of any other Adobe Experience Manager gotchas then drop us an email: info@aempodcast.com.

Why are you in CRXDE on Prod?

0
0

05287_WhyCRXDE_onProd_2
It seems weird that I even need to write this blog post, but too many times this issue has come up when we have: worked with other Adobe Experience Manager development teams, taken over projects for other AEM development teams, had sales calls with potential customers who already have Adobe Experience Manager, or learned that our own teams were doing this. Why are people working directly inside CRXDE on their Adobe Experience Manager Production environment? And lest you think this is only about development, this has taken the form of authoring as well.

It’s true that when a developer is in the middle of their development cycle that it is frankly faster and easier to be in CRXDE manipulating the code rather than going through a build process. You get to see your result much faster. It’s totally ok. But this should only be done through a Dev lane. Stage and Production should only get code via an automated deployment process or manually through the Package Manager.

I remember a T-shirt that a friend used to wear: “I don’t always test my code, but when I do, it’s in production.” It’s funny because it’s ridiculous (no self-respecting developer would do that) and because somewhere deep down where we don’t want to talk about it, we’ve all done it. We’ve all done it!

There is something fundamentally wrong with your implementation and process if you find yourself going into CRXDE on a regular basis, either to manipulate content or to modify code. I am reminded of a customer who explained the process of updating some piece of content. I was a little shocked when he casually told me that he went into CRXDE to change the address and phone number. I was even more shocked when I learned that the reason he did it is because there was no authoring interface for him to do it! That’s just sloppy/lazy development. Now, before we get too high on our soapbox, I don’t know what constraints the developer was given. Maybe the customer was out of money and there wasn’t any other choice. Or maybe it was another reason completely. It’s still a bad thing to do.

One of my early AEM projects provides another example. Occasionally the customer would need to change the publish time of an article, but the only way to do it was for me to go and modify the epoch within CRXDE because there was no authoring interface. Shocking, I know, from someone writing a post demonizing those who don’t architect appropriate solutions. Didn’t we always do things perfectly? I guess not. In our case, we just didn’t plan for it, because we didn’t know there would be a business case around that.

But let’s stop giving excuses. It’s not what should be done. We all know it. Don’t architect solutions that force authors to work on content in CRXDE. And, don’t manually make changes to code in CRXDE on Production. Just stop doing it. End of line.

Parity Restored: IntelliJ Gets AEM Plugin

0
0

05287_WhyCRXDE_onProd_2

One of the things I love about working at Axis41 is that we’re very tool-neutral. Some of our developers really love their Eclipse configuration, and may have been toting it around with them for years. Myself, I am more of a minimalist, and prefer Sublime Text. But a large segment of our development teams prefers to use Jetbrains’ IntelliJ IDEA, so when Adobe announced their Adobe Experience Manager plug-in for Eclipse last year, things got a little bit unbalanced.

That’s why I was excited when Ruben Reusser, CTO of headwire (which hosts both aemsolrsearch.com and Adobe CQ Blueprints) tracked us down at Adobe Summit last month to share with us the news that his team had developed an equivalent plug-in for IntelliJ users.

I took some time last week and poked around in it; as I mentioned, I’m not a hard-core IntelliJ fan most of the time, but it’s very cool to see the work Ruben’s team has put into this plug-in. I had some initial issues getting the latest snapshot to work with my IntelliJ, but one quick GitHub issue later, and I was able to get working with the tool. It’s not yet quite as polished as Adobe’s Eclipse plug-in (which is suggested by the 0.6 version number), but the team at headwire is being very responsive to issues. If you’re a developer who likes to use IntelliJ to work with Adobe Experience Manager, I encourage you to try out the plug-in and get involved in improving it by filing tickets.

Thanks to the team at headwire for sharing their work on this tool!

AEM Podcast: Pacific Dental Services – Filling your content management cavities with AEM

0
0

05287_AEM-Podcast-Pacific-Dental-Services
Just prior to Adobe Summit 2016, we were able to sit down with Matt Hall, Vice President of Marketing for Pacific Dental Services, who partnered with Axis41 at Adobe Summit 2016 to present at one of the breakout sessions. In this podcast Matt spent some time with Joey and I discussing the reasons that they chose Adobe Experience Manager to accomplish their need to supply websites for 495 individual dentist offices.

Also discussed were:

  • PDS business goals
  • Using analytics data to make the best business decisions for user experience
  • What part the PDS IT team played and what part Axis41 played
  • How content is updated across 495 sites
  • What PDS looked for in an implementation partner
  • Next things on the roadmap for PDS

At the end of the podcast Matt told us about Charity Water and why Pacific Dental wants to be part of helping the world get clean water. If you wish to donate then you can go to Charity Water’s website.

05287_AEM-Podcast-Pacific-Dental-Services_Article-Image
From left to right: Joey Smith, Matt Hall, and Peter Nash

Would you like to be interviewed on AEM Podcast or do you have an AEM question? Reach out to us at info@aempodcast.com or on Twitter @axis41 and we’ll see what we can do.


AEM Podcast team presenting at Boston AEM Meetup Group

0
0

05287_Joey-and-Peter-AEM-Meetup-Boston
Joey and I will be attending and presenting at the “Adobe AEM (CQ, CQ5) Developer Community in New England” Meetup Group April 26. If you are in the Boston area then you should come join. We will be out there for a couple of days and would love to be able to connect with anyone out there while we are in town.

We have a new mobile recording device and are itching to try it out. If you have something you want to podcast with us about while we are there then please let us know and we will try to make time to meet with you. Otherwise we’ll just end up sight-seeing or something else that will get us in trouble with our boss. :) Send us an email (info@aempodcast.com) or reach out via twitter @axis41.

Versioning ClientLibs in AEM

0
0

05287_Versioning-ClientLibs-in-AEM
Recently in a project I was working on, we had the need to cache our clientlibs and have them reliably recache every time there was a change. I looked around and found that there is an ACS AEM Commons tool made for just this purpose. In this post I’ll demonstrate how we went about using this tool to version our clientlibs.

The Versioned ClientLibs ACS AEM Commons feature uses a Sling rewriter to add an MD5 hash to the paths of your clientlibs, forcing them to recache after every modification. Typically Adobe Experience Manager will use the lastModified property to determine when to recache, however versioned-clientlibs is a more reliable approach.

To implement the versioned-clientlibs feature, simply copy the node from /libs/cq/config/rewriter/default to some path inside your application. In this example, we’ll choose /apps/acslibs/config/rewriter. For the most part this path is arbitrary, however the config node must be inside a four-level-deep path that ends in config/rewriter to work.

Your config file should be named versioned-clientlibs.xml and should look something like this:


    

Along with your config for the versioned-clientlibs, you should also copy down the default config node and make sure versioned-clientlibs is added to the transformTypes. Here’s an example of the content.xml for the default config:


    
        
        
        
    

If you want to validate whether your configuration was successful, you can check the Sling Rewriter tab in the OSGI Web Console (/system/console/status-slingrewriter). Under “Active Configurations” you should see a configuration section for the versioned-clientlibs.

Versioned ClientLibs
defaultclientlibs

Default
versionedclientlibs

Along with the rewriter configuration, you’ll also need to configure Apache to send the right headers. Here’s an example of what the config should look like:

SetEnvIf Request_URI "(\.min)?\.[a-f0-9]+\.js" long_expires=true
    SetEnvIf Request_URI "(\.min)?\.[a-f0-9]+\.css" long_expires=true
    Header set Cache-Control max-age=2592000 env=long_expires

That’s it. Now your clientlibs should recompile every time there’s a change to them.

It should be noted that per the ACS Adobe Experience Manager Commons documentation there are exceptions to which files this rewriter will support. These are the files this rewriter will NOT support:

  • URIs embedded in CSS or JavaScript, including: background-images, web fonts, etc.
  • Relative URIs, e.g., etc/clientlibs/mysite/styles.css
  • URIs including a scheme or protocol-relative location, e.g., http://example.com/etc/clientlibs/mysite/styles.css and //example.com/etc/clientlibs/mysite/styles.css
  • URIs to non-AEM HtmlClientLibrary resources, e.g., /etc/designs/mysite.css
  • Tags contained in conditional comments
  • Clientlibs included by JavaScript (e.g., when leveraging the property channels)

So if you’re looking for a way to reliably update your ClientLibs every time there is a change, this is a pretty simple approach.

Top 10 Hottest Features in Adobe Experience Manager 6.2: Sites

0
0

05287_Top-10-Hottest-Features-in-AEM-Manager-6_Sites
Last year, at Adobe Summit 2015, I was able to attend a session on the hottest features in AEM Sites and it was really good. So I was really looking forward to this year’s session titled, “What’s new in AEM Sites 6.2: Top 10 hottest features,” to see the new features and controls that would be coming down the pipe for AEM 6.2 Sites. AEM 6.2 was released April 21, 2016. Let’s take a few minutes and walk through the finer points of their presentation. I will be using their list of top 10 items, with some commentary from me about each one. I encourage you to take an hour to watch the full presentation online (FYI—the first 8 minutes of the video is almost all dead air). Thanks to Irina Guseva and Peter Krmpotic from Adobe for their presentation.

  1. Find Anything Anywhere
    Adobe has introduced an updated Touch UI. This is actually a great enhancement, but once again Adobe is changing the user interface. It’s hard on authors to constantly need to learn a new way of doing things and navigating around, and it means additional training for people when they upgrade from one version to another. But let’s not get bogged down with negativity. The new update to AEM is called OmniSearch and this is a really decent way of getting around. No longer do I have to do multiple clicks to find my tags. I just type “tags” and then the page loads. It also comes with search suggestions that show you all the possible destinations within AEM and the ability to do filtered searches. Also, they removed the need to go to a “selection mode” to select multiple items (pages, assets, etc.) when you need to activate them or update their properties. That’s great.
  2. Templates for Everyone
    This is the new Template Editor. Last year when they teased this I mentioned how reluctant I was about it. Put the template in the hands of the authors and not the developers, are you insane? I still feel that way, but not as strongly now. An author can still royally screw things up, if you give them the permissions to do so. And that is the key. You can tie down this functionality by only giving it to people who actually know what they are doing. I was able to chat a bit with Gabriel Walt during Summit and that was his big piece of advice. So, we can still be happy, authors can still feel empowered, and developers won’t have to do as much. I had a chance to play around with it a bit in one of the Summit lab sessions and it certainly shows some promise.
  3. Content Mixology
    Content fragments! This is very interesting. You get to treat content as an asset. And that is actually where it is stored as well, within the Assets (DAM) section of AEM. No longer does your content need to be freeform and disconnected. This could become incredibly useful if you need to use the same content in different places, because then you can just edit it once and it shows up everywhere else you need it. This content becomes “channel agnostic”. It also allows you to tie other assets to it, making it easier to find when you want to use an image along with your content. You can make variations of the fragment as well. It is a scaled down and simpler authoring experience, so don’t expect it to have all the AEM bells and whistles. I think this is an innovative idea.
  4. Social Power
    This is all about content reuse. You can use content fragments in Communities as well, and this seems like a cheap new feature since we already learned about content fragments. But, content published in or coming from Communities can become a content fragment. To be clear, this is user-generated content, not content created by AEM authors. So if someone wrote a blog post or posted a comment to a forum, you could capture that piece of content and then move it into Assets.
  5. Fire Up Content at Scale
    AEM is now structured to work with Livefyre to allow you to capture user-generated content from other sources and bring it into your web channel experience. Livefyre components now come as part of AEM, and they bring in content from these other sources. The nice thing is that you choose what content comes in. These assets are stored within AEM Assets.
  6. Fine-Grained Personalization
    Like peanut butter and chocolate, Target and AEM were made for each other. They are now together using the same user interface and code base to run their features. I saw this coming a couple years ago when we were helping the Target team get their Target demo running (demo.adobe-target.com). And now that they are together, it seems like a no-brainer to merge these two solutions. Create your audiences, activities, and experiences for your content and do your testing, all within AEM. Frankly, I always thought Target was much better than the AEM personalization tools, and I usually recommended that to customers. Seeing this finally pay off such that Target becomes the default personalization engine feels like a win all around. Obviously, this change comes with a cost. You don’t get to just use all the features of Target in AEM for free. You’ve gotta pay for it.
  7. Target Locally, Manage Globally
    Using this new part of Multi Site Manager, you can allow geolocated people to modify things to suit them. The global campaign (or Target activity) that was set up can be manipulated at the local level to give it a more personal touch for that language or location. The Target piece gets sent along with the rest of the page info/content.
  8. Roll with the Masters
    If you’ve been using AEM for a while, you know that different parts of the Capability get different levels of attention. One that has been underserved for a while now is the localization features available in MSM, specifically in regards to Assets. In AEM 6.1 and lower, there was no support for localization of Assets—6.2 finally addresses this, bringing the full suite of localization tooling to Asset management. Back in Content Mixology, I talked about content fragments, and how they are—under the covers—represented as an asset. Because of this addition, content fragments are also able to be localized using the same tools as your other content. You can also pick and choose which parts of your content are localized via machine translation, and which parts involve human translation efforts; this can be really handy once you start determining which content is popular in which geos, allowing you to focus on getting the largest benefit for those human translation dollars.
  9. Back to the Roots
    6.2 introduces a new concept called Continuous Publishing, which brings a greater degree of flexibility to control which pieces of content are managed via the AEM Launch tool, and which pieces of content are part of which Launches; the first iteration of Launches was introduced with 6.1, but 6.2 really starts to make this feature a larger part of AEM Sites. The general idea is to control what goes into the publish queue, and at what point in time, and what degree of immediacy it gets.
  10. Best Practices Bonanza
    Now there is a new default site that people can play around with called We.Retail. I’m glad they are updating this to stay with new features and we don’t have to keep talking about Geometrixx, but in the back of my mind the whole time I just kept thinking “great, one more thing I need to make sure and remove, before a site goes live, when we do an implementation for a customer”. I am such a pessimist. :) All the code is in github for you to look at.

Bonus Feature. Connect Clicks and Bricks – Last year Adobe told us about AEM Screens. More progress is being made in this area and it is now part of 6.2. It will allow you to push content through various screens and channels. They really seemed determined to make Screens a part of AEM. It’s certainly another channel for your content, but it still just seems so theoretical. Maybe now that it is more tied in with AEM it will start to show some additional use cases. But when they talk about the capabilities of AEM, I still don’t always see them adding Screens to the list of Sites, Assets, Communities, Forms, and Mobile.

AEM 6.2 has quite a few new features and we look forward to exploring them further. If you’re looking for a more in-depth review of AEM 6.2 Sites, then I recommend you check out the Summit presentation, or look over some of the other blog sites I have seen around where they dive into some features a little deeper. If you know of any other features that you are excited about in 6.2, let us know via email (info@aempodcast.com) or Twitter (@axis41).

Axis41 Presents at Adobe Summit 2016

0
0

Axis41-Presents-at-Adobe-Summit-2016
I recently had the opportunity to attend Adobe Summit 2016 in Las Vegas. It was loads of fun and we had the opportunity to meet a lot of wonderful people and hear about where Adobe is taking the Marketing Cloud. As a Platinum Sponsor, Axis41 was granted a breakout session to present on a topic related to one of the Adobe Marketing Cloud products. Because of our years of experience doing Adobe Experience Manager implementations, we chose that as our focus. Partnering with Kem Elbrader (Chief Software Architect for Axis41) and Samantha Martin (Vice President of Strategy at Axis41) to help frame the discussion was Matt Hall, the Vice President of Marketing from Pacific Dental Services.

Our goal for the presentation was to share how Axis41 was able to help PDS redesign, plan a new user experience, implement a brand new Adobe Experience Manager code base, get them set up on Adobe Managed Services, and launch 495 sites—all within 100 days. Talk about an uphill battle, but completely doable if all partners are synced together and stick to the plan. Our key takeaways from the presentation were:

  • Use Adobe Marketing Cloud’s strengths
  • Leverage already existing systems
  • Take advantage of Adobe Experience Manager’s extensibility
  • Find a good partner to help guide you through this process

This case study of how Axis41 helped the PDS team deliver these objectives shows that if you bring the right team members together and use Adobe Experience Manager and the Adobe Marketing Cloud in the best ways possible, you can accomplish quite a lot. Below is the video of our presentation, in its entirety, for you to review. Please feel free to contact us via email to discuss AEM and our Adobe Marketing Cloud implementation experience in more depth.

Solving the dissonance between AEM Dispatcher and Publish

0
0

Solving-the-dissonance-between-AEM-Dispatcher-and-Publish
Part of the beauty and attraction of Adobe Experience Manager is its system architecture—the Author, Publish, and Dispatch instances. Let’s look at a high-level overview of how these things work together. The Author instance allows content to be authored and updated easily and efficiently. The content is then activated and replicated to the Publish instance so web pages are always teeming with the newest content, ready for public consumption. The Dispatcher instance is a cached version of published content so when users hit a website, the content is readily available at increased speeds. The Publish server also lets the public-facing Dispatcher know when its content is out of date and needs to be re-cached on a content path. When a user visits a page with old, invalidated content, that page request will prompt the Dispatcher to fetch new content from the Publish instance and serve that content to the user as well as cache it. The next person to visit the page will receive a fast, updated web page.

It’s simple, right? Author new content –> activate –> publish updates –> Dispatcher is informed it has old content -> Dispatcher re-caches new content when page is visited. It really is a great system, but it isn’t without complex and interesting challenges, depending on the structure of your site and how content is being used.

The problem we faced:
What happens when you have content on one page relying on content from another page? In one particular project, we worked on a complicated site architecture where pages used information from other related pages to populate certain content. For example, Page A is related to Page B for specific content it displays. When the related Page B is updated and activated, AEM does its process and Page B is updated on the Publish instance and eventually gets updated on the Dispatcher. But Page A is relying on that content and does not know that Page B has been updated. Page A does not get re-cached or invalidated and displays old Page B content. There may be additional cases, where Page B refers to content from other pages as well. As you can imagine, this created a huge problem. This system of speed and accuracy was suddenly only fast and definitely not accurate. How did we get related content to stay updated?

Our solution:
We used a combination of an AEM workflow launcher and a custom Java class, implementing the WorkFlowProcess class. Let’s first look under the hood of how this site architecture works. The relationship is that Page A contains a property that refers to the path of Page B. There may also be several other pages: Page C, Page D, etc., that refer to and point to Page B for information and content. If we can collect all of these paths, we can do a request to the Dispatcher, telling it to invalidate and re-cache all of these pages. Whenever a page was activated, the workflow launcher kicked off the custom workflow and executed a series of JCR queries to check for the path of the recently activated page (Page B), which we got through the payload of the WorkItem Java class.

public class RelationalCacheBusting implements WorkflowProcess {
 
	public void execute(WorkItem item, WorkflowSession session, MetaDataMap args)
     	   throws WorkflowException {  
 
WorkflowData workflowData = item.getWorkflowData();
String triggeredPagePath = workflowData.getPayload().toString()
 
…}

If Page B’s path existed in any properties in the JCR nodes of other pages, it would be related to the activated page. We conducted a check to see if Page B refers to any other additional pages. The site architecture allowed us to have an idea of which page component types to check for in our query, narrowing down where to look for relationships, but also largely relying on knowing where to look based on the page component type of the activated page. For example: one page component type—the Map Modal—will always refer to another page component type—the Location—that provides information about a physical location or an address. We knew if this address page was modified and activated, we needed to look in the pages that referenced the address pages.

We collected all the paths of pages that referred to Page B and all the pages that were referenced by Page B and did a request to the Dispatcher, telling it to invalidate all of those pages and then re-cache them.

Now, pages can be activated without worrying about the repercussions of pages relying on each other for their content! Even though it was a decent effort up front, this solution has been a big help to keep the site up to date and fresh, and has taken a big load off of the content authors.

Viewing all 172 articles
Browse latest View live




Latest Images