Tuesday 4 June 2019

AEM Site Performance Issues - Root Cause - Analysis - How to Fix

When we say the AEM site performance is hit?

Once the production deployment of an AEM site is done, and if we find slowness in any of the things like pages are loading slow, creation or editing of pages are slow, AEM response times are not fair, AEM is not responding to some requests,  request.log on AEM shows slow response times etc. we can assume there is some issue with the performance of the site.



Common reasons for slow performance

Below given some of the possible reasons for AEM site performance issues;
  • Improper design - Not a deeply though solution
  • High CPU utilization due to long running requests such as slow searches, write-heavy background jobs, moving the whole branches of site content, etc.
  • Application code - Error prone code
  • Memory Issues - Not an efficiently written
  • Insufficient server sizing or incorrect architecture - For a huge site, we did not use mult author multi pubish setup
  • Indexing Issues - Not done a proper indexing
  • Lack of caching - No efficient caching
  • Wrong disk I/O configuration - Improper infra configuration
  • Memory sizing - Not used enough memory
  • Network bandwidth and latency - Not having proper bandwidth allocated
  • Replication Issues - Improper configuration which leads to blockage
  • Ineffective or inadequate maintenance
  • Lack of a Content Delivery Network

How do we analyze the root cause of a performance issue?
  • Check CPU utilization for any AEM process eating much memory
  • Study the request.log file for detailed data
  • Collect thread dumps and analyze them
  • Workflow checks, version checks, audit checks
  • Analyze caching strategies implemented at the AEM dispatcher
  • Check maintenance related to Oak repositories
  • Validate asset guidelines
  • Check indexing and review the jcr queries for 1. Poorly restricted (or scoped) queries 2. Large result set queries 3. Index-less queries

Some of the Tools for validating and fixing AEM performance:

  • JMX Console in AEM : Enables you to monitor and manage services on the CRX server.
  • JConsole : that comes with JDK - helps to find memory leaks, thread deadlock etc.
  • Any other profilers : like YourKit(CPU and memory profiling tool) which recommends the better usage of code
  • Memory analyzer tool - MAT :  Eclipse's MAT is a set of plug-ins for the Eclipse IDE. Helps for heap dump analysis & memory problems in the application
  • Apache Bench : Helps to identify memory leaks, selectively analyze response time.
  • JMeter : Load and functional tests.
  • JProfiler : In-depth CPU and memory profiling.
  • SonarQube : A code validation tool for better code

How to make sites perform better?
  • Ensure you are carrying out regular maintenance
  • Improve back-end service calls to a fail safe state.
  • Optimize AEM client libraries - Embed client libraries, Minify them
  • Cache JavaScript and CSS for long periods of time
  • Optimize Indexes so that querying works better
  • Modify the jcr queries to scope limited and efficient.
  • Install the recommended AEM service packs, cumulative fix packs and hot fixes:
  • Follow the Assets best practices.
  • Allocate enough RAM to avoid IO saturation
  • Enable transient workflows - this avoids manual purging of workflows
  • Tune the Oak Repository as per best practice

Hold on; Before you go for any big changes as part of performance improvements, have a backup plan, Disaster recovery plan do itfirst before you try to fix the performance.

More Like This:

AEM 6.5 Site related new features

AEM 6.5 Specific new features in Assets section

New Features in AEM 6.5 Forms

Foundation updates in AEM 6.5 which a developer should be aware of

Cloud Manager for AEM 6.5 New features


Storage concepts in AEM 6.5   

HTML Template language updates which needs to be observed with AEM 6.5

Friday 24 May 2019

How to fix JSON deprecated API error in AEM? Alternatives of Deprecated JSON API in AEM

When ever we need to retrieve a value from JSON using its key, JSONParser is a better and easy approach.

We know in AEM 6.3, all json related operations are deprecated from package org.apache.commons.json.

For eg  JSONParse, JSONObject.

