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