Friday, June 28, 2013

How to check whether the payload is subjected to the workflow or not?

You can use “com.adobe.granite.workflow.status.WorkflowStatus” API to check the WF status of the payload.

      Eg:

WorkflowStatus wfState = <payload object>.adaptTo(WorkflowStatus.class);

          boolean status=false;
          status = wfState.isInRunningWorkflow(true);

HTTP Authentication for HttpURLConnection

Here is the piece of code which you can use for HTTP Authentication while connecting to CQ url:

                final String login ="admin";
                final String password ="admin";
               
                Authenticator.setDefault(new Authenticator() {
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication (login, password.toCharArray());
                    }
                });

              String webPage ="http://localhost:8502/etc/workflow/models/translation?path=test";
              URL url = new URL(webPage);
              URLConnection urlConnection = url.openConnection();

Saturday, June 22, 2013

OSGi Events

Every OSGi framework sends (asynchronously) a number of events that can be captured by any bundle.

Framework Events
  • org/osgi/framework/BundleEvent/STARTED
  • org/osgi/framework/BundleEvent/ERROR
  • org/osgi/framework/BundleEvent/PACKAGES_REFRESHED
  • org/osgi/framework/BundleEvent/STARTLEVEL_CHANGED
  • org/osgi/framework/BundleEvent/WARNING
  • org/osgi/framework/BundleEvent/INFO
Bundle Events
  • org/osgi/framework/BundleEvent/INSTALLED
  • org/osgi/framework/BundleEvent/STARTED
  • org/osgi/framework/BundleEvent/STOPPED
  • org/osgi/framework/BundleEvent/UPDATED
  • org/osgi/framework/BundleEvent/UNINSTALLED
  • org/osgi/framework/BundleEvent/RESOLVED
  • org/osgi/framework/BundleEvent/UNRESOLVED

The followig properties are always present in a bundle event object:

  • bundle.id
  • bundle.symbolicName
Service Events
  • org/osgi/framework/ServiceEvent/REGISTERED
  • org/osgi/framework/ServiceEvent/MODIFIED
  • org/osgi/framework/ServiceEvent/UNREGISTERING

The following properties are always present in a service event object:

  • service
  • service.id
  • service.pid

Ref: http://felix.apache.org/site/apache-felix-event-admin.html

Tuesday, June 18, 2013

How to disable options like ‘Activate’, ‘Delete’, ‘move’ and etc.. to user/group?

 

Disable options

For example, How to disable/remove ‘Activate’ or ‘Deactivate’ option to the specific user/group.

Solution:

1. Go to the CQ useradmin

2. Select the user/group and disable read permissions under (/libs/wcm/core/content/siteadmin/actions).

Thursday, June 13, 2013

How to impersonate the seesion in the workflow?

Here is the piece of code to impersonate the session:

@Reference
SlingRepository repo;

Session adminSession = repo.loginAdministrative(null);
Session userSession = adminSession.impersonate (new SimpleCredentials("<userId>",new char[0]));

          log.debug(“Session is: {}”, userSession.getUserID());

Tuesday, June 11, 2013

Parallel content authoring in AEM/CQ

Q: What if there are two groups of marketing users that want to author the same site/page at the same time but have a different release schedule? How would you solve this problem?

Ans: We can create two launches for each release and various teams can author content and release at different times. Launches is a new feature in AEM(5.6) and documentation can be found here.

Friday, June 7, 2013

Performance Tuning Tips

Performance problems in CQ can be due to many things in combination. Here are few performance tuning tips which improve your CQ performance.

http://helpx.adobe.com/cq/kb/performancetuningtips.html

How to remove features from welcome screen

Question: How do you remove features from the welcome screen, so that only restricted users can access what is allowed? (Eg. Deny a user from accessing the siteadmin Or damadmin).

Solution


You can remove read permission to any of the following nodes in order to deny users from seeing these features in the welcome screen (To deny read permission, please use the security admin console with a superuser) -
1. Modules
Disabling Read Permissions at below levels will disable all the CQ 'Modules' from the welcome screen as well as deny access to the direct urls..

Eg: Disabling Read permissions at ' /libs/wcm/core/content/siteadmin' will Remove 'Websites' option from the welcome screen as well as http://<host>:<port>/siteadmin.html will not be accessible.

Websites - /libs/wcm/core/content/siteadmin
Digital Assets - /libs/wcm/core/content/damadmin
Communities - /libs/collab/core/content/admin
Campaigns - /libs/mcm/content/admin
Inbox - /libs/cq/workflow/content/inbox
Users - /libs/cq/security/content/admin
Tools - /libs/wcm/core/content/misc
Tagging - /libs/cq/tagging/content/tagadmin

