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

Develop With The Author In Mind For Adobe Experience Manager

$
0
0

I’ve talked about the importance of considering the author when doing an Adobe Experience Manager implementation before. Here is a link to watch the presentation I gave at Adobe Summit back in 2014. It is the role of an author to deliver content out to the sources that consume it and need it. Marketing authors are the heart of your organization’s web presence, delivering content to the people who need it most: customers.

As I stated in my presentation: “I personally have been involved with web development for almost 10 years now. And most of that time was spent creating websites using various tools that developers built based on business objectives or needs. And sometimes those systems were clunky, awkward, and not very easy to use. They got the job done, but they were far from elegant. Nobody really spent any amount of time considering how an author was supposed to use the tool to create content (content being arguably the most important part of a website). Simply put, a developer usually just wants to make a thing work and then move on to the next thing.”

I’m not trying to be down on developers, but in all honesty I have seen this a lot. In a way we have bred developers to be like this. Clients, analysts, and managers are known to throw a request to developers with limited details or requirements and tell you to build it as quickly as you can. That’s not fair. My job with this blog post is to suggest some ways that you can improve your process and development using Adobe Experience Manager, in a way that benefits the authors.

In that Summit presentation I mentioned some things an organization can do, one of which is to utilize an Authoring Advocate. “This is a person whose express job it is to capture the requirements for how content will be authored. A stakeholder that understands the author’s needs and can give feedback to the development team can be incredibly helpful and time saving.” I still stand by this and would recommend that you use this in your organization, but typically developers don’t have the necessary influence on this decision.

Here are a few suggestions about how you can take the author into consideration when doing development, that you can absolutely control:

  1. Be aware that a human is going to have to use this, likely on a daily basis – I know this seems dumb to say, but if you visualize your best friend being the one who has to use this authoring tool, day in and day out, then you might be more apt to give it a second thought. I find it best to think of authors as a finite resource. The idea of authoring fatigue is a very real concern. And if you can do something to make their process easier, then you should do it.
  2. Hallway usability tests – Grab a person who hasn’t been working on the project to come and use it. This should be in addition to your normal pull request/code review process that you do with your regular dev team. A fresh perspective is always helpful when you have been working on a project for a long time since you often end up with tunnel vision.
  3. Generate test content for your component so that you know how it works with all the needed material – Creating this test content serves multiple purposes: a) it’s a chance for you, the developer, to communicate the assumptions and behaviors you built into the component; b) it drives both the usability testing and edge-case testing for the QA team (If they know where the assumptions are, it’s easier to test what happens when they fail.); and c) it becomes a growing library of both functional and behavioral testing for the component over the long term, easing future maintenance and development efforts.
  4. Appropriately sized dialogs in Touch UI – Just because everything is there in the editing dialog for a component, doesn’t mean that it is the best it can be. Take some time to make sure that all the dialogs are sized appropriately on all targeted devices, so that you can view the contents of them all easily. A good example of this is the 6.0 release where the dropdown for Touch/Classic UI rendered below the bottom of the dialog, making it appear that there was only one option in the dropdown.
  5. Properly labeled dialogs and component titles – Label or name the component or page type (and, if possible, get the Author Advocate or stakeholders to help with naming). When you end up with a bunch of components on the page it will make everyone’s lives easier to know what each component is, especially if you have components with similar functionality. Plus, having all the fields of the dialog labeled correctly will make it easier for the author when they forget the training that they received.
  6. Demo, Demo, Demo! – Include the authors, or the Authoring Advocate, in your regular demo process. If you aren’t doing regularly scheduled demonstrations of your code then you should start. Nothing is worse than getting to the end of the project and then having the customer tell you that features are missing or functioning incorrectly.

We at Axis41 think that the fundamental consideration you should make to have a successful implementation is the author’s experience. And, thanks to AEM, you have the ability to optimize the authoring experience to your organization’s needs. This is true if you are running CQ 5 or AEM 6, Touch UI or Classic UI. I hope you take some of these considerations into mind as you develop with AEM. If you have any thoughts on these recommendations then drop us a line via our email: info@aempodcast.com


AEM Podcast: An ACS AEM Commons Interview with Justin Edelson, Pt1

$
0
0
AEM_Podcast_ACS-AEM-Commons-Interview

Justin Edelson, Peter Nash, and Joey Smith

