Monday, September 16, 2024

Using Code to Verify Web Page Accessibility

 To check if a page is available on a particular domain, you can use Java's HttpURLConnection class to send a HTTP request to the page's URL and check the response code. Here's a simple example:


import java.net.HttpURLConnection;

import java.net.URL;


public class Main {

    public static void main(String[] args) {

        try {

            URL url = new URL("http://www.example.com");

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            connection.setRequestMethod("GET");

            connection.connect();


            int responseCode = connection.getResponseCode();

            if (responseCode == 200) {

                System.out.println("Page is available");

            } else {

                System.out.println("Page is not available. Response code: " + responseCode);

            }

        } catch (Exception e) {

            System.out.println("Error: " + e.getMessage());

        }

    }

}

Replace "http://www.example.com" with the URL of the page you want to check. This code sends a GET request to the URL and checks if the response code is 200 (HTTP OK), which indicates that the page is available. If the response code is anything other than 200, it means the page is not available.


We can also automate the process of opening multiple URLs in Chrome using Puppeteer, a Node.js library that provides a high-level API to control Chrome or Chromium over the DevTools Protocol. Puppeteer runs headless by default but can be configured to run full (non-headless) Chrome or Chromium.


const puppeteer = require('puppeteer');


async function openUrls() {

    const browser = await puppeteer.launch();

    const page = await browser.newPage();


    const urls = ['http://www.example.com', 'http://www.example2.com', 'http://www.example3.com'];


    for (let url of urls) {

        await page.goto(url);

        await page.waitForTimeout(5000); // wait for 5 seconds before going to the next URL

    }


    await browser.close();

}


openUrls();


Code to execute this using AJAX

var urls = ['http://www.example1.com', 'http://www.example2.com', 'http://www.example3.com'];


urls.forEach(function(url) {

    $.ajax({

        url: url,

        type: 'GET',

        success: function(res) {

            console.log('Successfully fetched data from ' + url);

        },

        error: function(err) {

            console.log('Error fetching data from ' + url);

        }

    });

});


fetch('https://www.example.com')

    .then(response => {

        console.log('Response status:', response.status);

    })

    .catch(error => console.log('Error:', error));


In JavaScript, you can iterate over multiple URLs using a loop. Here's an example using a for...of loop and the fetch API to send a request to each URL:

const urls = ['http://example1.com', 'http://example2.com', 'http://example3.com'];


for (const url of urls) {

    fetch(url)

        .then(response => console.log(`Status of ${url}: ${response.status}`))

        .catch(error => console.log(`Error fetching ${url}: ${error}`));

}

Friday, July 21, 2023

AEM Interview Questions : OSGi

1. What is OSGi, and how does it relate to AEM?

   - OSGi is a Java-based modular framework that allows applications to be composed of loosely coupled, independently deployable, and manageable components. AEM is built on top of OSGi, using it to provide a scalable and extensible platform for developing enterprise-level web applications.


2. What is the role of OSGi in AEM?

   - OSGi provides the foundation for AEM's modular architecture, allowing it to leverage the benefits of modularity, versioning, and dynamic service management. It enables AEM to have a flexible and extensible architecture that supports the deployment and management of components as independently deployable units called bundles.


3. What are OSGi bundles in AEM?

   - OSGi bundles in AEM are self-contained units of software that encapsulate and provide specific functionality. Bundles can be Java libraries, servlets, services, or any other deployable unit within AEM. They are packaged as JAR (Java Archive) files and can be installed, updated, or uninstalled dynamically without affecting the entire system.


4. What are the advantages of using OSGi in AEM?

   - Some advantages of using OSGi in AEM include:

     - Modularity: OSGi allows for modular development, making it easier to develop, test, and maintain AEM applications.

     - Versioning: OSGi provides versioning support, allowing different versions of bundles to coexist and be managed independently.

     - Hot deployment: OSGi supports dynamic bundle installation, update, and removal without requiring a system restart.

     - Service-oriented architecture: OSGi facilitates the development of loosely coupled services and promotes a modular and flexible architecture.

     - Dependency management: OSGi manages dependencies between bundles, ensuring that required services are available at runtime.


