Thursday, 11 December 2014

Workflow Details using MBean in AEM

When I was working on my project, I got an interesting task in which - 

I have to retrieve workflow related information such as total number of model, total active model instances, total stale instances for a model, currently active model instances i.e. complete list as displayed in workflow launcher. 

In this post, I will explain how I complete this task. There are lot of different ways to achieve these information for ex. you can write your own custom logic in sling servlet or service & then you will got your result.

But I am not going to do that. In place of it, I will use "Workflow Maintenance Operation MBean". This JMX MBean provides a set of methods, using them, I am able to find required results.

Agenda
1). How to use "Workflow Maintenance Operation MBean" to get workflow related information?


For doing this I have created a project named as blog as shown in left figure - 

Here, I create a component named as -workflowDetailsUsingMbean that uses MBean.

Note : - all JMX MBeans are displayed at -
http://localhost:4502/system/console/jmx

Here just search for "workflow", you will find two MBean services -

First having type Maintenance
Second having type Statics

In this post I will use first MBean service and fetch results from this service.


One more thing I want to ask you -
Do you know, what is the difference between Sling Services and MBean Services?
Shortly, just open both kind of services you will see the difference in MBean services you have access to all the method provided in your service (if exposed) as well as you can directly execute these methods by providing there parameters which is not possible in case of sling services.

NOTE :- If you have no idea about MBeans in AEM then in my next post, I am going to explain everything related to MBean as well as how to register them in AEM.

Now go to http://localhost:4502/system/console/jmx link -> search for "workflow" -> click on workflow MBean having type Maintenance. you will get a screen as -























Here you can click on any of the provided method and provide its required parameters, you are able to get the result of these methods for ex. click on fetchModelList() method and click on invoke, you can see all model present at your instance.

Now go to workflowDetailsUsingMbean component jsp file and paste given code -

<%@include file="/libs/foundation/global.jsp"%>
<%@page session="false"
    contentType="text/html; charset=utf-8"
    import="javax.management.MBeanServerConnection, 
    javax.management.MBeanServer,
java.lang.management.ManagementFactory,
javax.management.ObjectName,
javax.management.openmbean.TabularData,
java.util.* " %>
<%
    try
{
        /* 
          Get MBeanServer Instance for further infor read given link - 
          https://docs.oracle.com/javase/7/docs/api/javax/management/MBeanServer.html
        */
        MBeanServer server = ManagementFactory.getPlatformMBeanServer();

        /*
          QueryNames Method have two parameter one is ObjectName to identify 
            which MBean Service you are looking for & other is QueryExpr which add
            additional conditions to find this object it is similar as database 
            where clauses.For further reading of ObjectName class go through the link - 
            https://docs.oracle.com/javase/7/docs/api/javax/management/ObjectName.html
        */
        Set<ObjectName> names = server.queryNames(
                                                      new ObjectName("com.adobe.granite.workflow:type=Maintenance,*") , null);
        ObjectName workflowMBean = names.iterator().next();
        /*
            Server invoke method is used to invoke a particular operation on existing MBean instance.
            It's parameter details are as follows - 
            invoke(ObjectName name, String operationName, Object[] params, String[] signature)
          I am executing stale workflowitems method from AEM.
        */
        Object staleWorkflowCount = server.invoke(workflowMBean, "countStaleWorkflows", 
                                                                               new Object[]{null}, new String[] {String.class.getName()});
        int mystaleCount = (Integer)staleWorkflowCount; 
        out.println("<h3>Number of Stale workflow instances are - "+mystaleCount +"</h3>");
        /*
          Another method execution that returns list of all workflow model present at your instance.
        */
        TabularData modelList = (TabularData) server.invoke(workflowMBean, "fetchModelList", null,null);
        Iterator itr = modelList.keySet().iterator();
       out.println("<h3>List of Workflow Models</h3>");
        while(itr.hasNext()){
        out.println(itr.next().toString()+"<br>");
        }
    }catch(Exception e){
out.println(e.getMessage());
    }
%>

I provide the description for all method used in JSP with reference URL.  Everything is done just drop this component at your web page you will get number of stale workflow model instances as well as list of all available model at your AEM.

github repository link

Happy Coding
Namah Shivay

Thursday, 4 December 2014

AEM Client Library in Detail

In this post, I will explain client library in detail. i.e. In this post I will explain use of different client libraries properties with the help of working example. So - 