Let us try to fix this using GSON. AEM has default GSON library to parse the JSON or for JSON processing & conversations.

How to convert a String to JsonObject using Gson library.

Below is the common syntax to use GSON in java code. To use this ensure your pom.xml has the GSON dependency added.

The pattern to use GSON is,

Gson gson = new Gson();
YourClass yourClassObject = new YourClass();
String jsonString = gson.toJson(yourClassObject);


Below given a real case example.

Say we have a multifield in AEM which has a JSON string array as,

String personalData = {"name": "Alex","age":"27","details": "User says at Washington"}

// Now we need to create a Java model class as given below. Remember to match the fields(keys in JSON with string variables )

public class PersonalData {
    public String name;
    public String age;
    public String details;
}


//Now in our sling model or relevant class, the GSON invocation could be something like;

Gson gson = new Gson(); 
PersonalData persondata = gson.fromJson(personalData, PersonalData.class);


Another simple example is
Say we have a multifield as shown below.

String organization = {"org": "Google"}

// Our Java model class
public class OrgData {
    public String org;
}

//invoking the method
Gson gson = new Gson(); 
OrgData orgdata = gson.fromJson(organization, OrgData.class);

Another example using JSON Element

package com.aem.core;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

//This class takes a json string and parse it to get its value from a key.
/*Say we have a json {"key":"value"}
Then to get its 'value' easily without using Java regular expression or patterns
We can use this approach
*/

public class MyJsonParser {

//You can run this code directly to test how it works
    public static void main(String[] args) {
        Gson gson = new Gson();
        String jsonString = "{\"key\":\"value\"}";
//Create JSON element from JSON String
        JsonElement element = gson.fromJson(jsonString, JsonElement.class);
//Fomr a Json Object from element       
        JsonObject jsonObject = element.getAsJsonObject();
//Below line takes the 'key' from json and print its 'value'
        System.out.println(jsonObject.get("key").getAsString());    
    }
}
 

We can also use Jackson for JSON parsing in AEM.

More Like This:

AEM 6.5 Site related new features

AEM 6.5 Specific new features in Assets section

New Features in AEM 6.5 Forms

Foundation updates in AEM 6.5 which a developer should be aware of

Cloud Manager for AEM 6.5 New features


Storage concepts in AEM 6.5   

HTML Template language updates which needs to be observed with AEM 6.5

Monday 20 May 2019

Storage concepts in AEM 6.5

AEM server holds both content and binary data. For a better deployment isolation and organizing data considering performance and scalability of AEM, the binary data(for eg media files) can be stored independently from the content nodes by configuring it.


Generally binary data is stored in a data store, whereas content nodes are stored in a node store. Both 'data stores' and 'node stores' can be configured by updating persistent identifier (PID) in OSGi configuration.

Say when we are working with large number of binaries, Adobe recommends to use an external data store instead of the default node stores. This provides better performance.

The external data store can be File Data Store, Amazon S3 Data Store, Azure Data Store which works well when we need to store binaries like media files.

Node store can be of two types 'Segment Node' Store & 'Document node' store. Segment node store is the basis of Adobe's TarMK implementation & document node store is the basis of AEM's MongoMK implementation in AEM6x.

Configuration PID's for each storage types are given below.

Document node store
org.apache.jackrabbit.oak.plugins.document.DocumentNodeStoreService.config

Segment Node Store
org.apache.jackrabbit.oak.segment.SegmentNodeStoreService.config


File Data Store
org.apache.jackrabbit.oak.plugins.blob.datastore.FileDataStore.config

Amazon S3 Data Store
org.apache.jackrabbit.oak.plugins.blob.datastore.S3DataStore.config PID

Azure Data Store
org.apache.jackrabbit.oak.plugins.blob.datastore.AzureDataStore.config

Summary: Thus by selecting the recommended configurations based on requirement, we can achieve a high performing AEM instance.

Note: The concepts are same for all AEM 6x versions, except a few minor configuration changes.


More Like This:

AEM 6.5 Site related new features

AEM 6.5 Specific new features in Assets section

New Features in AEM 6.5 Forms

Foundation updates in AEM 6.5 which a developer should be aware of

Cloud Manager for AEM 6.5 New features


Storage concepts in AEM 6.5   

HTML Template language updates which needs to be observed with AEM 6.5

HTML Template language updates which needs to be observed with AEM 6.5

HTML Template language updates which needs to be observed with AEM 6.5

While working on AEM 6.5, we can use a set of new HTL Features which are listed below.

1) There is  a new operator 'in' which helps to check availability of an item in strings, arrays and objects.

Usage:
${'c' in 'abc'}
${10 in myArray}
${'b' in myObject}

2) A new data-sly-set to define variables in HTL

Usage:
<sly data-sly-set.title="${currentPage.description}"/>${description}

3) More control for the list iteration using parameters 'begin,step,end'

Usage:
<h2 data-sly-repeat = "${currentPage.listChildren @ begin =1 , step =2 }"> ${item.title} </h2>


4) data-sly-unwrap improvement with identifiers

Usage:
<div data-sly-unwrap.isUnwrapped="${myFirstCondition || mySecondCondition}">
text <span data-sly-test = "${isUnwrapped}"> is unwrapped </span>
</div>

5) Now htl supports negative numbers
So while working with AEM 6.5 , dont forget to utilise this improvements as part of HTL development.

Demo of the new HTL features: 

 

Sample Code given below,

template.html


<!DOCTYPE html>
<!--/* Calling the server-side JS script for all view logic that Sightly cannot do */-->
<html data-sly-use.logic="logic.js">
<head>
    <!--/* Expressions allow to easily output variables */-->
    <title>${currentPage.title}</title>
    <meta charset="utf-8">
    </head>
    <body>
    Hello
        <!--/* To allow some HTML, use the following context option */-->
        <p>${properties.jcr:description @ context='html'}</p>
        ${'a' in logic.myObject}
        ${10 in logic.myArray}
        ${'d' in logic.myString}
       
        <div data-sly-unwrap.isUnwrapped= "${'d' in logic.myObject }">
            text <span data-sly-test = "${isUnwrapped}"> is unwrapped </span>
        </div>
        <p data-sly-use.logic="logic.js" data-sly-unwrap>#### World</p>
     
        <!--/* Iterating over any collection or iterable is easy */-->
        <ul data-sly-list="${logic.myPage.listChildren @ begin =2 , step =1}">
            <li><a href="${item.path}.html">${item.title}</a></li>
        </ul>
            <ul data-sly-list="${logic.myPage.listChildren}">
                <li> ${item.title} </li>
            </ul>

    </body>
    </html>
   
    logic.js
    ----------
        use(function () {
   
    return{
        myString: "abcd",
        myArray: [10,100,1000],
        myObject: {
        a: "Hello",
        b: "World"
        },
        myPage: pageManager.getPage('/content/we-retail/us/en')
    };
});

More Like This:

AEM 6.5 Site related new features

AEM 6.5 Specific new features in Assets section

New Features in AEM 6.5 Forms

Foundation updates in AEM 6.5 which a developer should be aware of

Cloud Manager for AEM 6.5 New features


Storage concepts in AEM 6.5   

HTML Template language updates which needs to be observed with AEM 6.5

How do we access the Magento product detail to AEM? - Magento AEM integration

There are cases where we need to access magento data to AEM. AEM By default supports magento plugin - AEM Extension to import data from Magento.

In some scenarios, Magento exposes the products over API's. In this case we can access the products from Magento using below explained method.

Note: In this example, the Magento API authorization is based on bearer token. The API response is in JSON format.