5. How are dependencies managed in OSGi?

   - In OSGi, dependencies between bundles are managed using the OSGi Service Registry. Bundles can declare their dependencies on other services, and the OSGi framework ensures that the required services are available when needed. This dynamic service management enables loose coupling and runtime service discovery.


6. What is the OSGi Declarative Services (DS) specification?

   - The OSGi Declarative Services specification is a standard that simplifies the development of OSGi services. It provides annotations and a configuration mechanism to define services and their dependencies. AEM extensively uses OSGi DS for service component development, making it easier to create and manage services within the platform.


7. How do you create and deploy an OSGi bundle in AEM?

   - To create an OSGi bundle in AEM, you can use a development tool like Apache Maven or Adobe's CRXDE. By following the OSGi specifications, you define the bundle's components, services, and dependencies. Once built, the bundle can be deployed to AEM either manually or using the OSGi bundle management console or package manager.


8. How does AEM handle OSGi bundle lifecycle and versioning?

   - AEM uses the Apache Felix implementation of the OSGi framework to handle OSGi bundle lifecycle and versioning. It allows bundles to be installed, started, stopped, updated, and uninstalled dynamically. AEM also provides versioning support, allowing different versions of bundles to coexist and be managed independently.


9. Can you explain the concept of OSGi services in AEM?

   - OSGi services in AEM are components that provide functionality to other components or modules within the system. Services follow the Inversion of Control (IoC) principle, where the service provider publishes its interface, and the consumer dynamically discovers and uses the service. AEM leverages OSGi services extensively for modular development and promotes loose coupling between components.


10. How do you configure and manage OSGi configurations in AEM?

    - In AEM, OSGi configurations can be managed through the OSGi configuration console (CRXDE) or the Apache Felix Web Console. The console allows you to create, update, and delete configurations for OSGi services. You can set configuration properties and specify values for different environments (e.g., author, publish) to control the behavior of OSGi services in AEM.


11.  What is lifecycle of an OSGi Bundle ?

The lifecycle of an OSGi (Open Service Gateway Initiative) bundle involves various stages, from its initial installation to its eventual removal. Each stage is managed by the OSGi framework, and the bundle goes through these stages during its lifetime. Here's a step-by-step explanation of the OSGi bundle lifecycle:


    1. Installation:

       - The first stage in the lifecycle is the installation of the bundle. During this stage, the OSGi framework receives the bundle JAR file and makes it available in the OSGi container. However, the bundle is not yet active and cannot provide or consume services.


    2. Resolved:

       - After installation, the framework tries to resolve the bundle's dependencies. If the bundle depends on other bundles or services that are not available in the container, the resolution process will fail. In such cases, the bundle remains in the "resolved" state.


    3. Starting:

       - If all the bundle's dependencies are successfully resolved, the OSGi framework proceeds to the starting phase. In this stage, the bundle's `BundleActivator` (if provided) or any components with declarative services are activated. The bundle can now start providing its services or consuming services from other bundles.


    4. Active:

       - Once the bundle is successfully started, it enters the "active" state. It is now fully operational, providing its services to other bundles or applications in the OSGi environment. It can also consume services from other active bundles.


    5. Stopping:

       - During the stopping stage, the bundle's `BundleActivator` (if provided) or declarative service components are deactivated. This process may occur either because the bundle is being explicitly stopped or because it has been updated or uninstalled.


    6. Updated:

       - If a new version of the bundle is installed while the current version is still active, the OSGi framework will update the bundle. The "updated" state represents the period during which the bundle is transitioning from its previous version to the new one.


    7. Uninstalled:

       - The final stage in the lifecycle is the uninstallation of the bundle. When a bundle is uninstalled, it is completely removed from the OSGi container, and all its resources and services are discarded. The bundle can no longer provide or consume services.

    8. REGISTERED:

    In the OSGi bundle lifecycle, the state "REGISTERED" refers to a specific stage in which a bundle's service(s) are registered with the OSGi Service Registry. The Service Registry is a core component of the OSGi framework that allows bundles to publish their services and make them available for other bundles to use.

    When a bundle is in the "REGISTERED" state, it means that the bundle has successfully registered one or more services with the OSGi Service Registry. These services can be Java objects, interfaces, or instances that provide specific functionality or resources. Other bundles in the OSGi environment can then discover and consume these services.