As mentioned in our last podcast, we like ACS AEM Commons and want to cover a number of features that we find useful. This is the next in our ongoing series about ACS AEM Commons. In this podcast we are joined by Justin Edelson, Global Evangelist for AEM and co-project lead of ACS AEM Commons and ACS AEM Tools, from Adobe. Because of Justin’s work on ACS AEM Commons, he was able to give us some rich insight and background as to why and how the ACS AEM Commons project got started initially, as well as share some of his favorite features. Due to the length of our discussion, we decided to break this podcast up in to 2 parts. This is part 1.

Make sure to also join his AEM Gems session, Inside ACS AEM Commons & Tools, planned to be aired Aug. 26, 2015. at 8 a.m. Pacific. Or if you are reading this after the event, you can find it in the Adobe Gems backlog here.

Music Intro: Code Monkey by Jonathan Coulton

AEM Podcast: An ACS AEM Commons Interview With Justin Edelson, Pt2

$
0
0
AEM_Podcast_ACS-AEM-Commons-Interview

Justin Edelson, Peter Nash, and Joey Smith

In part one of our discussion about ACS AEM Commons, with Justin Edelson (Global Evangelist for AEM and co-project lead of ACS AEM Commons and ACS AEM Tools, from Adobe), we talked about the history and purpose behind ACS AEM Commons and ACS AEM Tools. In part 2 of our recording we get in to the nuts and bolts of two ACS AEM Commons features: Query Packager and the ACL Packager. Special thanks again to Justin for taking the time to record with us for almost an hour.

Make sure to also join his AEM Gems session, Inside ACS AEM Commons & Tools, planned to be aired Aug. 26, 2015. at 8 a.m. Pacific. Or if you are reading this after the event, you can find it in the Adobe Gems backlog here.

Music Intro: Code Monkey by Jonathan Coulton

To Scaffold Or Not To Scaffold

$
0
0

That is the question. Whether ’tis nobler in the author instance to suffer the slings and arrows of a messy authoring dialogue… Alright, enough of that Hammy intro (pun intended).

We were recently consulting for another agency that was working on their first AEM implementation. They came to us with a few questions around some general Adobe Experience Manager best practices. One of them stood out to me because I have had to answer it multiple times. Question: When is it best/appropriate to use scaffolding to build a page? As many of you know, the typical method talked about in the AEM marketing is the ability to do “drag-and-drop” content authoring. This is a great feature to tout as it really does put the power in the author’s hands to create their own content without the necessity of calling up their IT department. But AEM does have a feature called Scaffolding, which shifts some or all of the authoring of a page away from the drag-and-drop method.

Adobe’s documentation on scaffolding explains it pretty well: “Sometimes you may need to create a large set of pages that share the same structure but have differing content. Through the standard AEM interface, you would need to create each page, drag the appropriate components onto the page and fill each of them in individually.”

“With scaffolding you can create a form (a scaffold) with fields that reflect the structure you want for your pages and then use this form to easily create pages based on this structure.” On that same page they also talk about how to create a scaffolded page in that same link, in case you are interested. There is also a pretty good write-up about how to do it over here at this blog: http://experience-aem.blogspot.com/2014/04/aem-cq-561-working-with-scaffolding.html. I won’t be dealing with the “How” of scaffolding, only the “Why”. Here are some reasons to do it and some reasons not to do it.

To Sleep, Perchance to Dream… – Reasons to use Scaffolding in AEM
1. Brand considerations – Brand is everything. Authoring a website absolutely affects the brand, and most likely there are numerous rules around how a corporate website should look. Inconsistency of content is just as damning as using the wrong red color in a Coke ad. If an author were to just come along and randomly put any component on any part of the page, then it might break those rules. Allow an author to pull any component, at will, from the sidekick (classic UI) or sidebar (touch UI), and suddenly you have a spastically arranged page that doesn’t follow along with how the company wants to present itself. But if everything for the page is in one specific place, then the author can’t forget a particular component. And if you don’t have a parsys on the page, then an author can’t add components out of place.
2. Constant/Consistent authoring – If you have authors that are putting out a lot of content every day, then they might get tired of dragging the same components out every single time. It would get monotonous. Plus there is the concern of authoring fatigue. And if an author happens to forget a component, then you could end up having an inconsistent page that doesn’t follow brand standards. Also, If you are expecting a specific component, such as a title, to be at a particular location in the JCR relative to the parent node of the page and an author forgets to add it, a news teaser list or some similar component would fail to find the title.
3. Same components used over and over – Structured content is probably the biggest reason to use scaffolding. If your content follows the same format on most of your pages, you can use the scaffolding tool to easily and quickly fill out those sections. An author can fill data into each section within the scaffolding form and know that it will appear consistently across all pages, without the risk of user error from dragging and dropping individual components.