Java code - to invoke the API and access the products.
-----------------------------------------------------

 //Create a HTTP connection management
 DefaultHttpClient httpClient = new DefaultHttpClient();

 //HttpGet helps posting client data the server.
 HttpGet getMagentoRequest = new HttpGet("Magento API url");

 //Add authorization token as part of request header
 getMagentoRequest.addHeader("Authorization", "Bearer TOKEN");

 //Invoke the API to retrieve response
 HttpResponse response = httpClient.execute(getMagentoRequest);

 //Read the response using buffered readerr
 BufferedReader magentoBr = new BufferedReader(new InputStreamReader((response.getEntity().getContent())));

 String retrievedResult;
 String resultString="" ;

 //capture the entire response in sting format
 while ((retrievedResult = magentoBr.readLine()) != null) {
                resultString = resultString + retrievedResult;
            }
           
           
//Parse the JSON data present in the string format
JSONParser parse = new JSONParser();
//Type caste the parsed json data in json object
JSONObject jsonData = (JSONObject)parse.parse(resultString);

How to retrieve the JSON data?

Say we have below JSON fromat which has primary child and secondary child elements

{
    "id": "file",
    "value": "File",
    "popup": {
        "menuitem": [{
                "value": "New",
                "onclick": "CreateNewDoc()"
            }
        ]
    }
}



//get the individual item from JSON
String ID =  (String) jsonData.get( "id" );
//Now append ID on your bean class object


//Store the JSON object in JSON array as objects (For level 1 array element)

            JSONArray menuItems = (JSONArray) jobj.get("menuitem");
           
            for(int i=0;i<menuItems.size();i++)
            {
            //Store the JSON objects in an array
            //Get the index of the JSON object and print the values as per the index
            JSONObject childItem = (JSONObject)menuItems.get(i);
            String value = (String) childItem.get("value");
            //Now append value on your bean class object
            String onclick = (String) childItem.get("onclick");
            //Now append onclick on your bean class object
            }
           
           
Once we execute the code, we will have the parsed JSON Data available in Bean class.

Now in your HTL, iterate over the bean class objects and display the response.

Debug AEM 6.x using eclipse

Note: This is a tested approach and works for AEM 6.4

Step 1:
Add the Remote Debugging JVM Parameter


In Start.bat update 'CQ_JVM_OPTS' by adding below code

-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n

Click on image to see it big

Step 2: Start a remote debugging session in Eclipse

  • Open Eclipse then choose Run > Debug Configurations.
  • Right-click 'Remote Java Applications' and select 'New'.
  • Select the AEM project under 'Project'.
  • Under 'connection Properties' enter the host. For local dev machine it is 'localhost'.
  • Enter the port configuration of the jvm parameter defined in step 1. In the example, we have given port number as 8000.
  • Save the configuration.
  • Now double-click the newly saved configuration in the Debug Configurations screen.

Demo Video

More Like This:

AEM 6.5 Site related new features

AEM 6.5 Specific new features in Assets section

New Features in AEM 6.5 Forms

Foundation updates in AEM 6.5 which a developer should be aware of

Cloud Manager for AEM 6.5 New features


Storage concepts in AEM 6.5   

HTML Template language updates which needs to be observed with AEM 6.5

Wednesday 24 April 2019

What is Assets HTTP API?

We know that AEM Supports 3 ways of headless delivery in JSON format.

1) Content Services
2) Assets HTTP API
3) Custom Sling Model Exporter


The Assets HTTP API exposes folders and assets from AEM to external world over Restful HTTP APIs.




The API is exposed at http://[server:port]/api/assets and allows all CRUD operations on Assets, including binary, metadata, renditions, and comments.

At present the Assets HTTP API supports the following operations:
  • Retrieve a folder listing
  • Create a folder
  • Create an asset
  • Update asset binary
  • Update asset metadata
  • Create an asset rendition
  • Update an asset rendition
  • Create an asset comment
  • Copy a folder or asset
  • Move a folder or asset
  • Delete a folder, asset, or rendition

Note: Ensure the property 'Filter Methods' l: POST, PUT, DELETE are selected at location > system/console/configMgr>'Adobe Granite CSRF Filter'.