Agenda

1). Use of categories property.
2). Use of dependencies property.
3). Use of embed property.
4). Use of channels property.
5). Use of Client Lib Debugger tool using categories.
6). Adobe CQ HTML Library Manager Service configuration.

For explaining all of these properties, I have created a project named as blog under apps directory as shown below - 
For explaining all of the above task, I have created three things. These are - 

1). I have created three client library named as dependency, embedded & main under clientlibs folder.

2). I created a page component named as clientLibInDetail. This page component will use all of the above specified client libraries.

3). I also created a template named as clientLibInDetail. This template uses the above created page component.



Let's start with the first property of client library folder i.e.




Use of Categories : 

"This property defines to which category this set of CSS & JS files belongs"
i.e. If you define multiple values for this property then this set of JS & CSS belongs to all of these defined categories & wherever you use any of these category this set of JS & CSS will be present there.

If you define only one value for this property, there is no need to make it as String[], just define it as String property. It will work fine but if you want to give multiple value for this property then just define it as String[] and add as many values as you want. In my case property set of these client libraries are - 

property for main.client client library











property for dependency client library









property for embedded client library








Use of dependency Property:

1). It is multivalued property.

2). All categories defined in this property must be in the same order in which you want to load them. i.e. if there are four client libs c1,c2,c3,c4 & you want then to be loaded in c3,c2,c1,c4 sequence then just maintain the same order in this field so that these client libraries will be load in the same manner.

3). For every dependency property value there is a individual hit to the server for loading these categories i.e. if you have four values in this property then 4 hits will be shown at debugging console network tab.

4). When you see  the source of your page using right click -> view source tab you will see same number of script tag will be generated as of values in this property. i.e for 4 values there are four script tags for these values.

Use of embed Property:

1). It is multivalued property.

2). For all embed property value there is only one hit to the server for loading these categories i.e. if you have four values in this property then only one combined hits will be shown at debugging console network tab.

3). When you see  the source of your page using right click -> view source tab you will see only one script tag for all values in this property. i.e if there are n values in this property only one script tag will be generated.

4). Using embed property means add code of all categories into one combined JS & CSS file. i.e. for 4 client libraries c1,c2,c3 & c4 only one combined JS file with the name of parent client library name is created.

NOTE : Name of final JS file will be same as parent client lib name. i.e. main.js or main.min.js (if minified) option is clicked in HTML Service.

5). All categories defined in this property must be in the same order in which you want to add them in main client library. i.e. 
if there are four client libs c1, c2, c3, c4 & you want them to be added in c3, c2, c1, c4 sequence in main client library then just maintain the same order in this field so that these client libraries will be added in the same manner. 
i.e. if you have embed property value in the given order with simple alert message. c1, c2, c3, c4 then first c1 alert will be executed then c2 alert then c3 then c4 & at the end main.client.lib JS file that embed these categories alert will be executed.

Use of channel Property:

1). It is multivalued property.
2). It is used to some additional functionality for different channels. For example : 
if you want to perform some JS functionality only for ie6 not for other browsers, or you want to add some CSS or JS for only touch UI. then this channel property comes into picture.


I will give you a demo for this property for this in my main client library just add channel property & it's values as "touch" as shown in figure - 












effect of adding this property is :- 
As I added this property to my main client library so the main.min.js or main.js will not be available for desktop system.
i.e.
I have added three alerts in these three client libs as given below -
main.js - " Main js working fine" 
dependency.js - "dependency is working fine"
embed.js - "embed is working fine"

as embed is a part of main.min.js or main.js (if not minified) so you don't get two alerts for main.js as well as for embed.js but for dependency.js, I will get an alert as it is not a part of main.min.js or main.js file.

Use Case for this property - 
If you want to achieve some functionality for touch only devices then just create two client libraries with same category name & in first client lib add common code for all channels & in second client lib use this property channels and set it's value as touch. So that for touch devices both of these client libs are loaded and you will get your desired functionality. For non touch devices only first client lib is loaded as second have this channel property it will not be available here.

I have used four values for this property ie6, extjs, touch & negation of these values.
Note: I have checked this functionality only for ie6, extjs, touch, !touch. 

AEM client lib debugger tool
AEM provides a UI for debugging a tool for identifying all the JS, CSS & themes related to a particular client lib. you can find it at - 
http://<IP-Address>:<PORT>/libs/granite/ui/content/dumplibs.test.html in my case it is -
http://localhost:4502/libs/granite/ui/content/dumplibs.test.html
when you hit this URL you will see a screen where you can enter a client lib category name and it will show you How this client library CSS & JS file will be available in different modes. As show in fig. - 