All of these reasons came together in the case of CMO.com, a website developed by Axis41. They are a marketing news aggregator website and produce 30–40 new pages (articles) a day, and they use only two page types for these articles. With CMO being the thought leadership website on marketing for Adobe, it is critical that they follow the appropriate brand strategy to keep content consistent. Also, as a news website it is good to keep the content consistent as well, so everything is in the same place regardless of what type of article that someone is reading. Because we enforced the structure of the content in the JCR (since there is only one component, you know where all of the properties are stored in the JCR), it became easier to grab the data from the page to display in the various teasers, lists, and carousels on other pages of the site. The benefit of scaffolding is that all properties can be edited in one place, making authoring potentially faster.

CMO-Article-Page
CMO.com Article Page

CMO-Scaffolded-Page
CMO.com Scaffolding Page in the Classic UI
(This only shows a small portion of the scaffolding items for CMO.com)

Ay, there’s the rub… – Reasons not to use Scaffolding in AEM
1. Wanting to give authors complete control – I have known groups that have said, “Hey, we know how to do stuff, just give us the tools.” They were tired of having to wait for other groups to get their content pushed live or being dictated by a developer. Some people have the skills and ability to author correctly. Trust that. Don’t put up a barrier to their authoring just because you have an inherent mistrust in people’s abilities (I’m the biggest offender of this). At some point you have to let people go out on their own. If they make a mistake, it is not the end of the world and it can be corrected.
2. In-Context Authoring – As I mentioned at the top of the article, the drag-and-drop functionality is a big selling point to people considering AEM. Content authors feel like the control is being put back into their hands. The author can also see the content of their page being built as they drag each component out, which is empowering. This in-context authoring allows them to see the page without having to go back and forth for each component or tool when they update content. They see it immediately. Scaffolding, on the other hand, forces them to effectively switch back and forth. It’s not hard, but it can be annoying. In the past, I’ve suggested that authors have two browser tabs open: one for the scaffolding and the other for the actual page. I never liked telling people to do that.
3. It isn’t an option in Touch UI for AEM 5.6 or AEM 6.0 – If you are running AEM 5.6 or AEM 6.0 then you will have to use the Classic UI for your scaffolding. This isn’t a problem unless you are planning to use the Touch UI for the rest of your authoring. The authoring experience of switching back and forth between Classic and Touch is very bad and we strongly encourage avoiding it if possible. Choose one and stick to it.

A possible alternative
One idea that we have done for a few clients is to utilize what we call enhanced templating. This method allows you to use the the AEM system to create a page template with all the relevant or necessary components already on the page. Adding the components to the template saves the author from having to create the structure of each new page manually. Keep in mind, though, this does not prevent the author from deleting or rearranging components that the template initially created and can cause branding or JCR problems, as mentioned previously.

Cudgel thy brains no more about it – Conclusion
When Adobe announced their Touch UI in AEM 5.6, we found it odd that they did not include scaffolding as part of it. Indeed, David Nuescheler, one of the main creative forces behind CQ, indicated that it was a method he did not prefer in AEM development, when we interviewed him on our podcast. But with the release of AEM 6.1 they have included scaffolding back as an option. My assertion as to why they decided to do this is because there really is a place for the use of scaffolding in a good AEM implementation.

As with most things in life, there are good and bad reasons to use scaffolding, and there is not a definitive right or wrong time to use it. It’s all about weighing what controls your authors need against the risks of giving them those controls. Sometimes it really is best to put a fence around something in order to protect both the product and its users. Other times it is best to let them go hog wild.

We don’t need to be quite so fatalistic as Hamlet in our decision to choose whether to scaffold. No one is going to die, see specters, or have horrible nightmares. But you might be able to help your authors avoid some heartburn if you make the right choice. Use these guides to help know when it is the right time to use scaffolding. And remember, scaffolding is a part of AEM and we shouldn’t be afraid to use it or not use it. Reach out to us through email if you have some additional questions about scaffolding in AEM: info@aempodcast.com.

Rich Text Editor Dialog Height Resize for AEM

$
0
0

At some point in your development with Adobe Experience Manager, you’ve probably created a dialog with a richtext xtype in it. You open the dialog and begin writing your text. With all of the functionality provided out of the box and with all of the plug-in options available to you, this seems like a great xtype, and indeed it is. However, after you put a paragraph or two of text in the dialog or maybe a larger image, you want to resize the dialog window to see all of your content at the same time. When you do, you realize that the rich text editor doesn’t increase in height. You still have to scroll in the small editor window even though you’ve made your dialog window much larger. Here is one possible fix for this problem.

