Sunday, September 28, 2014

Building Accordion Component Using AEM 6.0 Slightly Framework




Front end components :


There are two component's, one is accordion container component and another one is accordion section component, the container component will act as a container for section component's

Accordion Container Component Snippet

<script>
  $(function() {
    $( "#accordion" ).accordion();
  });
</script>

<div id="globalcont">
<div id="header">
<div data-sly-resource="${ @path='container', resourceType='foundation/components/parsys'}">
</div>
<div data-sly-use.acc="com.rz.AccordionContainer" >
<div id="accordion">
<ul data-sly-list.child="${acc.src}" data-sly-unwrap=""><h3>
${child.title}</h3>
<p>
${child.body}</p>
</ul>
</div>
</div>
</div>
</div>

Accordion Section Component Snippet

<div data-sly-test="${wcmmode.edit}">Show this only in edit mode to the author</div>


Code base for accordion container component

this is the code base for accordion container component what it does is it will iterate all the child nodes of container component and build custom collection called "AccordionCollection"

The AccordionContainer component extends from WCMUse which is comes with AEM 6.0 slightly framework, the main advantage of this you can get all component related properties ex : getResource()

package com.rz;

import io.sightly.java.api.Use;
import com.adobe.cq.sightly.WCMUse;
import javax.script.Bindings;
import com.day.cq.wcm.api.Page;

import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceWrapper;
import org.apache.sling.api.resource.ValueMap;
import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
public class AccordionContainer extends WCMUse  
{        

 private static final Logger log = LoggerFactory
   .getLogger(AccordionContainer.class);
    List src = null; 
    @Override 
    public void activate()
    {      
        
  Node rootNode = getResource().adaptTo(Node.class);
  try {
   log.error("Executing handler for try");
   if (rootNode != null) {
    log.error("Executing handler for node" + rootNode.getPath());
    Node par = rootNode.getParent();
    log.error("Executing handler for node" + par.getPath());
    NodeIterator child = rootNode.getNodes();
    while (child.hasNext()) {
     src = new ArrayList();
     Node childnode = child.nextNode();
     log.error("Executing handler for section node"
       + childnode.getPath());
     NodeIterator sectionnode = childnode.getNodes();
     long i = sectionnode.getSize();
     log.error("printing the size " + i);
     
     while (sectionnode.hasNext()) {
      Node node1 = sectionnode.nextNode();
      log.error("Executing handler for child section node"
        + node1.getPath());
      String title = node1.getProperty("sectionTitle")
        .getValue().getString();
      log.error("display the property" + title);
      String body = node1.getProperty("sectionBody")
        .getValue().getString();
      log.error("display the property" + body);
 
       src.add(new AccordionCollection(title,body));
              
     }

    }


   
   }
  } catch (RepositoryException e) {
   log.error("any Error");

   e.printStackTrace();
  }
    }   
    public List getSrc() 
    {       
        return src;  
    }
}


Code base for AccordionCollection component

package com.rz;


public class AccordionCollection {

 private String title;
 private String body;
 
 AccordionCollection(String title, String body){
  this.title = title;
  this.body = body;
 }

   
    public String getBody() {
  return body;
 }
 public void setBody(String body) {
  this.body = body;
 }
 public String getTitle() {
  return title;
 }
 public void setTitle(String title) {
  this.title = title;
 }


 @Override
 public String toString() {
  return "AccordionCollection [title=" + title + ", body=" + body + "]";
 }
  
}


Find the output below


Saturday, September 27, 2014

Limit tags selection to certian number in AEM 6.0

Limit tags selection to certian number in AEM 6.0

I see some people have written javascript to limit tags selection to certian number in tags field, but actually there is a OOTB functionality to achieve this and this post will explain how to use OOTB functionality to limit tags selection to certain number

Step 1:

I am going to follow below structure to create tag field but you can use your own strcuture to limit tags selection to certain number, here the tag field node name is categorys


Step 2:

the below properties are created for tag field ( categorys )node


Step 3:

Create node called "namespaces" under your tag field in my case I created under categorys field

