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>

Thursday, August 4, 2016

AEM6 | Integration with Translations.com

Translations.com's GlobalLink Project Director integrates with Adobe Experience Manager, providing users with a powerful solution to initiate, automate, control, track, and complete all facets of the translation process.


Refer the following links for more details-
http://www.translations.com/products/globallink-AEM-adaptor,
http://www.translations.com/globallink/partners/adobe.html

Translations.com provide packages (in Zip farmat) which can be installed through AEM package manager. They provide two packages- 

a.       GlobalLink-Adaptor-4.7.6.zip (Check the latest packages from TDC site)

b.      GlobalLink-Workflows-2.1.zip (Check the latest packages from TDC site)

Please note that this is not an open source product and you need to contact to TDC to get these packages. Once packages installed, required page templates will be available. Look at the screenshot below-



You need to create pages for each template under /content/global-link (Their latest Adaptor package doesn't need this activity. Their configuration is available from /projects.html page of the AEM instance)-


Configuring Translation.com

First add the new Translation vendor to Translation configurations-































  • On the rail, click or tap Tools > Operations > Cloud > Cloud Services.
  • In the Adobe Marketing Cloud/Translation Integration area, click or tap Show Configurations.
  • Click the + link next to Available Configurations.
    file
  • Type a title for your configuration. The title identifies the configuration in the Cloud Services console as well as in page property drop-down lists. The default name is based on the title. Optionally, type a name to use for the repository node that stores the configuration. 
  • Click Create.
  • On the configuration page, click Edit.
  • On the Translation Integration Configuration tab, select the translation provider, and select the category to use for translating the content.  
  • (Optional) On the User Generated Content tab, select the repository node where the original user-generated content and the translations are stored.
  • Click OK.

  • Now, Go to the Adaptor configuration page in AEM- http://localhost:4502/content/global-link/globallink-adaptor-configuration.html and enter required details for TDC web service URL, account user name, password etc. Screen also asks you to define a language key mapping and properties to include for translation.

    Scheduling Translations

    I am taking here an example of Asset's description metadata field. To submit asset's “description” metadata for translation, follow below steps-

    2. Fill in required details.  Click on the “Find Metadata” button; it will show up the result assets available for translation. Only those assets will be listed which have description property set.
    3.       Expand the asset(s), and check the metadata fields need to be send for translation. Next, move to the “Target Languages” drop-down and select the desired languages. Click on the “Start Workflow” button to initiate the translation workflow. Look at the screenshot below-



    4.       After this, go to TDC submission list page to check status- http://localhost:4502/content/global-link/globallink-adaptor-submissions-list.html

    Verifying Translation

    Translation workflow will update node properties sent for translation with translated text automatically once response is received.

    In order to display translation in front end, you can customize AEM UI to show translated data. In this example I will add a new tab named "Alt Text Translation" to show all Alttext translations to the author. 


    Select "Default" (You can pick image, forms etc. depending on your requirement) and Click on pencil icon to edit it. 

    1. Use the "+" icon next to tags in left hand screen to add a new tab- "Alt Text Translation"
    2. Use the "Build Form" in right hand screen to add language fields.

    Look at the below snapshot on how should it look-



    Once you have saved the metadata template, you can go to Asset Properties from Assets section. The properties section will look like this-


    Note: This article is based on integration of an older version of Translations.com Global Link Adaptor. While working with new adapter version, all above steps may not be required.

    Tuesday, August 2, 2016

    Bulk Editor/ Searching pages based on Parameters

    Bulk editor helps you in editing pages in bulk. Based on query parameters, you can search for pages under a root path and then you can edit properties of those pages. It provides you option to add conditions to fetch list of pages. You can also select additional columns to be displayed in reports.

    Bulk Editor URL: http://localhost:4502/etc/importers/bulkeditor.html


    Below is an example to search all pages with title as "Features"-


    Once the result come; you can edit the property values by double clicking them. Once you are done click on "Save" button. Look at the snapshot below-



    Alternatively, you can use "Export" option to download the result list as TSV file. Then you can modify the values in Excel and then Import it from the following URL-

    Bulk Import URL: http://localhost:4502/etc/importers/bulkeditor.html?hib=false



    You can also create a new TSV file in proper format and Import it using the above URL. While doing so you ought to be very careful to not override any unintended value/ property.

    Monday, August 1, 2016

    XSS Protection in AEM6

    XSS (Cross Site Scripting) protection in AEM to  prevent attackers to inject code into web pages viewed by other users, is based on AntiSamy Java library provided by OWASP (Open Web Application Security Project). Due to this sometime you may get following kind of errors:
    org.apache.sling.xss.impl.HtmlToHtmlContentContext AntiSamy warning: The iframe tag contained an attribute that we could not process. The src attribute had a value of "some-non-xss-standard-iframe-url". This value could not be accepted for security reasons. We have chosen to remove this attribute from the tag and leave everything else in place so that we could process the input.

    Most basic configurations for XSS protection is configured out of the box. In case you need to happen to change this, you can override these configurations but do it carefully because these configurations apply globally. The default AntiSamy configuration can be found at following location in AEM- /libs/cq/xssprotection/config.xml. For reference, XSS rules are defined like this:
    <!-- START: Additions for oembed inserts -->
    <regexp name="iframesrc" value="^(http:|https:)?\/\/(www\.)?(((youtube|youtube-nocookie|vimeo|player\.vimeo|dailymotion|instagram|tumblr|twitter|wordpress|facebook|wikipedia|stackoverflow)(\.com))|(flickr\.com|flic\.kr))\/([A-Za-z0-9]).*"/>
    <!-- END: Additions for oembed inserts -->

    This article categorizes the protection mechanism into two parts-

    1. Code Level Protection

    A. Use the features/ methods provided by XSS API in you AEM application JSP, Servlets, Services etc. while processing user inputs, page selectors etc. XSS API provides two type of features- encoding and validation. In general, validators are safer than encoders. Encoding only ensures that content within the encoded context cannot break out of said context. It requires that there be a context (for instance, a string context in Javascript), and that damage cannot be done from within the context (for instance, a javascript: URL within a href attribute.

    In Java code-
    import com.adobe.granite.xss.XSSAPI;
    import org.apache.sling.api.resource.ResourceResolver;
    
    public class UserInput {
      public String getFilteredURL(ResourceResolver resolver, String userInputText) {
        XSSAPI xssAPI = resolver.adaptTo(XSSAPI.Class);
        return xssAPI.getValidHref(userInputText);
      }
    }
    

    In JSP Code-
    <%@ include file="/libs/foundation/global.jsp" %><%
    %><%
        String siteTitle = request.getParameter("siteTitle");
        String websiteLink = request.getParameter("websiteLink");
    %>
    <html>
        <head>
            <title>
                <%= xssAPI.encodeForHTML(siteTitle); %>
            </title>
        </head>
        <body>
            <a href="<%= xssAPI.getValidHref(websiteLink); %>">Website Link</a>
        </body>
    </html>
    

    B.
    Sightly takes care of XSS prevention itself by virtue of it's framework architecture. This means that all HTML values and attributes are subject to XSS check before they are rendered by server. If you have to explicitly bypass this restriction then you need to use context="unsafe". But be very careful when you decide to do that beacause it disables escaping and XSS protection completely for the applied element which can cause security issues.

    2. Server Level Protection

    A web application firewall, such as mod_security for Apache should be used/ configured on dispatcher to make it more reliable.

    Following rules may come handy to you in security.conf at your dispatcher-

    # Disable cross site scripting

    RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
    RewriteCond %{QUERY_STRING} ^.*(<|%3C).*script.*(>|%3E).*
    RewriteRule .* /errors/404.html
    RewriteRule .* - [F]
    

    # Disable SQL Injection

    RewriteCond %{QUERY_STRING} ^.*(localhost|loopback|127\.0\.0\.1).*    [NC,OR]
    RewriteCond %{QUERY_STRING} ^.*(\*|;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|).* [NC,OR]
    RewriteCond %{QUERY_STRING} ^.*(;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|).*(/\*|
    union|select|insert|cast|set|declare|drop|update|md5|benchmark).* [NC]
    RewriteRule ^(.*)$ - [F,L]
    

    # Disable Clickjacking

    Header always append X-Frame-Options SAMEORIGIN

    # Disable unwanted HTTP Methods

    RewriteEngine on
    RewriteCond %{REQUEST_METHOD} ^TRACE [NC]
    RewriteRule .* - [F]
    RewriteCond %{REQUEST_METHOD} ^TRACK [NC]
    RewriteRule .* - [F]
    RewriteCond %{REQUEST_METHOD} ^DELETE [NC]
    RewriteRule .* - [F]
    RewriteCond %{REQUEST_METHOD} ^OPTIONS [NC]
    RewriteRule .* - [F]
    RewriteCond %{REQUEST_METHOD} ^PUT [NC]
    RewriteRule .* - [F]
    
    Sources:
    1. https://docs.adobe.com/docs/en/aem/6-0/administer/security/security-checklist.html
    2. http://tostring.me/270/how-to-prevent-cross-site-scripting-xss-attack-on-your-adobe-cq-based-web-application/

    Friday, July 29, 2016

    AEM6 | Swedish/ Non English Characters not displaying on page

    If you are facing issue with display of Non-English characters in your site/ page then you can check following things-


    1. Change Request Parameter Encoding 

    a. Go to OSGi configuration console (http://localhost:4502/system/console/configMgr) and search for "Apache Sling Request Parameter handling" Service
    b. Change Encoding to "UTF-8"



    c. If changing this does not work then try restarting AEM after this change.
    d. In worst case, you can apply the encoding to the property directly:
           
           new String(str.getBytes("ISO-8859-1"),"UTF-8"); Where str is the property string

    2. Set Character Encoding to "UTF-8" in Ajax and Servlets.

    Thursday, July 28, 2016

    AEM Troubleshooting/ Useful Links

    Sharing few utility tools/ links-

    1. To find the generated java files in AEM6.1

    Generated JSP JAVA files used to be at -  /var/classes location but AEM6.1 on wards it's no longer present there. This is due to change of repository ClassLoader, now it uses FSClassLoader (File System ClassLoader) for better performance and throughput.

    Generated JSP java files are located at- [AEM_INSTALL_DIR]/crx-quickstart/launchpad/felix/bundle[BUNDLE_ID]/data/classes



    Source: For details read following article - http://labs.6dglobal.com/blog/2015-06-23/new-apache-sling-fs-classloader-console/

    2. Dependency finder- 

    Use the following link to know the maven dependency for a package-http://localhost:4502/system/console/depfinder

    3. Rebuilding clientlibs-

    Use following link to rebuild Client Libraries for CSS and JS-
    http://localhost:4502/libs/granite/ui/content/dumplibs.rebuild.html?rebuild=true


    4. Reecompile JSP

    Use following link to recompile all generated JSP Java files-
    http://localhost:4502/system/console/slingjsp 

    5. Auto Deploy UI Package


    mvn clean install -PautoInstallPackage

    For publish-  mvn clean install -PautoInstallPackagePublish -Daem.publish.host=localhost -Daem.publish.port=4503

    6. Auto Deploy Java Package


    mvn clean install sling:install


    7. Accessing repository through WebDav for Bulk uploads

    Following link describes detailed steps on how to access the AEM repository through WebDav-
    http://labs.6dglobal.com/blog/2016-05-11/webdav-transfers/

    8. AEM Companion App:

    Alternative to WebDav you can use AEM Companion App for Desktops. It is very helpful for managing DAM Assets directly from your system. Here is the link for documentation-
    https://docs.adobe.com/docs/en/aem/6-1/administer/integration/companion-app.html

    9. Grunt Integration with AEM-Maven Project

    http://labs.6dglobal.com/blog/2016-07-21/using-grunt-in-aem-maven/

    10. Monitoring/ Reporting

    Go to- http://localhost:4502/miscadmin#/etc/reports. Following tools are available- 

     11. Bulk Editor/ Searching pages based on Parameters

    12. Checking log files

    system/console/slinglog/tailer.txt?tail=500&name=/logs/error.log

    Tuesday, July 26, 2016

    SDI Integration to render dynamic content through web server

    Below are the steps to integrate Sling Dynamic Include in your project:

    1. Download the source code from- https://github.com/Cognifide/Sling-Dynamic-Include and put it in a folder
    2. Run a mvn clean install command in the folder containing pom.xml
    3. Go to the target folder and pick the created jar file (so generated SDI jar)
    4. Install the bundle in AEM OSGi or placeit in your project install folder
    5. Follow the steps given at- https://github.com/Cognifide/Sling-Dynamic-Include

    Changing Default AEM login background image

    Default AEM login screen is rendered using the login component located at - /libs/cq/core/components/login path. If you need to change anything in login UI, you need to overlay this structure and make changes as desired. One such use case is changing the background image of the default login page.

    Look at the following file in CRXDE Lite - /libs/cq/core/components/login/login.jsp

    You will see that the background image is defined here-

    If you just want to change the background image then overlay the path - /libs/cq/core/content/login/bg/background.png for your project. and place your background.png in the overlayed location in /apps/.

    Thursday, July 21, 2016

    AEM6 | Export Users/ Groups with ACL Permissions

    If you need to transfer users and groups in  AEM from one server to another or from one AEM instance to another then you need to create a package of users/groups along with rep:policy nodes. It is important to include rep:policy nodes as the permissions are stored at the individual target nodes instead of group/ user node. We need to Include all individual rep:policy nodes where you have given access to groups.

    If users are included in the package then :
    Add Exclude rule to users for token: /home/users/.*/.tokens

    The Recommended option is to use acs-aem-commons tool to create a separate ACL package to migrate the ACLs. This utility picks the rep:policy nodes automatically so we don't have to worry about it.

    Follow the below steps :

    1. Create the ACL package as shown below -




    2. Configure the ACL package

    Once package is created open the ACL package page and configure it for groups and users definition.
    While configuring package, it is important that you select all the principles i.e. users or groups which you want to export under "Principal Names". You can keep the "Include Patterns" field blank to ensure that all nodes which have rep:policy node are included automatically. You don't have to include them selectively because doing that may be cucumbersome and  there are chances you may miss few entries.


    You need to check "Include principles" option if the selected principals do not exist in target environment otherwise you can keep it unchecked.

    Set ACL Handling to overwrite (or Merge**)
    **In case the "overwrite" does not work for you, try with "merge" option.

    3. Install the package in destination AEM instance

    Note :- I suggest to perform/ verify this in a test instance first. Ensure you take back of existing User/group definitions before you upload the package in destination AEM instance.

    Troubleshooting: 

    Once you have installed the package in destination, cross verify the users, groups and permission. Make changes in your filter definition in Step 1 as required if you see any issues and build/ install again.
    In case the permissions does not reflect properly, check if you have given the permission at root level i.e. selecting the check all option at the top. Sometimes this give issue so instead of giving permissions at root level, give permissions at sub root level i.e. /content, /etc, /home, /libs etc.


    Sunday, July 17, 2016

    AEM6 | Compatible Audio Codec for MP4 video

    If you want to support mp4 video in AEM then you need to add "libfdk-aac" as audio codec profile in AEM . Just install "libfdk-aac" encoder with FFMPEG. This encoder provides "AAC" audio codec which runs by default on IE , Chrome and Safari browser.

    Thursday, July 7, 2016

    Performance Tuning in AEM6


    1. Tuning the Sling Job Queues
    The bulk upload of large assets may be very resource intensive. By default the number of concurrent threads per job queue is equal to the number of CPU cores, which may cause an overall performance impact and high java heap consumption.  It is recommended to not exceed 50% of the cores. To change this value, go to : http://<host>:<port>/system/console/configMgr/org.apache.sling.event.jobs.QueueConfiguration and set queue.maxparallel to a value representing 50% of the CPU cores of the server hosting your AEM instance (eg. for 8 CPU cores, set the value to 4). 

    2. Create custom oak indexes for all frequently used search queries.
    a) Analyze slow queries
    b) Create the custom indexes under the oak:index node for all search properties
    c) For each custom Lucene-based index, try to set includedPaths
    d) Make use of guessTotal when querying large data sets in the application code.
    e) Cache the search results JSON using a selector-based URL approach

    Following links may help-
    Oak index generator utility: will generate an index definition from a search query

    Granite query performance monitor:

    Granite search index manager:

    Search index config docs:

    Another useful tool for search index developing and debugging:

    3.  JVM parameters
    Prevent expansive queries from overloading the systems:-
    -Doak.queryLimitInMemory=500000 (see also the Oak documentation)
    -Doak.queryLimitReads=100000 (see also the Oak documentation)
    -Dupdate.limit=250000
    -Doak.fastQuerySize=true

    4. Lucene index configuration:
    Open /system/console/configMgr/org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexProviderService and
    enable CopyOnRead
    enable CopyOnWrite
    enable Prefetch Index Files

    5.  Externalize the Data Store
    If you are using AEM Assets or have an AEM application that heavily uses binary files then it is recommended to use an external datastore. 

    6. TAR off-line compaction only
    As per Adobe on line compaction provides high-performing and healthy AEM environment but may cause rapid repository growth. Currently Adobe currently recommends to use the offline compaction, via the oak-run tool as documented under http://docs.adobe.com/docs/en/aem/6-0/deploy/upgrade/microkernels-in-aem-6-0.html#Maintaining the Repository

    7. Disable Link Checker
    If your project requirement does not need checking links on your pages then disable the link checker option from OSGi console-



    Otherwise, follow the below link to figure out if it is causing any issue-

    8. Settings for windows servers
    If you are using windows server then look at the following link to figure out if any extra thing is required-
    https://helpx.adobe.com/experience-manager/kb/high-memory-usage-aem-6.html

    9. Avoid AEM crash during large asset upload
    Follow the below link - https://helpx.adobe.com/experience-manager/kb/cqbufferedimagecache-consumes-heap-during-asset-uploads.html

    10. IE Specific Tuning
    If you support authoring in IE then following article may help you-
    http://aem6solutions.blogspot.in/2016/06/aem6-image-upload-issue-in-internet.html


    CDN | Clearing Cloudflare cache

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