2. Resources

Cloud Services -
         Welcome Screen  -  /libs/cq/core/content/welcome/resources/cloudservices
         Url  -  /etc/cloudservices
Workflows
         Welcome Screen  - /libs/cq/core/content/welcome/resources/workflows
          Url   -  /libs/cq/workflow/content/console
Task Management
         Welcome Screen - /libs/cq/core/content/welcome/resources/taskmanager
          Url   -  /libs/cq/taskmanagement/content/taskmanager
Replication
         Welcome Screen  - /libs/cq/core/content/welcome/resources/replication
         Url  -  /etc/replication
Reports
         Welcome Screen  - /libs/cq/core/content/welcome/resources/reports
         Url   -  /libs/wcm/core/content/misc
Publications
        Welcome Screen  - /libs/cq/core/content/welcome/resources/publishingadmin
        Url   -  /libs/media/publishing/admin/content/admin
Manuscripts
       Welcome Screen  - /libs/cq/core/content/welcome/resources/manuscriptsadmin
       Url    - /libs/media/articles/admin/content/admin


3. Docs
Documentation
        Welcome Screen - /libs/cq/core/content/welcome/docs/docs
Developer Resources
        Welcome Screen - /libs/cq/core/content/welcome/docs/dev

4. Features
CRXDE Lite
        Welcome Screen  - /libs/cq/core/content/welcome/features/crxde
         Url  - As per my knowledge, we need to deny access at dispatcher level/ need to write custom service.
Packages
        Welcome Screen - /libs/cq/core/content/welcome/features/packages
        Url  -  libs/crx/cor/content/welcome/core/crx
Package Share
         Welcome Screen - /libs/cq/core/content/welcome/features/share
Clustering
        Welcome Screen  - /libs/cq/core/content/welcome/features/cluster
        Url  -  /libs/granite/cluster/content/admin
Backup 
       Welcome Screen - /libs/cq/core/content/welcome/features/backup
       Url   - /libs/granite/backup/content/admin
OSGi Console
      Welcome Screen - /libs/cq/core/content/welcome/features/config
       Url -  Can't be accessible withour credentials..so there won't be any issue..
OSGi Console Status Dump
       Welcome Screen - /libs/cq/core/content/welcome/features/statusdump
        Url  - /libs/crx/core/content/welcome/osgi/statusdump

Ref:  http://helpx.adobe.com/cq/kb/remove-features-welcome-screen.html









xtypes in CQ

 

http://wem.help.adobe.com/enterprise/en_US/10-0/wem/developing/widgets.html

Wednesday, June 5, 2013

Handy Urls

URLS

/crx/explorer/index.jsp  - CRX explorer

/crx/de/index.jsp – CRXDE Lite url

/libs/cq/search/content/querydebug.html – Query debug tool

/libs/granite/security/content/admin.html – New user manager standalone ui  [5.6 only?]

/libs/cq/contentsync/content/console.html – Content sync console

/system/console/bundles – Felix web admin console

/system/console/jmx/com.adobe.granite.workflow%3Atype%3DMaintenance - Felix web admin console JMX / Workflow maintenance tasks

/system/console/jmx/com.adobe.granite%3Atype%3DRepository - Felix web admin console JMX / Repository maintenance tasks

/etc/reports/diskusage.html?path=/content/dam – To know the size of the repository

Params

wcmmode=DISABLED - This handy publisher parameter turns off CQ authoring features so you can preview a page cleanly

/system/console/depfinder – This new 5.6 tool will help you figure out what package exports a class and also prints a Maven Dependency for the class.

If you have more handy URL’s and or parameters that you think others should know about please comment on this blog entry and I will add them to the list.

Tuesday, June 4, 2013

How to create a custom xtype element for Dialogs ? How to make it as a replicant ?

We can create a custom xtype using the out of the box xtypes from AEM. We can do it using the compositeField. Composite field allows a number of form Fields to be rendered on the same row. We use EXT JS to extend Composite Field and add all the required fields into it as a list. Then, we can register this Class as a custom xtype.

Any user who needs this list of fields together can directly use this custom xtype while developing dialogs instead of creating them individually.  We can use this custom xtype as a mutilfield to make it as a replicant.
Code and Steps are given below.

1) Registering the Custom Component :  Create a Javascript file in Client Lib folder and add that into the Component JSP. This Javascript file is used to create the custom xtype and then register it to with EXT JS , so that it can be used in Dialogs.