non-responsive
(Non-Responsive Rich Text Editor Dialog)

When constructing your dialog, make the richtext node a direct child of the root widget collection rather than wrapping it in a tabpanel. If you are building using Maven/Vault, a sample dialog.xml file is listed below.



   
       
           
      
           
       
       
   

Now your text dialog is responsive, but we need to make sure to add the textisRich boolean to the dialog so that the html doesn’t get printed to the screen.

responsive
(Responsive Rich Text Editor Dialog)

If you have other tabs in your dialog, be sure to add a hidden boolean field named textIsRich to one of those other tabs.



    
        
            
                
            
        
        
        
            
                
                    
                        
                        
                    
                
                

            
        
    

If you only have one tab in the dialog (the one containing the richtext), you will need to add an additional tab (which can be hidden) to store the textIsRich boolean. An example of how to do that would be to replace the XML comment “Other dialog tabs go here” with the following XML.

So all together with two tabs and some of the plug-ins added back in, our code would look like this:



    
        
            
                
                
                    
                        
                            
                                
                                    
                                        
                                    
                                    
                                    
                                
                            
                        
                    
                
                
                
                    
                        
                        
                        
                    
                
                
            
        
        
        
            
                
                    
                        
                        
                    
                
                

            
        

    

alltogether
(Responsive Rich Text Editor Dialog with plugins)

In conclusion, to get a responsive RTE dialog, don’t wrap the RTE plug-in in a tab panel and make sure to add the textIsRich boolean as a hidden value.

Dispatcher Flush UI: An In Depth Review

$
0
0

05287_Dispatcher_Flush_UI

Joey and Peter did a podcast introducing ACS AEM Commons, and within that podcast they talked about one of their favorite features: Dispatcher Flush UI. I thought I would take some time to outline a little bit more about this incredibly useful AEM feature.

What is it?
Dispatcher cache can often confuse authors, especially in content-heavy sites. Traditionally, authors publish pages and rely on the flush agents on the publish servers to automatically flush the cache of that page, but this process can leave a lot of gaps. What if the author does not want to actually push the content out to the dispatcher? What do you do when a content change affects a group of related pages? Or, you might find yourself occasionally needing to flush the dispatcher cache on demand. While you certainly COULD visit each and every page that is affected by a change and manually activate it, triggering a flush, people have often found the need for a better answer. ACS AEM Commons provides the Dispatcher Flush UI feature that allows privileged users to set up pages to hold paths that can be flushed at the push of a button, without the involvement of the Operations team.

How it works
The Flush UI tool creates a new type of page, in the /etc tree, under the “miscadmin” (or “Tools”) panel of the Classic UI. Who exactly should be allowed to create these Flush UI pages will differ from project to project and can be managed through user permissions, but suffice it to say, users with the appropriate permissions can create a page and use the built-in pathfield component to add references to any number of paths within their JCR. Once the page is defined, users can visit this page and hit a clearly labelled button, causing all referenced paths to be activated (and subsequently flushed) in a single batch. Since the authors use the Flush UI in the authoring environment, the author server needs to have dispatcher flush agents available. The ACS AEM Commons page provides specifics for the configuration.

Why it’s good
In addition to the use cases described in “What is it?”, the Dispatcher Flush UI feature has useful applications in the development process. Dispatchers can more easily stay in sync with quickly changing development environments without disabling cache altogether. Multiple Flush UI pages can be set up, each controlling different sections of cache. It is particularly helpful in flushing clientlibs (if you are not using the Versioned Clientlibs feature) and networks of pages related by dynamic content.

How to do it
First, a Dispatcher Flush replication agent must be created to service this feature on the authoring environment. Active flush agents usually reside on publish environments and get triggered when the publish server receives a replication request. We need ours on the author environment, so when an author hits the “Flush Paths” button, there is something there to send the request. The Ignore Default option designates the flush agent as outside of the normal replication flow, ensuring it is not called by other processes.

