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'.

Monday 8 April 2019

Making SPA's(Single Page Applications) SEO(Search Engine Optimized) Friendly in AEM

AEM now supports SPA SDKs which helps to create Single Page Applications using Angular and React JS. A Single Page Application is a java script code which injects new content from a server into a page without the entire page getting reloaded in the browser. This gives the advantage of faster loading websites.


If we dont take care of SEO from beginning, we may have to put extra efforts to go back and fix the indexing issues later.

Why indexing required?

User comes to the site through various search engines and indexing site pages with this search engines are one of the major task during project implementation.

What is SEO?

Search Engine Optimization is the way which the search engine find the content in a website and index it. We need to ensure our site pages are SEO friendly by following SEO Guidelines. Every search engines like Google, Bing, Yahoo, DuckDuckGo having their own bots to crawl the site content.

This post is written considering the users are having a basic understanding about SEO technology.

Why SPA is not readily SEO Friendly?

The advantage of SPA is, they can even update entire pages or part of the page without making another request to the server or even changing the URL. In this case an entire HTML is not getting rendered. AJAX calls are used to load parts of the page using JSON snippets. SEO expects a fully built page for indexing.

Methods to make SPA s SEO Friendly

Below given some of the methods identified to make SPA pages SEO friendly. This solely depends on the usecase too.

Pretty URLs: Never use 'hashes' in URL's. Always go for SEO friendly pretty URL's instead.

Canonical URL's: 
Here a complete duplicate site would be created within the same url to ensure that crawlers would index the site pages properly.

Pre-rendering: In this scenario, we can run the app before deploying it, capture the page output and replace all HTML files with the captured output. Typically this is achieved with a headless browser (For e.g. Firefox Headless Mode, PhantomJS etc). Pre-rendering is a good choice because there is no additional server load, and therefore faster and cheaper than server side rendering.

Server-Side Rendering (SSR): In this case, pages that display constantly changing data which must be loaded dynamically at load time, or for pages that have user-specific content. Note here, Server hosting the website should have Node enabled to implement server side rendering.

HTML pushState: HTML 5 provides a History API called 'Push State'. The pushState method takes three arguments, a data 'state' object, a 'title' string, and a 'url'. When the pushState method is called, the url which is passed to it will appear in the browsers url window. This method can be used as an alternate indexing options for the SPA pages.


What are all the new features of AEM 6.5?

Below given the further details about new features.
 
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