CustomPathField.js
----------------------------------------------------------------------------------------------------------------------------------
/**
* @class MyClientLib.CustomPathFieldWidget
* @extends CQ.form.CompositeField
* This is a custom path field with a Link Text and a Link URL
* @param {Object} config the config object
*/
/**
* @class Ejst.CustomWidget
* @extends CQ.form.CompositeField
* This is a custom widget based on {@link CQ.form.CompositeField}.
* @constructor
* Creates a new CustomWidget.
* @param {Object} config The config object
*/

CQ.form.CustomMultiField = CQ.Ext.extend(CQ.form.CompositeField, {
/**
* @private
* @type CQ.Ext.form.TextField
*/
hiddenField: null,
/**
* @private
* @type CQ.Ext.form.TextField
*/
linkText: null,
/**
* @private
* @type CQ.Ext.form.PathField
*/
linkURL: null,
/**
* @private
* @type CQ.Ext.form.CheckBox
*/
openInNewWindow: null,

constructor: function (config) {
config = config || {};
var defaults = {
    "border": true,
    "labelWidth": 75,
    "layout": "form"
};
config = CQ.Util.applyDefaults(config, defaults);
CQ.form.CustomMultiField.superclass.constructor.call(this, config);
},
initComponent: function () {

    CQ.form.CustomMultiField.superclass.initComponent.call(this);
    // Hidden field
    this.hiddenField = new CQ.Ext.form.Hidden({
         name: this.name
    });
    this.add(this.hiddenField);

// Text TextField to enter Title
    this.linkText = new CQ.Ext.form.TextField({
        cls: "customwidget-1",
        maxLength: 100,
        emptyText: "Enter Title",
        maxLengthText: "A maximum of 100 characters is allowed for the Link Text.",
        width: 335,
        allowBlank: true,
        name : "item",
        listeners: {
        change: {
        scope: this,
        fn: this.updateHidden
    }
    }
    });
    this.add(this.linkText);

// Link PathField to map a URL
  this.linkURL = new CQ.form.PathField({
        cls: "customwidget-2",
        allowBlank: true,
        emptyText: "Enter Title URL",
width: 335,
        listeners: {
         change: {
            scope: this,
            fn: this.updateHidden
        },    
        dialogclose: {
            scope: this,
            fn: this.updateHidden
        }
       }
    });
    this.add(this.linkURL);

    // Link openInNewWindow
    this.openInNewWindow = new CQ.Ext.form.Checkbox({
        cls: "customwidget-3",
        boxLabel: "New window",
        listeners: {
        change: {
        scope: this,
        fn: this.updateHidden
        },
        check: {
        scope: this,
        fn: this.updateHidden
    }
    }
    });
    this.add(this.openInNewWindow);
},
processInit: function (path, record) {
    this.linkText.processInit(path, record);
    this.linkURL.processInit(path, record);
    this.openInNewWindow.processInit(path, record);
},
setValue: function (value) {
    var link = JSON.parse(value);
    this.linkText.setValue(link.text);
    this.linkURL.setValue(link.url);
    this.openInNewWindow.setValue(link.openInNewWindow);
},
getValue: function () {
    return this.getRawValue();
},
getRawValue: function () {
    var link = {
    "url": this.linkURL.getValue(),
    "text": this.linkText.getValue(),
    "openInNewWindow": this.openInNewWindow.getValue()
    };
    return JSON.stringify(link);
},
updateHidden: function () {
this.hiddenField.setValue(this.getValue());
}
});
CQ.Ext.reg("CustomMultiField", CQ.form.CustomMultiField);
----------------------------------------------------------------------------------------------------------------------------------
When this Javascript is executed you should have the CustomMultiField as xtype.

2) Using the Custom Component in Dialog: Use this xtype in the Dialog to see all the 3 fields ( Text Field, Link Field , Open in New Window )  displayed as a set.  For example, if we want to display them as a multifield, here is how the dialog.xml should look like.

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
    jcr:primaryType="cq:Dialog"
    width="550"
    xtype="dialog">
    <items
        jcr:primaryType="cq:Widget"
        xtype="tabpanel">
        <items jcr:primaryType="cq:WidgetCollection">
            <tab1
                jcr:primaryType="cq:Panel"
                title="Links Component">
                <items jcr:primaryType="cq:WidgetCollection">
                    <links
                        jcr:primaryType="cq:Widget"
                        border="false"
                        fieldDescription="Press + to add more links"
                        fieldLabel="Links"
                        hideLabel="true"
                        name="./links"
                        xtype="multifield">
                        <fieldConfig
                            jcr:primaryType="cq:Widget"
                            xtype="CustomMultiField"/>
                    </links>

                </items>
            </tab1>
        </items>
    </items>