Let’s make a flush page to invalidate the main clientlibs.
DispatcherFlushUI1
The Flush UI page can be created through the /miscadmin/tools section of AEM. There is a folder set up by ACS to hold flush pages under /etc/acs-commons/dispatcher-flush. The page is created like any other and uses the “Dispatcher Flush” page template.
DispatcherFlushUI2
The properties on the node point to ACS resources.
DispatcherFlushUI3
The flush page holds a dialog with configurable path fields that you can point to whichever resource you want to flush and how you want to flush them. The flush method can be Invalidate Cache or Delete Cache. We will point our paths to the CSS and JavaScript generated by the main clientlibs. Note that we have minification off in this example. And also note that the paths are not necessarily in the author JCR. It is the dispatcher that cares about these paths. The pathfield’s browse and autocomplete capabilities will not help you find things like compiled clientlibs, servlet paths, or selectors.
DispatcherFlushUI4
The configuration node looks how you would expect: resources pointing to ACS components and the paths held in a String[].
DispatcherFlushUI5
Once configured, the flush method, paths, and agent are displayed and there is a big red button to push to do it.
DispatcherFlushUI6
If these pages are useful, you might consider adding them to your build process to make them available across all stages of your development process. Pages are quick to create and the paths are easy to modify, but it can be helpful to have pre-configured pages that point to a set of pages that need frequent flushing.

Audience Impact (authors, devs, admins)

  • Developers drive the decision of which items should be flushable by whom
  • Admins create the Flush UI pages and set up the permissions
  • Authors use the result and trigger the cache flush from the interface created by the admins and devs.

Example application
One of our Adobe Experience Manager implementation customers had many of their content pages that were actually aggregations of content imported from third-party systems. When bulk updates were made to that third-party system, no one wanted to sit down and click “activate” on a few thousand pages; nor did we particularly relish the idea of having to manually flush the cache at the customer’s whim.

Instead, we created a Flush UI page that listed all these aggregate pages, and provided the authoring team the ability to trigger the flush event when they felt it was appropriate, as they were often the first group aware of changes in the third-party system that needed to be reflected on the site.

If you found this interesting then check out this page about ACS AEM Commons which contains other posts where we talk other things related to ACS AEM Commons. And if you have any question then feel free to send us an email to info@aempodcast.com.

How to Disable the “Change Password” Button for AEM in Touch UI and Classic UI

$
0
0

05287_Disable-Change-Password-button
We had a customer ask us how to disable the “Set Password” (Classic UI) and “Change Password” (Touch UI) features for a user who doesn’t have permissions to change a given password. The default behaviour in Adobe Experience Manager is to show the link, but issue an error when you actually try to set it. This code package, which you can download, makes some small modifications to the UI to simply disable or hide the control if the user doesn’t have permissions to perform the operation.

ChangePasswordvisibleinTouchUI
Change Password visible in Touch UI

ChangePassworddisabledinTouchUI
Change Password disabled in Touch UI

SetPasswordvisibleinClassicUI
Set Password visible in Classic UI

SetPassworddisabledinClassicUI
Set Password disabled in Classic UI

We’re always happy to answer your questions, so ask us on Twitter (@Axis41) or email info@aempodcast.com.

AEM – Sightly and Touch UI Tips

$
0
0

05287_AEM-Sightly-and-Touch-UI-Tips

As a CQ5/Adobe Experience Manager developer you know there are often times you need to embed a component on a page or within another component, and that it is quite easy to do. In a JSP, all you to do is add a line like this:

In Sightly, you can do a similar one-liner:

However, there are a few things to be aware of when embedding components, especially when using Touch UI.

I will highlight three issues that I have come across when embedding components using Sightly and Touch UI, and explain the symptom, the cause, and give a solution for each.

ISSUE 1: Edit config does not refresh page after component edit
The Symptom
A component set up to refresh the page after edit does not refresh the page in Touch UI. In the web console there is a JavaScript error: Uncaught TypeError: Cannot read property ‘componentConfig’ of undefined.

The Cause
The component was in the .hidden component group. Touch UI has a list of editables, or components. This list does not include components in the .hidden group. When the component is edited, JavaScript runs that looks for the component in the list of editables. Because it is not in the list, the JavaScript throws an error and the editconfig afteredit action does not happen.
EditConfigCause

The Solution
Put the component in a group other than .hidden. This will make the component available to be added to the list of components that can be dropped into a parsys, and it would be up to the content team to not include these components in the design configuration. To help keep this clear you could put the components into a group named Hidden.

Note: I am continuing to look for a good solution to handle components in the .hidden group, since the parsys component is in that group and in my experience is the most common component to be embedded. So far I have not yet found a way to deal with this. It appears in Touch UI there is an update method that runs after closing the dialog, and that supersedes any custom afteredit event handlers attached to the component.