It will show which CSS files and which JS file are included in this category with there dependency file name as well as their embedded file name. Also show the channel value.

Adobe CQ HTML Library Manager Service configuration

Go to Felix console ->> Configuration tab -> search for "HTML Manager Service" yow will get a screen as - 





















All properties are self explanatory.

reference documentation - 
http://docs.adobe.com/docs/en/cq/current/developing/clientlibs.html

github repository link

Happy Coding
Namah Shivay

Thursday, 13 November 2014

Custom Action in Configuration Bar in AEM

In my last post, I explained, how to create configuration bar in CQ using cq:EditConfig node as well as using Ext - JS. When I was doing that R & D a question come in my mind that using cq:actions property of cq:EditConfig node, we are restricted to used only few operation i.e. EDIT, DELETE, COPYMOVE, INSERT & TEXT.

What if I want to create my own custom action? How will I achieve it?

So In this post, I will explain how to add custom action into configuration bar.

Agenda
1). Use of cq:actionConfigs node.
2). Custom Action creation.

For doing this I create a project structure as shown below - 

Here I create a simple component named as customActionForConfBar.

Create a cq:EditConfig node under your component.

Brief Introduction of cq:editConfig-
"Edit config node is used to change the behaviour of a component."

under cq:editConfig node create a node having primary type nt:unstructured, name it as cq:actionConfigs.

" cq:actionConfigs node is used to append new action to the actions specified in cq:actions  property of cq:editConfig node of your component."

Under cq:actionConfigs node create nodes of type nt:unstructured. If you want two action then add two node of any name.

In my case, I create two nodes seperator & customAction used for - 
seperator -  for adding a separation (|) between two actions. 
customAction - This node denote my custom action.

at cq:editConfig node add properties as displayed - 












at seperator node add properties as  - 






at customAction node add properties as -







This node is main for creating custom action. Here I add two properties 

text - This property is used to add the name to the configuration bar. i.e. At configuration bar you will see one more button named as "My Action".

handler - This property is used to define a action or function to be done when this "My Action" button has been clicked on web page. This handler defines a javascript function. So in my case I want to open a new dialog box of it's child component. My JS code is - 

function(){ 
var editRollOver = CQ.utils.WCM.getEditable(this.path+"/childcomponent" );
CQ.wcm.EditBase.showDialog(editRollOver, CQ.wcm.EditBase.EDIT);
}

This function is first getting a roll over configuration of my child component named as "childComponent" & then open it's dialog. 

As I have another component named as childComponent as displayed in my project structure. I will open childComponent dialog when I click on "My Action" button of configuration bar of customActionForConfBar component. for creating component within component refer my Component with in Component blog post.

Note : 
1). Do not create parsys node just use your component node directly & include your child component in customActionForConfBar.jsp file. so your jsp file code becomes  - 
<%@include file="/libs/foundation/global.jsp"%>
<b>Container Component with default component in parsys</b><br/><br/>
<cq:include path ="childcomponent" resourceType ="blog/components/content/childComponent" /> <br/><b>End of Container Component</b>

2). Change childComponent componentGroup property to .hidden as it's created only for custom action & also remove any code from it's jsp file.


Everything is done now. go to your web page and drop customActionForConfBar component. you will see a configuration bar with custom action & when you click on this button you will see a screen as 


github repository link

Happy Coding
Namah Shivay

Wednesday, 12 November 2014

Configuration Bar in AEM

During my project, I got a task in which I have to create a Configuration Edit bar in publish mode for setting some of the particular publish instance level properties. In this post I will explain the approach I used to complete this task.

Agenda 
1). How to create Configuration Edit bar using cq:EditConfig node?
2). How to create Configuration Edit bar using Ext-JS node?
3). Difference between cq:EditConfig vs Ext-JS configuration Edit bar?

Approach - I :  

I will show you how to create configuration tab using cq:EditConfig node. 

For doing first I create a project structure as shown in fig. - 
Then, I have created a component named as -
componentWithEditBar.

Then I create a node of primaryType cq:EditConfig with a name cq:editConfig under componentWithEditBar node as displayed in image.

Note : Name of this node must be cq:editConfig


