Sunday, December 25, 2016

Java Coding- Inheritance Rules

Inheritance should be used wisely. Purpose of inheritance is to have a parent-child (Superclass-Subclass) relationship between objects. In result, it facilitates code reuse. But don't use Inheritance just for code reuse. 
Following two principles help you to use inheritance wisely-

is A? Principle

It helps you decide if you should inherit a class from other i.e. is the new class should or should not extends a super class. So before you decide to extend ask the below question-

Is a "Circle" a "Shape"?
Is a "Triangle" a "Circle"?
Is a "Cat" an "Animal"?

If answer is "Yes" then you should extend the super class.
If answer is "No" then you should NOT extend the super class.

has A? Principle

It helps you decide if a class should have a field or is it relevant to add a new field to a class? Ask below question-

Has a "Circle" has a "radius"?
Has a "Triangle" has a "radius"?

If answer is yes then you should have the field in the class otherwise NOT.


Inheritance facilitates one more Advantage that is in form of another principle-

Liskov Substitution Principle

Any child type of a parent type should be able to stand in for that parent without things blowing up. Reverse of this is not true i.e. you can not replace a child type object with it's parent type object. If you try do so i.e. by means of type casting the parent type object, there is a risk that it may blow up things.

Consider an example where "Animal" <---- "Dog" i.e. Dog extends Animal

A. Suppose a  method which accepts Animal - makeNoise(Animal a). You can always call this method with child type object i.e. makeNoise(d) where d is an object of class Dog.

B. Take another method which accepts Dog - sniffDanger(Dog d). Now you can NOT call this method with parent type object i.e. sniffDanger(a) where a is an object of class Animal. Even if you try to typecast a, something like this: sniffDanger((Dog) a), there is high possibility that it may blow up things, so not a safe approach.

Thursday, December 8, 2016

Enable debugging in AEM running in Vagrant/ VM

If you are running AEM instance in Virtual Box, in order to configure the AEM debug settings follow the below steps-

1. Open the debug port in VM Box. Go to VM Manager, select the AEM instance -> Settings -> Network -> Port Forwarding


Add the debug port 8000 to whitelist it as shown in below image-




2. Go to following location where you have installed kitchen and Run the following command-   bundle exec kitchen login aem-author-c 

OR

Alternatively go to VirtualBox and enter into the aem box by starting it in general mode as shown below-


The box console looks like this-


When asked for username/ password, enter vagrant/vagrant (Default box password)

3. If you are using vagrant then edit your kitchen environment script to change the debug port-


and you are Done!

But, if you are not using Vagrant then follow the next steps.

4. Run sudo su and Go to /opt/aem/author/crx-quickstart/bin

5. Run vi quickstart 

6. Change following line- CQ_JVM_OPTS='-server -Xmx2048m -XX:MaxPermSize=512M' 
to add following in the last
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=8000,suspend=n

7. Run vi start and Repeat step 5 for this file too.

8. Stop and Start the AEM instance.

Wednesday, November 2, 2016

Issues with Replication Queue

Sometimes you may come across to issues with content replication queue. Issue can be at any of 3 levels i.e. Agent level, Service level and corrupt replication queue. Below are the check points for each level to figure out what really went wrong in order to fix them:

1. Issues at Replication Agent Level

First thing to check is the required settings to replication agent. Go to /etc/replication/agents.author.html 



A. Whether agent is enabled? Ensure it is enabled.
B. Verify Transport details e.g. publish server URL, user name, password
C. Verify the trigger tab - The ignore default option should be unchecked unless this agent being used for replication via backend process.
D. Verify the connectivity with the publish instance by clicking "Test Connection".
E. Open the replication log via the "View Log" link and check when the last replication attempt was successful. Take screenshot of the items in replication queue. Try to clear the first item in replication queue, see if it unblocks the replication queue. 
F. Check in CRX Content Explorer, and ensure that there is no /bin/receive node on the publish instance. Otherwise, delete it.
G. Check in CRX Content Explorer, and ensure that there is no /bin/replicate node on the author instance. Otherwise, delete it.

2. Issues at Service Level

To identify issues with replication service, do following things:

a. Disable and enable the replication agent
b. Restart the replication bundle in the Felix console (http://host:port/system/console/bundles/com.day.cq.cq-replication).
c. Restart the Apache Sling Event Support bundle (http://host:port/system/console/bundles/org.apache.sling.event).
d. Restart the Apache Felix EventAdmin (http://host:port/system/console/bundles/org.apache.felix.eventadmin).

3. Issues with corrupt replication queue

Replication Queue is blocked?

Sometimes replication queue is blocked due to issue(s) with a single (or few more) item in replication queue. In this scenario, when you will go to replication queue- it will show Queue is blocked. The root cause might be seen in AEM error logs. So just jump to your error log file and see if you can rectify the root cause of replication error. In case, you are not able the figure out root cause, as a last resort, you can delete the particular entry from replication queue. Start with the very first item in queue and clear it from replication queue. Wait for 30 seconds and refresh to see if queue is unblocked. Repeat it with few other starting items in replication queue until the queue is back in active state. 



In this case, the above does not work then, you need to force the queue clearance by deleting corresponding Sling Jobs. Follow the Adobe link to read in detail- https://helpx.adobe.com/experience-manager/kb/replication-stuck.html

4. Issues with Creating Tmp directory

In case, you have explicitly set an argument like - -Djava.io.tmpdir=/ephetest0/tmp
and you have not created that directory you may see following errors in your log file:

10.10.2017 08:40:52.587 *ERROR* [192.150.10.204 [1507624852318] POST /bin/replicate.json HTTP/1.1] com.day.cq.replication.impl.ReplicatorImpl Error while building replication content.
com.day.cq.replication.ReplicationException: RepositoryException during serialization
at com.day.cq.replication.impl.content.durbo.DurboContentBuilder.create(DurboContentBuilder.java:164) .....
........................
.......................
Caused by: java.io.IOException: No such file or directory
at java.io.UnixFileSystem.createFileExclusively(Native Method)
at java.io.File.createTempFile(File.java:2024)

Resolution to this error is to create the tmp directory at the specified location and give appropriate access.

Tuesday, August 9, 2016

HTL (Sightly) Chit Note - Part 1

In this article, I am going to create a chit note for frequently used HTL syntax that will come handy while working with AEM.

1. HTL does not support JSP tag libraries.


2. Including a script: data-sly-include instead of cq:include

<cq:include script="template.html"/> //Including a HTL file in JSP
<sly data-sly-include="template.jsp"/> //Including a JSP file in HTL

The element on which a data-sly-include has been set is ignored and not displayed.

3. Including a Resource: data-sly-resource

Includes the result of rendering the indicated resource through the sling resolution and rendering process. Basic syntax-

<article data-sly-resource="path/to/resource"></article>

Override resourceType of an include-
<article data-sly-resource="${'path/to/resource' @ resourceType='my/resource/type'}"></article>

Change the wcmmode-
<article data-sly-resource="${'path/to/resource' @ wcmmode='disabled'}"></article>

Include resource parent div


<sly data-sly-resource="${'btn1' @ resourceType='my/components/content/button', decoration=true}"></sly>

4. Changing element tag: data-sly-element

This replaces the element name of the host element-
<h1 data-sly-element="${titleLevel}">text</h1>

Replaces the h1 with the value of titleLevel.

For security reasons, data-sly-element accepts only limited element names.

5. Including clientlibs: data-sly-use and data-sly-call 

In a single statement-

<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html"
     data-sly-call="${clientlib.all @ categories=['myCategory1', 'myCategory2']}"/>

In Separate statements-

<!doctype html>
<html data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
    <head>
        <!-- HTML meta-data -->
        <css data-sly-call="${clientlib.css @ categories='myCategory'}"/>
    </head>
    <body>
        <!-- page content -->
        <js data-sly-call="${clientlib.js @ categories='myCategory'}"/>
    </body>
</html>


6. If Statement: data-sly-test

HTL uses data-sly-test block statement to implement "if" behavior. There is no direct if-else implementation. You need to utilize data-sly-test in an efficient manner to achieve this.

A). Positive condition: if
<h1 data-sly-test="${properties.jcr:title}"> ${properties.jcr:title}</h1>
Negative condition: else
<h1 data-sly-test="${!properties.jcr:title}"> ${pageProperties.name | "Untitled" }</h1>

You can also use relational operators i.e.- "<=", ">=", "==" etc. in your test condition.

B). Always cache test block statement results in an identifier if it repeats itself

<h1 data-sly-test.hasTitle="${properties.jcr:title}"> ${properties.jcr:title}</h1> //if
<h1 data-sly-test="${!hasTitle}"> ${pageProperties.name | "Untitled" }</h1> //else

7. data-sly-unwrap/ sly Element

AEM 6.0 (HTL1.0) has an attribute "data-sly-unwrap" to avoid rendering of referenced HTML tag in context. 

<!-- /* This */ -->
<p data-sly-use.nav="navigation.js" data-sly-unwrap>Hello World</p>

<!-- /* Produces */ -->
Hello World

<!-- /* you can also put condition in data-sly-unwrap */ -->

<p data-sly-unwrap="${someCondition}">Hello World</p>

The above statement will render the hosting element only when the condition evaluates to false. 

AEM 6.1 (HTL1.1) has introduced a new element- "sly" to achieve this. So it is suggested to use sly statement instead of data-sly-unwrap in HTL 1.1 onwards.

<sly data-sly-test="${someCondition}">Hello World</sly>

8. Iterating through a list: data-sly-list Element

<ul data-sly-list="${listObject}">
    <li>Index: ${itemList.index}, Value: ${item}</li>
</ul>

Here itemList provides following properties-
  • index : counter (0-n)
  • count : counter (1-n)
  • first : if the current item is the first item
  • middle: if the current item is neither the first nor the last item
  • last: if the current item is the last item
  • odd: if index is odd
  • even: if index is even
You can also rename the item/ itemList variable name (This is suggested approach to use identifiers instead of using default item naming)-

<dl data-sly-list.child="${currentPage.listChildren}">
    <dt>index: ${childList.index}</dt>
    <dd>value: ${child.title}</dd>
</dl>

9. Use of Display Context

To protect against cross-site scripting (XSS) vulnerabilities, HTL automatically recognises the context within which an output string is to be displayed within the final HTML output, and escapes that string appropriately.

<p style="color: ${properties.color @ context='styleToken'};"></p>
<p>URL: ${teaser.link @ context = 'uri'}</p>

${properties.jcr:title @ context='html'}    <!--/* Use for HTML output. Removes markup posing XSS risks */-->
${properties.jcr:title @ context='text'}     <!--/* Use for plain text content - Encodes all HTML */-->
${properties.jcr:title @ context='elementName'}   <!--/* Allows only white-listed element names, outputs 'div' otherwise */-->
${properties.jcr:title @ context='attributeName'} <!--/* Outputs nothing if the value doesn't map to a valid HTML attribute; Doesn't allow 'style' and 'on*' attributes */-->
${properties.jcr:title @ context='attribute'}     <!--/* Applies HTML attribute escaping */-->
${properties.jcr:title @ context='uri'}     <!--/* Outputs nothing if the value contains XSS risks */-->
${properties.jcr:title @ context='scriptToken'}   <!--/* Outputs nothing if value doesn't correspond to the JavaScript token syntax */-->
${properties.jcr:title @ context='scriptString'}  <!--/* Applies JavaScript string escaping */-->
${properties.jcr:title @ context='scriptComment'} <!--/* Context for Javascript block comments. Outputs nothing if value break out of the comment context */-->
${properties.jcr:title @ context='scriptRegExp'}  <!--/* Applies JavaScript Regex escaping */-->
${properties.jcr:title @ context='styleToken'}    <!--/* Outputs nothing if the value doesn't correspond to the CSS token syntax */-->
${properties.jcr:title @ context='styleString'}   <!--/* Applies CSS string escaping */-->
${properties.jcr:title @ context='styleComment'}  <!--/* Context for CSS comments. Outputs nothing if value break out of the comment context */-->
${properties.jcr:title @ context='comment'}       <!--/* Applies HTML comment escaping */-->
${properties.jcr:title @ context='number'}        <!--/* Outputs zero if the value is not a number */-->
${properties.jcr:title @ context='unsafe'}  <!--/* Use at your risk, this disables XSS protection */-->

10. HTL Comments:

<!--/* An HTL Comment */-->


11. Formatting in Expression:

To format string, you can use Numbered parameters for injecting variables:

${'Assets {0}' @ format=properties.assetName}   <!--/* A shortcut of the array notation, useful when it has one element */-->
${'Assets {0}' @ format=[properties.assetName]}
${'Assets {0} - {1} of {2}' @ format=[properties.first, properties.last, properties.total]}

12. i18n: Internationalization

Following syntax is used to localize string literals in HTL-

${'Assets' @ i18n} <!--/* Translates the string to the resource language */-->

${'Assets' @ i18n, locale='en-US', hint='Translation Hint'} <!--/* Complete syntax with locale and hint options */-->

The i18n option can be combined with the format option, which replaces the placeholders after the string has been run through the dictionary:

${'Assets {0} - {1} of {2}' @ i18n, format=[properties.first, properties.last, properties.total]}

13. Array Join: Implode function

The join option allows to control the output of an array object by specifying the separator string.

${['one', 'two'] @ join='; '} <!--/* outputs: one; two */-->

14. URI Manipulation

Following options are available-
  • scheme (To prepend with http/ https)
    ${'http://example.com/path/page.html' @ scheme='https'} <!-- outputs: https://example.com/path/page.html -->
  • domain
    ${'///path/page.html' @ domain='example.org'} <!-- outputs: //example.org/path/page.html -->
  • path
    ${'http://example.com/this/one.selector.html/suffix?key=value#fragment' @ path=''} <!-- outputs: http://example.com/this/one.selector.html/suffix?key=value#fragment -->
  • prependPath
  • appendPath
    ${'path/page.selector.html/suffix?key=value#fragment' @ appendPath='appended'} <!-- outputs: path/page/appended.selector.html/suffix?key=value#fragment -->
  • selectors
  • addSelectors
  • removeSelectors
  • extension
    ${'path/page.json#fragment' @ extension='html'} <!-- outputs: path/page.html#fragment -->
  • suffix
    ${'path/page.html?key=value' @ suffix='my/suffix'} <!-- outputs: path/page.html/my/suffix?key=value -->
  • prependSuffix
  • appendSuffix
  • query
    ${'http://www.example.org/search?s=1&q=htl' @ query} <!-- outputs: http://www.example.org/search -->
  • addQuery
  • removeQuery
  • fragment
    ${'path/page#one' @ fragment='two'} <!-- outputs: path/page#two -->


References:

Monday, August 8, 2016

HTL (Sightly) Chit Notes Part-2

15. Java Use API

Format to call in html file-

<sly  data-sly-use.javaUseClassName="apps.mycomponent.MyComponent @title='Test Title'">${javaUseClassName.someProperty} </sly> 

Here class name is used without extension.  You cannot pass argument to a method. But it is possible to pass argument at the activation of the Java/Javascript class.

16. JavaScript Use API

<sly  data-sly-use.jsUseClassName="${'mycomponent.js' @ fieldValue =resource.valueMap}">${jsUseClassName.jsonVal}</sly>

Sample js file content -

"use strict";

use(function () {

var nodeJson = JSON.parse(this.fieldValue);
var title = currentPage.getTitle();

var description = properties.get("jcr:description", "default desc");

return {
   jsonVal: nodeJson,
   title: title,
   description: description
}
});

17. Template & Call

Template blocks can be used like function calls: in their declaration they can get parameters, which can then be passed when calling them. They also allow recursion. This consist of following steps:

A. Define A Template: data-sly-template

Template can be defined in a static or dynamic way-

<template data-sly-template.templateOne>blah</template> <!--/* Static Template */-->

<template data-sly-template.templateTwo="${ @ title, resource='The resource of parent node'}"><h1>${title}</h1>
<p>Parent: ${resource.name}</p></template> <!--/* Dynamic Template, with parameter- title and resource */-->

Note that the host element and its content are not output by HTL.

B. Call The Template: data-sly-call

Calling a static template defined above-

<div data-sly-call="${templateOne}"></div>

Calling the dynamic template with parameters-

<div data-sly-call="${templateTwo @ title=properties.jcr:title, resource=resource.parent}"></div>

C. Externalizing The Template (Optional Step): data-sly-use

When templates are located in a separate file, they can be loaded with data-sly-use:

<div data-sly-use.lib="templateLib.html" data-sly-call="${lib.templateOne}"></div>
<div data-sly-call="${lib.templateTwo@ title=properties.jcr:title, resource=resource.parent}"></div>

CDN | Clearing Cloudflare cache

In order to clear Cloudflare cache automatically via code, follow below steps: 1. Develop Custom TransportHandler Develop a custom Trans...