ISSUE 2: Dialog does not open in Touch UI
The Symptom
Embedded component’s dialog box doesn’t open in Touch UI. In the web console there is a 400 (Bad Request) error.

The Cause
Embedded components do not create their content node until after the dialog has sent a POST to the component’s content path. The problem here is that in Touch UI the component looks for the dialog to open based on the content path. Since the content path doesn’t exist the dialog fails to open with an error.
DialogDoesNotOpenCause

The Solution
Make sure the content node for the component exists. There are a couple ways of doing this.

  1. Add the component to the jcr:content of the template used to create the page.
  2. Add a script to run just before the include of the component that creates the node if it doesn’t already exist. (Below is some example code For solution 2)

JS Use API
In a file named EmbeddedComponent.js

"use strict";

/**
 * Creates a component node with name, if node does not yet exist.
 */
use([], function () {
    var newResourceName = this.name;
    var newResourceType = this.type;
    var resourceResolver = resource.getResourceResolver();
    var newNodePath = resource.path + "/" + newResourceName;
    var existingComponentResource = resourceResolver.getResource(newNodePath);

    if(existingComponentResource == null){
        var properties = {"jcr:primaryType":"nt:unstructured",
            "sling:resourceType":newResourceType};
        resourceResolver.create(resource, newResourceName, properties);
        resourceResolver.commit();
    }
});

Sightly script

Java Use API

package com.aempodcast.example.components.utils;

import com.adobe.cq.sightly.WCMUse;
import java.util.HashMap;
import java.util.Map;
import org.apache.sling.api.resource.Resource;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.ResourceResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EmbedComponent extends WCMUse {

    private static final Logger log = LoggerFactory.getLogger(EmbedComponent.class);
    private ResourceResolver resourceResolver = null;
    private String resourceType = null;
    private String resourceName = null;
    private Resource resource = null;
    private Resource child = null;

    @Override
    public void activate() throws Exception {
        // Set resource Name and Type
        resourceName = get("name", String.class);
        resourceType = get("type", String.class);
        resource = getResource();
        child = resource.getChild(resourceName);
        resourceResolver = resource.getResourceResolver();
        
        if (child != null && !child.isResourceType(resourceType)) {
            updateResourceType();
        } else if(child == null) {
            createResource();
        }
    }

    private void createResource() {
        try {
            Map properties = new HashMap();
            properties.put("sling:resourceType", resourceType);
            resourceResolver.create(resource, resourceName, properties);
            commitChanges();
        } catch (PersistenceException ex) {
            log.error("Failed to create resource", ex);
        }
    }

    private void updateResourceType() {
        try {
            Node childNode = child.adaptTo(Node.class);
            childNode.setProperty("sling:resourceType", resourceType);
            commitChanges();
        } catch (RepositoryException ex) {
            log.error("Failed to update resource type", ex);
        }
    }

    private void commitChanges() {
        try {
            resourceResolver.commit();
        } catch (PersistenceException ex) {
            log.error("Failed to save changes", ex);
        }
    }
}

Sightly Script

ISSUE 3: Component select highlight goes beyond the component area
The Symptom
Embedded component’s authoring highlight in Touch UI is bigger than the component itself, or an embedded component below is un-editable.
HighlightGoesBeyondSymptom Each paragraph is a copy of a component. The top most is embedded while the other four are dropped into parsys. The embedded component has data-sly-unwrap set on it. The blue border shown is the selected top most component. The other four components cannot be selected.

The Cause
The wrapping element of the component had been removed with data-sly-unwrap. Adobe Experience Manager puts a cq element, which holds helpful metadata for the authoring interface. One of the things it is used for is to set which element to use as the component boundary. When the component is selected, the boundary gets highlighted with a blue border. When the default wrapping element is removed, the next parent element is then used as the component boundary, which can cause the highlight to go beyond the component, and interfere with the ability to edit other components.

The Solution
Do not use data-sly-unwrap on elements including data-sly-resource.

Conclusion
In transitioning from CQ5 JSPs and the Classic UI to Adobe Experience Manager 6.0 Sightly and Touch UI, there are things that need to be adjusted in how they are done. Knowing the possible issues–and how to solve them–will make Sightly and Touch UI easier to use for developers and content authors.


LDAP in AEM 6.x

$
0
0

05287_LDAP_in_AEM_6(1)
Starting in Adobe Experience Manager 6.0, there has been a significant change in the way LDAP Authentication is managed. Rather than using the jaas.conf file of earlier releases, AEM 6.0 comes with Jackrabbit Oak, which has its own LDAP integration. Although the Apache Jackrabbit developers have provided documentation for configuring the system, we felt that it would be helpful if we could provide an example of this configuration.