Here's a step-by-step explanation of the "REGISTERED" state in the OSGi bundle lifecycle:

    1. Bundle Activation:

       - When a bundle is activated (usually after it has been installed and started), it has an opportunity to register its services with the OSGi Service Registry. This is typically done in the `BundleActivator` class, which is an optional class defined by the bundle.

    2. Service Registration:

       - The bundle uses the OSGi BundleContext's `registerService()` method to register its services. The method takes the service interface or class as a parameter and publishes it to the Service Registry.

    3. Interface and Properties:

       - Along with the service interface or class, the bundle can provide additional properties when registering the service. These properties can be used by other bundles to filter and discover services based on specific criteria.

    4. Published in Service Registry:

       - Once the service is registered using `registerService()`, it becomes available in the OSGi Service Registry. At this point, the bundle is in the "REGISTERED" state.

    5. Service Consumption:

       - Other bundles in the OSGi environment can now use the services provided by the "REGISTERED" bundle. They can search for the services in the Service Registry using the OSGi BundleContext's `getServiceReferences()` method or use service injection mechanisms (e.g., Declarative Services) to consume the services.

    6. Unregistration:

       - When a bundle is stopped or uninstalled, its services are automatically unregistered from the OSGi Service Registry. At this point, the bundle transitions from the "REGISTERED" state to a "STOPPING" or "UNINSTALLED" state.

The "REGISTERED" state is crucial in the OSGi framework, as it allows bundles to share functionality and resources while maintaining loose coupling and modularity. The Service Registry enables a dynamic and flexible architecture where bundles can discover and use services at runtime, providing a powerful foundation for building modular and extensible applications.

Tuesday, July 18, 2023

AEM Interview Questions: Sightly

1. What is Sightly?

   - Sightly is a templating language and runtime introduced in Adobe Experience Manager (AEM) 6.0. It provides a simpler and more secure way to develop components and templates by separating the markup (HTML) from the logic (Java) using a syntax that closely resembles HTML5.


2. How does Sightly differ from JSP in AEM?

   - Sightly differs from JSP (JavaServer Pages) in several ways:

     - Syntax: Sightly uses an HTML-like syntax, while JSP uses a mix of Java and HTML.

     - Separation of concerns: Sightly enforces a clear separation of markup and logic, making the code more maintainable. In JSP, the logic is embedded within the markup.

     - XSS protection: Sightly provides automatic output escaping, which reduces the risk of cross-site scripting (XSS) attacks. In JSP, developers need to manually escape output.

     - Strictness: Sightly enforces a stricter template structure and syntax, ensuring cleaner code and better performance. JSP is more flexible but can lead to less readable and optimized code.


3. How do you define a Sightly component in AEM?

   - In AEM, a Sightly component is defined by creating a file with a `.html` extension under the component's folder structure. This file contains the Sightly template, which consists of HTML markup enhanced with Sightly's data-sly-* attributes for adding logic and data manipulation.


4. What is the purpose of the Sightly data-sly-* attributes?

   - The Sightly data-sly-* attributes provide a way to embed logic and expressions within the Sightly templates. They allow you to perform actions such as iterating over collections, conditionally rendering content, setting variables, including templates, and accessing component properties.


5. How do you include Sightly templates within other Sightly templates?

   - To include Sightly templates within other Sightly templates, you can use the `data-sly-include` attribute. By specifying the path to the template as the attribute value, the content of the included template will be rendered at that location.


6. How do you iterate over a collection using Sightly?

   - To iterate over a collection using Sightly, you can use the `data-sly-list` attribute. This attribute takes a collection and allows you to define a loop that iterates over each item in the collection, rendering the desired content for each iteration.


7. How can you conditionally display content in Sightly?

   - Sightly provides the `data-sly-test` attribute to conditionally display content. You can specify an expression as the attribute value, and the content within the element will only be rendered if the expression evaluates to true.