Also add  properties on cq:editConfig node as shown in figure - 


Now when you drop this component on your web page you will see a configuration bar for this component in author mode. your screen will be look like this - 

















Approach - II :
How to create this configuration bar using Ext-Js code?
For doing this I have created a new component named as componentWithEditBarUsingExtJs.
in it's jsp file I add the given JS code - 

<%@include file="/libs/foundation/global.jsp"%>
<%@page session="false" %>
<%
    String path= resource.getPath();
    String resourceType= resource.getResourceType();
    String dialogPath = resource.getResourceResolver().getResource(resourceType).getPath() + "/dialog";
%>
<script type="text/javascript">
        CQ.WCM.edit({
            "path":"<%= path %>",
            "dialog":"<%= dialogPath %>",
            "type":"<%= resourceType %>",
            "editConfig":{
                "xtype":"editbar",
                "listeners":{
                    "afteredit":"REFRESH_PAGE"
                },
                "inlineEditing":CQ.wcm.EditBase.INLINE_MODE_NEVER,
                "disableTargeting": true,
                "actions":[
                    CQ.I18n.getMessage("Configuration Tab Using Ext-JS"),
                    {
                        "xtype": "tbseparator"
                    },
                    CQ.wcm.EditBase.EDIT,
                    {
                        "xtype": "tbseparator"
                    },
                    CQ.wcm.EditBase.DELETE

                ]

            }
        });
        </script> 
<br/>
<h3>Example for showing component with a configuration edit bar using Ext Js.</h3>
<br/><br/>


Now when you drop this component you will see a screen like this - 















Difference between these two approaches : 

When you want that your configuration bar is visible only in Author mode, use first approach.
Using first approach this configuration bar is visible in Author mode only and when you publish your code then it will be disappeared. Maximum time we have this type of requirement so generally we go with first approach.

But I got a task in which I am integrating AEM with Salesforce & we have to set some setting which are dependent on each publisher. This is a very specific requirement for achieving this when I go with approach one then my configuration bar has been disappeared then I start my R & D for achieving this goal & then I found this second approach using this approach I got the same functionality as I achieve using first approach.

The only difference is when I follow second approach my configuration bar is visible in author as well as in publish mode & works for me.

github repository link
https://github.com/vietankur009/blog.git

Happy Coding
Namah Shivay

Component with default Components in CQ5

During my project work I got a task in which I have to create a container component having a parsys & some default child component. In this post, I will discuss, how I achieve this functionality.

Agenda
1). How to create a container component having a parsys & some child component? i.e.

" Whenever I drop containerComponent on my webpage, I will get a childComponent & a parsys already present there so that I don't have to drop childComponent from sidekick. "

For achieving this functionality, I  create a project structure as shown below - 
Step : 1
Here I create two simple component one is childComponent & another is containerComponent.
Now drop these component on your webpage so that you are able to see component nodes with their names under 
/content/<your project>/jcr:content/par/<component name>. 
in my case it is -  
/content/blogSite/jcr:content/par
as shown below - 




Step 2: 
Go to your containerComponent in apps/blog/component/content folder.
Under containerComponent node create a nt:unstructured node with a name of cq:template.

Note :  name must be cq:template.

Step : 3
Copy par node from /content/blogSite/jcr:content node.
Paste this node under containerComponent/cq:template node in your project and rename it as parsys. In my case it is apps/blog/component/content/containerComponent/cq:template.
your structure looks like - 










Step : 4
Delete containercomponent node from cq:template node as we only want childcomponent under containerComponent. new structure looks like -

Step : 5
in containerComponent.jsp file just include this parsys node using cq:include.
my code for containerComponent.jsp is 














<%@include file="/libs/foundation/global.jsp"%>
<b>Container Component with default component in parsys</b><br/><br/>
<cq:include path ="parsys" resourceType ="foundation/components/parsys" /><br/><br/>
<b>End of Container Component</b>

Note : path property of cq:include tag must have the same value as that of the name or the parsys node under cq:template.

Note : If you don't want to see your childComponent in sidekick then just change it's componentGroup property with .hidden & it will disappear from sidekick.

now when you drop containerComponent  from your sidekick you will see a screen like this - 
github repository link
https://github.com/vietankur009/blog.git

Happy Coding 
Namah Shivay

Wednesday, 8 October 2014

Component Group not visible in AEM Sidekick