The primary type for "namespaces" node is "cq:widgetcollection"

Create a separate node in "namespaces" node and provide whatever name you want, here I given "categorynm"


Step 4:

the below properties are created for tag field "categorynm" node


The "maximum" property plays major role here and this property will limit the number of tags selection and displays error message while authoring




Tuesday, September 23, 2014

Post message on facebook wall from javascript


This article will help you to understand how to post a message on facebook wall

Now a days integration of facebook with application is very common requirement which we see from any client and there are multiple ways to integrate but This article will help you to understand how to post a message on facebook wall using javascript

To access facebook API's first we need to initialize facebook sdk by inserting below snippet directly under
tag

Initialize FaceBook SDK :

<script>
window.fbAsyncInit = function() {
FB.init({
appId      : '1374507272793832',
xfbml      : true,
version    : 'v2.1'
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>

Feed Dialog :

You need to call below code on click event of your custom link

FB.ui(
{
method: 'feed',
name: 'T20mins technology site.',
link: 'http://www.t20mins.com',
picture: 'http://t20mins.com/external-xfbml/share-image.gif',
description: 'Technology.',
message: 'Technology.'
});


Code :

<!DOCTYPE html>
<head>
<script src="http://my7steps.com/sites/all/themes/zulka/js/jquery-1.10.2.js"></script>
</head>
<body>
<div id="fb-root">
</div>
<script>
window.fbAsyncInit = function() {
FB.init({
appId : '1374507272793832',
xfbml : true,
version : 'v2.1'
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>
<a id='share_button' href="#">Post Message</a>
<script type="text/javascript">
$(document).ready(function(){
$('#share_button').on('click', function(e){
e.preventDefault();
FB.ui(
{
method: 'feed',
name: 'T20mins technology site.',
link: 'http://www.t20mins.com',
picture: 'http://t20mins.com/external-xfbml/share-image.gif',
description: 'Technology.',
message: 'Technology.'
});
});
});
</script>
</body>
</html>






Demo :

Click here to post message on facebook wall



An easy way to integrate facebook with your application

Now a days integration of facebook with application is very common requirement which we see from any client and there are multiple ways to integrate but in this article I am going to explain you how to integrate facebook like button with your website using javascript

To access facebook API's first we need to initialize facebook sdk by inserting below snippet directly under
<body> tag

Initialize FaceBook SDK
<script>
window.fbAsyncInit = function() {
FB.init({
appId      : '1374507272793832',
xfbml      : true,
version    : 'v2.1'
});
};
(function(d, s, id){
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) {return;}
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
</script>


The important thing which we need to keeep in mind is appId : '1374507272793832'

You can get appId by going to https://developers.facebook.com/ Settings and App ID


Render Like Button

You need to call below code to render like button
<div  class="fb-like" data-send="true" data-width="450" data-show-faces="true">
</div>

Monday, September 22, 2014

YouTube events are not firing from javascript


While integrating analytics with YouTube player, we found that the custom events were not firing when we use Iframe based javascript approach

Finally we found that by adding "enablejsapi=1" at the end of youtube url then is started working as expected , refer below code

Ex: http://www.youtube.com/embed/0Bmhjf0rKe8?enablejsapi=1

<iframe id="player" src="http://www.youtube.com/embed/0Bmhjf0rKe8" frameborder="0" allowfullscreen>
</iframe>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');

tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
playerVars: {
'autoplay': 1,
'controls': 1
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
var playerReady = false;
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
playerReady = true;

}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.ENDED) {
alert('Fired...');
}
}
</script>

AEM 6.0 BSOD Error

When ever I open AEM 6.0 instance in my local machine the system is going down and getting BSOD error

To overcome this problem, I have installed below things in my local machine

1. Install JDK1.8
2. Install AEM6.0 Service Pack1


Install JDK 1.8 :

you can download and install JDK 1.8 by following below link

http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

Installing Service Pack 1

Recently Adobe has released Service pack for AEM 6.0, you can download it by going through the package share

Install Service Pack :

Unzip your quickstart folder by using below command

java -jar a*.jar -unpack

Now, create a new folder called install in quick-start folder and place Service pack 1 for AEM 6.0 in install folder and then start your AEM 6 instance




Monday, October 7, 2013

Integration with other third-party service

The below list of questions will help you to get some high level overview of how to integrate
your application with other third party services and also will help you what are all the question's
we may need to ask to third party provider
  • Do you have any kind of web interface where we can test web methods by passing sample data?
  • How many ways we can integrate your product in to our application? ( Web-methods, REST API's, JavaScript api's, ODATA etc )
  • Does all API's support all functionality’s?
  • Limitations of your product?
  • Do you have any web interface, where we can do basic/limited operations like creating test user's, checking reports etc...
  • Who will provide secret token? Can we generate secret key by following client side web interface?
  • Any limitation on web service API’s calls count? Will you charge if the request count exceeds?
  • Do we need to send username and password along with web service request or username, password and secret token is enough?
  • Will you charge any amount? if we raise a request to create new user or modify something etc... ?
  • What kind of output does your application returns?
        • JSON
        • XML
        • Encrypted IMAGE
        • IFrame contains html
  • If the output is html, does it support all browsers?
  • What kind of authentication mechanism, do we need to follow while using web-service?
  • If authentication mechanism is basic then do we need to make SSL requests?
  • Does your application supports SSL?
  • Does your web-service supports generating entity classes?
  • How can we identify whether the request is succeed or not?
  • Is there any time-out applied for web-service calls?
  • If we are not able to access your web-service url, what are all the things do we need to check, do you have any trouble-shooting document?
  • Do we need to do any kind of encryption while passing parameters to server?

Wednesday, October 2, 2013

CMS Best Practices

Don't include JQuery libs at component level

I have seen so many people who include JQuery libs at component level, the disadvantage of including at component level is for each and every component the system will make request to server to download JQuery libs and it may lead to page performance

Sometimes we get lot of undefined JavaScript errors because of loading multiple versions of JQuery libs

Solution:

Maintaining central location, I suggest create client libs and include at Basetemplate level, if new version comes just update client libs

In some scenarios the system will force you to include at component level, in such cases use JQuery.noConflict () option to avoid conflicts

Consider that the AEM also provides JQuery libs, some functionality which is depending on particular version of JQuery then download into your clientlibs; otherwise try to utilize OOTB JQuery Libs

Don’t deploy CSS or JS files in to production

Is it right approach deploying CSS, JavaScript files as part of deployment package in “Content Management System”?

Why,  because I have seen some people who came from traditional web development and no knowledge on CMS trying to deploy css and js files through package and finally mess up entire environment like overriding content of css and js files of content authors

How can we handle this situation, in any CMS you can find two types of content one is static content and another one is dynamic content

Dynamic content:

The content which you think it changes frequently by content author or admin’s need to be handled by content deployment or replication or page activation

Ex: Style sheets, images, text etc…

Normally, the content authors or site admin’s performs this action

Static content:

The content which you think it will not change in future need to be deployed as package such as style sheets, images, JavaScript files etc…
This is the developer job and the developer includes this content into package and deploys into a respective environment

Solution:

Don’t include css and js files in your deployment package, if you feel the content author is going to modify it, keep it in central location which can be accessible by content authors as well as developers

Normally in SharePoint you can do this by placing style sheets in style library and in CQ5 you can do this by putting in etc/designs folder

Don’t deploy configuration file in to the production environment

The general meaning of configuration file is to change settings of system at any time, but if you deploy your settings through deployment package that may override existing entries which has made by author and the system may go down

I strongly recommend don’t deploy your configuration settings through package which you feel it changes frequently

Always create I18n folder at site level not at component level

Don’t create I18n folder at component level, if you create your I18n folder at component level you may lose certain capabilities,

Suppose in future if you want to create new locale it is very difficult to check entire solution to identify I18n folders, which needs to convert into new locale and which may lead to maintenance issue and moreover there is a chance for duplicate entries

These duplicate entries may override existing ones and you need to spend lot of time to debug the issue

Always use locale copy while creating new website

Don’t create web site by simply creating pages in hierarchy manner, it is very difficult to implement MSM

The page nName needs to be in the format of or _, for example en, en_US, en_us, en_GB, en_gb.
•    The supported language code is lower-case, two-letter code as defined by ISO-639-1
•    The supported country code is lower-case or upper-case, two-letter code as defined by ISO 3166
 

Don’t iterate nodes, try to use Query Builder, if you are performing any search operation


Use Case:

The user shall be able to receive news based on subscribed opt-in's

The Taxonomy for news is

    Therapy area news                                         
    Oncology news       
       
While registering into site the end user select’s any of news taxonomy keyword either Therapy area or oncology, based on the selection the system will send respective news related email’s to the user

Here, don’t iterate each and every user node to find out opt-in, try to use query build to avoid performance impact

The sibling nodes should not exceed more than 2k

Keep in mind that the sibling nodes should not exceed more than 2k , under normal circumstances it is fine like simple creating and reading node’s but, if you are  performing any kind of search operation on these nodes this may impact on performance


Don't enable dispatcher level cache in lower environment only enable in production environment

Don’t enable dispatcher level cache in lower environment, if you are planning to do load testing, test it on lower environments either pre-prod or the environment which is similar to your production box

Always make sure the cache should be enabling in production box, initially this may impact on performance but while going forward the performance will increase

Before enabling cache in production box think about your application digital asset size, if the volume of size heavy, then it is better to enable cache ASAP

All environments should be in sink to avoid surprises

Always make sure that the environments should be in sink to avoid last minute surprises, I strongly recommend don’t directly work on production environment if you face some problems in production environment, first fix it in pre-prod environment , then test it in prod author and finally fix  it on publish environment

I recommend first deploy package in author and publish environment then replicate content from author to publish environment, before replication content check all configurations are fine or not

I have seen some people who directly work’s on publish environment and making entire system down, but this is not right approach


Don't do over architecture keep it simple


While developing components don’t do over architecture keep it as simple as possible, sometimes the over architecture may impact on performance, for simple components try to reduce layers


Don't store PII information in cookies


The Personal Identification Information is very important for any client, so don’t store PII information in cookies like user password, social security number etc,..

Try to leverage to use OOTB functionalities


Once you receive requirements from your client first check whether it is feasible with OOTB functionality or not, if it feasible then tries to use OOTB, if it is not feasible then only start developing custom components

Identify Data Model before start developing custom components

Choosing database is not an big difficult just compare relational database features with JavaContentRepository features

Ex :

For some of the requirements demands versioning capability, in such cases the relational database does not support versioning functionality, so we need to think about JCR

Avoid loading unnecessary dependencies in POM files


Try to avoid loading un-necessary jar files through POM entries, identify all required common jar files and create separate module and import that in to other modules

This we can achieve only through user education


Don’t refer untrusted resources


I have seen some components which is directly referring like below code


The best practice is download the .js file to your solution and refer it

Use CDN 


To achieve greater performance, if possible try to implement CDN, but this totally depends on client

Don’t hard code CDN server url while making image, video, file etc… it is very difficult to identify each and every link

Create separate Filter which parse each and every url, if it is a digital asset then redirect to CDN server to download that Digital Asset

Create custom error pages


For any website the custom error pages are mandatory like 500 server error, 404 not found etc… if we directly display as it is then this will directly effect on overall website credit

So always design custom error message pages and apply it


XSS

Cross site scripting enable attacker to inject maliculious code in to your system, so don’t forget to encode user inputs before submitting form

Use XSSFilter in CQ5 to validate User entered information

 Know the difference between Sessions

If you see Any CMS there are two sessions one is Admin session and another one is User Session

For read only operations use User sessions and if you are doing some edit and update operations then go with admin sessions

If the requirement is just reading items or nodes and display it on a page then just go with user session

Try to avoid using admin sessions , if  you are obtaining inputs from end user try to store into /content/usergenerated folder in content repository

For just reading nodes and properties use user session slingRequest.getResourceResolver().adaptTo(Session.class)