8. How do you use variables in Sightly?

   - Sightly allows you to declare and use variables using the `data-sly-use` and `data-sly-attribute` attributes. The `data-sly-use` attribute is used to create a variable and bind it to a Java object, while the `data-sly-attribute` attribute is used to assign a value to a variable.


9. What is the purpose of the Sightly Use API?

   - The Sightly Use API allows you to define Java classes that encapsulate the logic and data for a Sightly component. By implementing the Use API, you can bind Sightly templates to specific Java objects and perform complex logic and data operations within the Sightly component.


10. What are the best practices for writing efficient Sightly code?

    - Some best practices for writing efficient Sightly code include:

      - Minimize logic in templates: Move complex logic to Java classes or services.

      - Use data-sly-resource sparingly: Overuse of `data-sly-resource` can impact performance. Use it judiciously.

      - Leverage caching: Utilize AEM's caching mechanisms to improve performance.

      - Optimize loops: Avoid unnecessary iterations and keep loops as efficient as possible.

      - Use appropriate output options: Utilize the appropriate output options, such as `text`, `html`, or `attribute`, depending on the context of the output.


11. Provide an example of using the data-sly-template attribute in Sightly

Suppose you have a Sightly template that displays a list of products. You want to reuse this template to display different sets of products in different parts of your application. You can achieve this using the `data-sly-template` attribute.


1. Define the template:

```html

<!-- Template: product-list.html -->

<div data-sly-template.productList="${products}">

  <h2>${title}</h2>

  <ul>

    <!-- Iterate over the products -->

    <li data-sly-repeat="${productList}">

      <h3>${item.name}</h3>

      <p>${item.description}</p>

    </li>

  </ul>

</div>

```


In the above example, we define a template with the name `productList` and a parameter `${products}`. It displays the title and iterates over the `products` list to display each product's name and description.


2. Use the template:

```html

<!-- Usage: home.html -->

<div data-sly-use.productsModel="com.example.ProductsModel">

  <!-- Call the template and pass the products parameter -->

  <div data-sly-call="${productList @ products=productsModel.getFeaturedProducts(), title='Featured Products'}"></div>

</div>

```

In the usage example, we use the `data-sly-use` attribute to bind a Java object (`com.example.ProductsModel`) to the variable `productsModel`. Then, we call the `productList` template using `data-sly-call`. Here, we pass the `products` parameter by invoking the `getFeaturedProducts()` method from the `productsModel` object. Additionally, we set the `title` parameter to "Featured Products". The template will be called with the provided parameters, rendering the list of featured products with the specified title.


By using `data-sly-template` and `data-sly-call`, you can reuse templates across different parts of your application and dynamically pass parameters to customize the output. This allows for more modular and flexible development in AEM Sightly.


12. What's the difference between data-sly-repeat and data-sly-list with example

In Sightly, both `data-sly-repeat` and `data-sly-list` are used to iterate over a collection. However, there are subtle differences between the two:


1. `data-sly-repeat`:

   - `data-sly-repeat` is used when you want to repeat a block of code for each item in a collection.

   - It requires an iterable object or a JavaScript array.

   - It creates a new scope for each iteration, allowing you to access properties specific to each item.

   - It provides the `index` variable, which represents the current iteration index.

   - Example:

     ```html

     <ul>

       <li data-sly-repeat="${items}">

         <!-- Access properties of each item -->

         ${item.name}

       </li>

     </ul>

     ```


2. `data-sly-list`:

   - `data-sly-list` is used when you want to generate a string by concatenating values from a collection.

   - It requires an iterable object or a JavaScript array.

   - It does not create a new scope for each iteration, so you cannot directly access properties of each item.

   - It provides the `itemList` variable, which represents the joined string of values.

   - Example:

     ```html

     <p>

       <!-- Concatenate values from each item -->

       The list of items: ${itemList}

     </p>

     ```


Here's a more detailed example to illustrate the difference:


```html

<!-- Template: collection.html -->

<ul>

  <li data-sly-repeat="${items}">

    <!-- Using data-sly-repeat -->

    <h3>${item.name}</h3>

    <p>${item.description}</p>

  </li>

</ul>


<p>

  <!-- Using data-sly-list -->

  The list of items: ${itemList}

</p>

```