</jcr:root>


Monday, June 3, 2013

Frequently Used CQ URLs

http://cq-ops.tumblr.com/post/21045033313/frequently-used-cq-urls

What are usual CQ Maintenance operations?

The following is the sequence recommended by Adobe.  A sample RHEL 6.3 shell script that invokes these operations using curl is available for download here.

ONCE PER DAY
——————————

BACKUP

1) Backup

OPTMIZATION

The elapsed times reported below are for a virgin CQ “author” instance with about 70,000 nodes and about 350,000 properties hosted on an SSD.

2) Tar Index Merge

3) Tar Optimization (~ 2 minutes)

This defragments the repository Tar files.  For massive DAM ingestion operations, here is a model that can predict how long this would take.

4) Tar Index Merge (again)

The automatically scheduled Tar optimization does in fact do an index merge, Tar optimize, and a second index merge.

FOR DEV Environment:

5) Consistency Check (~ 3 seconds)

6) Traversal Check (~ 4 seconds)

In addition, the following CQ Knowledge Base article discusses ways to prevent repository inconsistencies from occurring.  Here are links to the sample (v5.6)repository.xml, workspace.xml and start.bat (Windows).  Please note that these settings do slow down CQ startup times, the bigger your repository, the longer the startup.

ONCE PER WEEK
———————————

1) Datastore Garbage Collection (~ 4 minutes)

This removes orphaned files in the datastore that are no longer referenced from within the repository.  The bigger the data store, the longer this operation will take.  See this for a model to predict this.

If your repository is large, you can choose to start the following operations at a level lower than at the top (/ which represents the root of the hierarchical Java Content Repository).  E.g. /content/dam/MySite1Assets for Start Path.

Source: http://cq-ops.tumblr.com/post/29627149909/recommended-sequence-of-cq-maintenance-operations

Search Queries to Determine the Size of CQ’s Repository

CQ comes with a page that can be used to query its repository at http://server:port/crx/explorer/ui/search.jsp

Copy-paste them into the “Query” field and hit the ‘Search Now’ button.  Scroll to the bottom of the page to see total reported numbers.

Make sure you are logged in to CQ as “admin”.  

Total number of nodes

// * order by @jcr:score

Total number of CQ pages

// element(*, cq:Page) order by @jcr:score

Number of audit events

// element(*, cq:AuditEvent) order by @jcr:score

Number of digital assets in DAM

// element(*, dam:Asset) order by @jcr:score

Number of images

// metadata[jcr:like(@dam:MIMEtype, ‘image/%’)] order by @jcr:score

Number of tags

// element(*, cq:Tag) order by @jcr:score

Number of workflow instances

// element(*, cq:Workflow) order by @jcr:score

Number of websites that are “Live Copies” of other websites

// * [@cq:master and not(@jcr:frozenUuid)] order by @jcr:score

Source: http://cq-ops.tumblr.com/post/29906959491/search-queries-to-determine-the-size-of-cqs-repository

How to really delete assets from DAM?

In CQ DAM, files larger than a configurable size (4 KB by default) are kept in a separate “DataStore”.  This DataStore can be located on a separate disk or disk array for performance reasons.

When digital assets are deleted from CQ DAM, they are only “marked” for deletion.  The real cleanup of the DataStore happens during a process called “DataStore Garbage Collection” (DS-GC).  This can be triggered from the Apache Felix OSGi Console (JMX tab) - click on the “Repository” MBean.

How long the DataStore Garbage Collection takes depends on the size of your CQ DAM repository. A property called  ’DataStoreGarbageCollectionDelay’ controls how long (in milliseconds) this process pauses after processing 10 JCR nodes.  By default, this is 10 milliseconds.

For example, if your JCR has 25 million nodes (the result of about 250,000 assets), the scan will take (25 million nodes/10 nodes) x 10 milliseconds = about 7 hours.  The scan happens twice during a single DS-GC run - so the delay would be about 14 hours.

Testing by Adobe’s Server Performance Lab shows that the duration of this garbage collection can be significantly reduced by changing the value for ‘DataStoreGarbageCollectionDelay’ from the default “10” milliseconds to a lower number.  On one lab machine, setting this to 0 caused the duration of DS-GC to go from about 2 hours down to 7 minutes.  Of course, on a busy PRODUCTION system, 0 is a bad idea.

To change the value, just click on the 10.

Source: http://cq-ops.tumblr.com/post/35642664963/speeding-up-cq-dam-datastore-garbage-collection

Best Practices for Component Development in AEM

Good practicing standards on how to develop components including the most flexible folder structure are given below.