There are three things we need to configure in Adobe Experience Manager: the LdapIdentityProvider, a DefaultSyncHandler, and an ExternalLoginModule. While in these examples we will be using the Felix Console, we at Axis41 always recommend that all Production OSGi configurations be saved in your source code repository, and become a regular part of your deployment process.

You should take the time to understand all the options in each configuration; however, we will be focusing on the options that you most likely will need to configure.

Apache Jackrabbit Oak LDAP Identity Provider (LdapIdentityProvider)

LdapIdentityProvider

provider.name The “idp.name” we will provide to the ExternalLoginModule
host.name The host where your LDAP server is running
bind.dn The Distinguished Name (DN) to bind to LDAP with
bind.password The username to bind to LDAP with
user.baseDN The LDAP DN that is the base for user accounts that will be allowed to authenticate with AEM
user.objectclass The LDAP objectclass for user objects that will be allowed to authenticate with AEM
user.idAttribute The LDAP attribute that will determine the AEM username
group.baseDN The LDAP DN that is the base for group objects that will be searched by AEM

Apache Jackrabbit Oak Default Sync Handler (DefaultSyncHandler)

DefaultSyncHandler

handler.name The “sync.handlerName” we will provide to the ExternalLoginModule
user.expirationTime How long after synchronization a user object should be considered valid
user.autoMembership Synchronized users will automatically be added to this group.
user.propertyMapping A String[] of “key=value” pairs; keys will be the AEM property name, values the LDAP property which will be copied.
user.pathPrefix Location where synced users will be stored; the value will be appended to /home/users.
group.pathPrefix Location where synced groups will be stored; the value will be appended to /home/groups.

Apache Jackrabbit Oak External Login Module (ExternalLoginModule)

ExternalLoginModule

idp.name provider.name from the LdapIdentityProvider
sync.handlerName handler.name from the DefaultSyncHandler

What it looks like after it syncs

One of the things we found to be a surprise was the name Adobe Experience Manager chooses for the node as it syncs the user from LDAP. Here’s a CRXDE Lite view of a set of objects created using the OSGi configs I shared above. You can see the machine-generated name of both the user and group nodes after the sync took place.

crxde

Indexing Properties and Nodes for AEM 6.0 and 6.1

$
0
0

AEM-Podcast_Indexing-Properties-and-Nodes-for-AEM-6
Due to the growth of Axis41’s AEM business, we have been spending a lot of time recently both training internal resources and customer development teams on Adobe Experience Manager. During trainings and in conversations with some of them it became clear to me that it would be good to share with the wider AEM developer community. Even if you aren’t new to Adobe Experience Manager/CQ development this still might be useful or a good refresher, and if you are new then you should definitely know how to properly index properties and nodes. Consider this a new year public service announcement. :)

To index a particular property, create a node directly under your oak:index of type oak:QueryIndexDefinition with the following properties:
name = propertyNames, type String[], value is the name of the property(ies) you want to index
name = type, type String, value = property
name = reindex, type Boolean, value = true

To index entire nodes so that you don’t have to list all their property names (for example, if they are coming from an outside source and you don’t know them all ahead of time), you have to do different things depending on if you are on 6.0 or 6.1. The following steps concern indexing nodes (and their properties) in the DAM, but they should work for general cases:

For 6.1:

  1. In CRXDE Lite, navigate to this path: /oak:index/damAssetLucene/aggregates/dam:Asset. You should see a list of nodes with names that start with “include” and then a number.
  2. To this list, add a new node of type nt:unstructured that follows the same naming convention and a new number one higher than the current highest (for example, if “include7” is the highest number with 7 then make a node with the name “include8”). The name probably doesn’t matter but we don’t tempt fate around here.
  3. Add a property to this node with the name “path” with a String value set to “”, for example: “jcr:content/metadata”.
  4. Click Save All.
  5. Navigate up the tree to /oak:index/damAssetLucene.
  6. Change the value of the “reindex” property on this node to “true”. This should perform a reindex on the repository.