```html

<!-- Usage: home.html -->

<div data-sly-use.itemsModel="com.example.ItemsModel">

  <!-- Call the template with a collection of items -->

  <div data-sly-call="${collection @ items=itemsModel.getItems()}"></div>

</div>

```


In the above example, we have a template called `collection.html` that defines both `data-sly-repeat` and `data-sly-list`. When we call this template in `home.html`, we pass a collection of items using `itemsModel.getItems()`. 


- The `data-sly-repeat` section iterates over the `items` collection and displays each item's name and description within `<li>` tags.

- The `data-sly-list` section concatenates the values from each item into a string, which will be displayed in a `<p>` tag.


By understanding the differences between `data-sly-repeat` and `data-sly-list`, you can choose the appropriate attribute based on your specific requirements.    

These answers should provide you with a good understanding of AEM Sightly. 

AEM Interview Questions: Essential Topics to Master

Sling Models in AEM

1. What are Sling Models in AEM?

   - Sling Models in AEM are a Java-based framework that provides a convenient way to map AEM's JCR resources to POJO (Plain Old Java Object) representations. They act as a bridge between the resource-oriented approach of AEM and the object-oriented approach of Java.


2. How do Sling Models work in AEM?

   - Sling Models work in AEM by leveraging the adaptable concept provided by the Sling framework. Sling Models use annotations to define and map the properties of AEM resources to fields within a Java class. They can be automatically adapted to different resource types based on the resource's adaptable hierarchy.


3. What are the advantages of using Sling Models in AEM?

   - The advantages of using Sling Models in AEM include:

     - Easy mapping of resource properties to Java fields.

     - Improved code readability and maintainability.

     - Reduction in boilerplate code.

     - Automatic adaptation to different resource types.

     - Dependency injection of services and resources.

     - Enhanced testability and easier unit testing.


4. How do you define a Sling Model in AEM?

   - To define a Sling Model in AEM, you need to create a Java class and annotate it with the `@Model` annotation. This annotation identifies the class as a Sling Model. The class should also extend the `WCMUsePojo` class or implement the `org.apache.sling.models.annotations.Model` interface.


5. What is the purpose of the @Model annotation in AEM Sling Models?

   - The `@Model` annotation in AEM Sling Models is used to mark a class as a Sling Model. It informs the AEM framework that the class should be treated as a Sling Model and enables the Sling Model functionality for the annotated class.


6. How do you inject resources or services into a Sling Model?

   - To inject resources or services into a Sling Model, you can use the `@Inject` annotation. You can annotate fields, constructor parameters, or setter methods with `@Inject` to indicate the dependencies that should be automatically injected by the AEM framework.


7. What is the difference between @Inject and @Self annotations in AEM Sling Models?

   - The `@Inject` annotation is used to inject services or resources into a Sling Model, while the `@Self` annotation is used to inject the current resource into a Sling Model. The `@Inject` annotation allows you to inject any available service or resource, while `@Self` specifically injects the resource associated with the Sling Model instance.


8. How do you use Sling Models to map properties from a resource to the model fields?

   - To map properties from a resource to model fields, you can use the `@Inject` or `@ValueMapValue` annotations. The `@Inject` annotation injects individual properties, while the `@ValueMapValue` annotation injects a `ValueMap` object containing all the properties of the resource.


9. How can you use Sling Models to adapt to different resource types in AEM?

   - Sling Models automatically adapt to different resource types based on the resource's adaptable hierarchy. By creating different Sling Model classes and defining them to adapt to specific resource types, you can ensure that the appropriate Sling Model is used based on the resource being adapted.


10. Can you explain the concept of Sling Model Exporters in AEM?

    - Sling Model Exporters allow you to expose Sling Models as different output formats, such as JSON, XML, or custom formats. By defining export annotations (`@Exporter` and `@Exporters`) on Sling Models, you can control the serialization and provide custom mappings for the exported output.


11. How do you handle nested resources or child resources using Sling Models?

    - To handle nested resources or child resources using Sling Models, you can use the `@ChildResource` or `@ChildResources` annotation. These annotations allow you to inject child resources as separate Sling Model instances or as a collection of Sling Model instances.