In this post, I will address a common issue which we face when we create a component with new group. 
Sometime it happens that we create a component using CRXDE Lite and defined a new group there & when we go to our web page sidekick in design mode, we are not able to see this component group there. 
Most of AEM developers are suffering with this common issue and we are not able to find why this group not visible in sidekick. In this post, I will show you what common mistake we did while we create a component using CRXDE Lite. So

Agenda
1).  Why Component group not visible in sidekick?
2).  How to resolve this issue?
3).  How to make it work as it is i.e. without changing in component?

NOTE: - 
This problem is present in CQ5.x as well as AEM6 so it's solution work for all CQ5.x and AEM6 version.

For addressing this issue I just create a new component with these properties - 













Everything is looking right but when I go to your web page sidekick in edit mode, click on parsys edit button, in this list are not able to see this component group.

Cause of this issue.
My finding tells that jcr:title property started with small letter, So that it's not visible in sidekick.

Solution
Just change this property value "blog" with "Blog" & again go to your web page. First clear your Browser cache, then refresh your web page. goto sidekick. Here it is, your component is visible here.

Convention to create new Component According to my findings
As you see there are lot of groups present in sidekick, all are started with capital letter, so you just follow these assumption while creating new component - 

1). Keep  jcr:title property values Starting with a capital letter. It's a mandatory property for displaying this component group in sidekick.

2). Keep componentGroup property starting with capital letter, while it's not mandatory but for displaying it in sorted order in sidekick, it's good to have it. if you don't define this property then this component will be visible under "NO GROUP DEFINED!" component group.

How to make it work without changing these properties?
Some of my colleagues ask me that we don't want to change these properties then how to use this component group.
Answer is when you select a group from sidekick then it's value will be stored at template node under design page jcr:content node. This design page  property is a template level property and present at jcr:content node of your template. If you don't define this property then AEM create a nt:unstructured node under /etc/designs/default/jcr:content node having name same as of your template name.

In my case, I don't define any design page property so I have my design level properties under /etc/design/default/jcr:content node, with a name of my template name (homepage). This node is of type nt:unstructured.
Under this node we have different node for different parsys, just go to any parsys node in my case it is par as displayed - 

Select your par node, here you will see some properties on your right panel of screen.


it looks like - 














If you select any of group like General or any other then you will see components property but if you don't select any of group then this property will not be displayed. If you don't have this property then Just create this property as string array and set it's value having syntex

Syntex - I
group:<new group name>
in my case it is 
group:blog

Syntex - II
Copy and paste relative path or absolute path of your component. In my case it is 
/app/blogComponent/components/content/blog
Here no need to define group: prefix.

Save it, goto your web page, clear browser cache, and reload the page now you are able to see you component group in sidekick. This is the fix only but if you want to remove it from sidekick then it's not possible to directly uncheck from sidekick as it is not visible in that list, So you have to do it manually.


Happy Coding 
Namah Shivay

Tuesday, 7 October 2014

Pre - Populated Multifield in AEM

During my project work, I got a task where I have to prepopulate a multifield with some predefined values. i.e when a multifield is loaded first time, It should be displayed with some default values. In this post, I will discuss, How I achieve this functionality. So 

Agenda of this post
Prepopulate Multifield with default values

For doing this, I am creating a project using adobe maven archetype as I created in my last post. It create a folder structure under app directory as shown below - 

Here I create a component named as blog

This component contains a dialog having a tab with a multifield & one listener (nt:unstructured) node under cq:dialog node.

So the final structure looks like - 



multifield is created with properties 
xtype = multifield
jcr:primaryType = cq:Widget
name = ./names
fieldLabel = Names

fieldconfig node have properties 
xtype = textfield
jcr:primaryType = nt:unstructured

Till now what ever we create is simple work which is required to create a simple multifield. 

Key point is - 
Now the original work for starts for prepopulating multifield. As we create on additional node named as listeners under dialog node, jcr:primaryType of this node is nt:unstructured.
here I define a function named as loadcontent as type string and It's values is a javascript function that set's the default value for this multifield. the function value is -

function(dialog) { 
var field = dialog.getField('./names'); 
if(field.getValue()){
var values = ["Pre", "Populated", "Multifield"];
field.setValue(values);
};
return true;
}

this node's properties look like-











Now Everything is done go to a test page drop this component & open dialog. You will see your multifield is prepopulated as desired.

final output is -
























github repository link

Happy Coding
Namah Shivay