For 6.0:

  1. In CRXDE Lite, find the node /oak:index.
  2. Under the oak:index node, create a new node of type oak:QueryIndexDefinition with the name “damAssetLucene”.
  3. Set the following properties on this new node:
    1. Name: async, type: String, Value: async
    2. Name: compatVersion, type: Long, Value: 1
    3. Name: evaluatePathRestrictions, type: Boolean, Value: true
    4. Name: reindex, type: Boolean, Value: false (you don’t want to trigger a reindex yet!)
    5. Name: type, type: String, Value: lucene
  4. Click Save All.
  5. Under the damAssetLucene node you just created, create a new node of type nt:unstructured with the name “aggregates”.
  6. Click Save All.
  7. Under the aggregates node you just created, create a new node of type nt:unstructured with the name “dam:Asset”.
  8. Click Save All.
  9. Under the dam:Asset node you just created, create a new node of type nt:unstructured with the name “include0”.
  10. Add a property to the include0 node with the name “path” with a String value set to “”, for example: “jcr:content/metadata”.
  11. Click Save All.
  12. Navigate back up the tree to the damAssetLucene node you created earlier.
  13. Change the value of the “reindex” property on this node to “true”. This should perform a reindex on the repository.

The key thing to note here is that you are replicating some of the same node structure on 6.0 that already exists by default on 6.1, but the compatVersion property is set to 2 in 6.1 and must be set to 1 on 6.0.

With the transition to Jackrabbit Oak, a lot of people are still working out what the best practice is for indexing Oak nodes; this may not be the definitive way to do indexing for properties and nodes in AEM, but it is one way we have found that seems to work well. If you know of a better way then please let us know by tweeting us at @axis41 or emailing info@aempodcast.com.

Adobe Critical Security Hotfix for AEM 5.5.0-6.1

$
0
0

Adobe today released a Critical Hotfix for AEM to patch a flaw (CVE-2015-7501) classified as CVSS 10.0 (highest criticality in the Common Vulnerability Scoring System). You can find information about the Hotfix by logging into your Adobe PackageShare, or by visiting https://www.adobeaemcloud.com/content/marketplace/marketplaceProxy.html?packagePath=/content/companies/public/adobe/packages/cq/hotfix/cq-ALL-hotfix-NPR-8364.

We join with Adobe in recommending that this Hotfix be applied as soon as possible to all AEM servers 5.5.0-6.1.

If you need any background on the issue, or help figuring out how to apply this to your environments, please don’t hesitate to contact us: @axis41 or info@aempodcast.com.

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.

System Notifications: A Quick Review

$
0
0

05287_System_Notifications_A_Quick_Review
We did a podcast about the System Notifications 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 Adobe Experience Manager Commons GitHub page: “ACS AEM Commons System Notifications provide a means to deliver on-platform notifications to Authors using the system. This is a great way to communicate when system activities will occur, are occurring, and have ended.” This is one of the few ACS AEM Commons features that are set up to work in both Classic and Touch UI.

How it works
It allows you to author a page using a scaffolding-like UI to populate and schedule messages that will show to anyone logged into an author instance. You have a few simple controls, such as basic styling, “On” and “Off” times, a title and body, and the ability to disable a notification so it can be reused in the future without annoying the authors in the interim. Other customizations can be done, but you will have to code them in yourself (such as color/branding changes, size, etc.). You can make notifications “not dismissable” so that the message stays up. We have only seen System Notifications implemented for all users. You are not able to customize it to a specific user group.

Since we posted our podcast about this, we were lucky to have a brief email exchange with David Gonzalez, Solution Architect at Adobe and co-project lead of ACS AEM Commons and ACS AEM Tools, giving us a bit more information about styling and the nature of the dismissable. Here are his comments:
“It’s not that straightforward to style the Adobe Experience Manager Notifications; the ‘easiest’ way would be to overlay the CSS classes and change the ‘color’ styles. IIRC the style options are hardcoded into the JSP and not pulled off some configurable list.

* If Dismissable is UNCHECKED, then on EVERY page load the notification will display. You can click ‘Dismiss’ on it to hide it on THAT page, but it keeps showing up. I found that making it totally not-dismissible made it hard to navigate the UI (ex. to turn off the notification).

* If Dismissable is CHECKED, then the dismiss state for THAT notification is stored in a cookie. The key for checking if a notification is dismissed is the path to the notification + the lastModified time of that node—so if anything is changed on that notification, it will show up again.”

Audience impact (authors, admins)

  • admins – A great way for admins to set expectations around, and communicate with, the authors about a variety of things.
  • authors – It notifies them!

Example application
If you have a content freeze for a migration or other system event, you can warn authors before they get involved in a new content project. Or, you can inform users of an issue that is affecting the site or of a software upgrade, etc.

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).


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.

Viewing all 50 articles
Browse latest View live




Latest Images