12. What is the purpose of the @PostConstruct annotation in AEM Sling Models?

    - The `@PostConstruct` annotation is used in Sling Models to mark a method that should be invoked after the Sling Model instance has been constructed and all dependencies have been injected. It allows you to perform initialization or setup tasks that require the Sling Model to be fully constructed.


13. How can you handle request-specific data in Sling Models?

    - To handle request-specific data in Sling Models, you can use the `@SlingObject` annotation to inject the `SlingHttpServletRequest` or `RequestContext` object. These objects provide access to the current request and can be used to retrieve request-specific data, such as request parameters or headers.


14. Can you explain the concept of Sling Model inheritance and how it works?

    - Sling Model inheritance allows you to define a base Sling Model class and have other Sling Model classes inherit its properties and behavior. Inheritance is achieved by extending a base Sling Model class using the `@Model` annotation. The child Sling Models inherit the fields, methods, and annotations of the base class.


15. How do you handle multivalue properties in Sling Models?

    - To handle multivalue properties in Sling Models, you can use the `@ValueMapValue` annotation with the `defaultValue` attribute set to an array. This allows you to inject a property as an array or `List` of values. Alternatively, you can use the `@Inject` annotation with the `@Named` annotation to inject multivalue properties as an array or `List` directly.


These answers should give you a good understanding of AEM Sling Models and help you prepare for an interview on this topic.

Saturday, March 21, 2020

AEM Short Useful URL's

Listing down all the important URL's which are useful while working on AEM
  • Login Page  URL:-
         http://localhost:4502/
  • Siteadmin URL:-
         To open, create, delete pages from AEM using classic UI.
          http://localhost:4502/siteadmin
  • Welcome :-
        To go to welcome screen from where you can navigate almost everywhere within AEM.  Here is the link: - welcome
  • System Console URL :-
          To see all the bundles and its state, to navigate to the OSGi configuration of bundle

         http://localhost:4502/system/console/bundles  URL for System console

         http://localhost:4502/system/console/configMgr  URL for OSGi configuration

         http://localhost:4502/system/console/slinglog - URL to add the new logger or see the existing logs in AEM through your browser 
         http://localhost:4502/system/console/status-slingsettings - URL to check the run mode of a server

         http://localhost:4502/system/console/status-slingscheduler - URL to check the status of sling schedulers

         http://localhost:4502/libs/granite/operations/content/diagnosis.html . - URL to check the indexing related logs, performance of a query.

         http://localhost:4502/etc/replication.html - URL to check the replication agents, activate tree












Unit testing or Junit for Sling models using Mockito in AEM


Unit testing or Junit for Sling models using Mockito in AEM


  • First generate AEM sample project with the help of below archetype which will download the sample AEM project compatible in AEM 6.5



mvn -B archetype:generate -D archetypeGroupId=com.adobe.granite.archetypes -D archetypeArtifactId=aem-project-archetype -D archetypeVersion=23 -D aemVersion=cloud -D appTitle="Training" -D appId="training" -D groupId="com.training"-D frontendModule=general -D includeExamples=n

           This will generate a project with below structure





Now add the dependency for Mockito

  • Add below entry in main pom.xml

           
    

  • Add below entry to core/pom.xml .       


     

  • Create new Sling model class with name 'HelloIndiaModel' which will have Sling Objects such as Resource and ResourceResolver, init method and public method getMessage which will return a message based on few conditions.

import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;

import javax.annotation.PostConstruct;
import java.util.Optional;

@Model(adaptables = Resource.class)
public class HelloIndiaModel {

    @SlingObject
    private Resource currentResource;

    @SlingObject
    private ResourceResolver resourceResolver;

    private String message;

    @PostConstruct
    protected void init() {
        PageManager pageManager = resourceResolver.adaptTo(PageManager.class);
        String currentPagePath = Optional.ofNullable(pageManager)
                .map(pm -> pm.getContainingPage(currentResource))
                .map(Page::getPath).orElse("");

        message = "Hello " + getRegion(currentPagePath);
    }

    private String getRegion(String currentPagePath){
        if(currentPagePath.contains("geometrixx")){
            return "Geometrixx";
        }else if(currentPagePath.contains("India")){
            return "Indians";
        }
        else {
            return "World";
        }
    }

    public String getMessage() {
        return message;
    }

}

  • Now go to test folder , create test class for HelloIndiaModel, this class should have an annotation @RunWith(MockitoJUnitRunner.class) which keeps tests clean and improves debugging experience.

  • Try to understand the logic of init method from HelloIndiaModel, first line is using resourceresolver to adapt to PageManager. Since both of these objects are AEM/Sling Objects so we need to mock these Objects in our HelloIndiaModelTest class

  • Line 3 is trying to get the Page from page manager object, Page Object is also belongs to AEM hence we need to mock this object as well

    @Mock
    private Resource currentResource;

    @Mock
    private ResourceResolver resourceResolver;

    @Mock
    private Page currentPage;

    @Mock
    private PageManager pageManager;



  • We have used the @Mock since we need these objects to support testing of class to be tested.
  • Now we need to call the Object of the class which we wish to write test, which can be done by . using the @InjectMocks

    @InjectMocks
    private HelloIndiaModel helloIndiaModel; 

  • Now we need to handle the logic which is written using sling objects in sling model. For example :- what should mockito do when it reaches to the line resourceResolver.adaptTo(PageManager.class); We can specify this with the help of @Before method. 



Methods annotated with the @Before annotation are executed before each test. This is useful when we want to execute some common code before running a test.

@Before
public void setUp() {

    when(resourceResolver.adaptTo(PageManager.class)).thenReturn(pageManager);
    when(pageManager.getContainingPage(currentResource)).thenReturn(currentPage);
    when(currentPage.getPath()).thenReturn("/content/geometrixx");

    helloIndiaModel.init();

}

  • Write first test for the method getMessage

   @Test
   public void shouldMatch(){
         assertNotNull(helloIndiaModel.getMessage());
         assertEquals("Hello Geometrixx",helloIndiaModel.getMessage());
   }


Please find below the complete Test class

import com.day.cq.wcm.api.Page;
import com.day.cq.wcm.api.PageManager;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import static junit.framework.Assert.assertNotNull;
import static junitx.framework.Assert.assertEquals;
import static junitx.framework.Assert.assertNotEquals;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class HelloIndiaModelTest {

    @Mock
    private Resource currentResource;

    @Mock
    private ResourceResolver resourceResolver;

    @Mock
    private Page currentPage;

    @Mock
    private PageManager pageManager;

    @InjectMocks
    private HelloIndiaModel helloIndiaModel;

    //initialize
    @Before
    public void setUp() {

        when(resourceResolver.adaptTo(PageManager.class)).thenReturn(pageManager);
        when(pageManager.getContainingPage(currentResource)).thenReturn(currentPage);
        when(currentPage.getPath()).thenReturn("/content/geometrixx");

        helloIndiaModel.init();

    }

    @Test
    public void shouldNotMatch(){
        assertNotNull(helloIndiaModel.getMessage());
        assertNotEquals("Hiiiii",helloIndiaModel.getMessage());
    }

    @Test
    public void shouldMatch(){
        assertNotNull(helloIndiaModel.getMessage());
        assertEquals("Hello Geometrixx",helloIndiaModel.getMessage());
    }


Monday, February 25, 2019

Debug in AEM IntelliJ


Debug Java Code in AEM using IntelliJ

1) First start AEM in debug mode use below command for the same

java -jar aem-author-4502.jar -fork -forkargs -- -Xdebug -Xrunjdwp:transport=dt_socket,address=59865,suspend=n,server=y -Xmx1520m -XX:MaxPermSize=512m -XX:-UseSplitVerifier

2) Make sure the debug port number 59865 is free

3) Go to IntelliJ, Run Configurations, Remote and click on + icon

4) In the settings, mention the same port which is used while starting the AEM in debug mode


5) Select the debug configuration and click on debug icon , it should show below message

Connected to the target VM, address: 'localhost:59865', transport: 'socket'

6) Set debug points and make a request from Front End, and enjoy debugging !!