Sunday, December 29, 2024

A Step-by-Step Guide to Adding Clientlibs to AEM Components and Working with SCSS | Adobe AEM

 Adobe Experience Manager (AEM) offers robust tools for developers to create highly customizable components. In this guide, we’ll show you how to add client libraries (clientlibs) to specific components in AEM and seamlessly integrate SCSS for styling. Let’s break it down step by step.



A Step-by-Step Guide to Adding
 Clientlibs to AEM Components and Working with SCSS

Structure of Component



How to Create a Component in AEM

Creating a component is the first step in building customized functionality in AEM. Here’s how you do it:

  1. Navigate to the desired folder where you want to create the component.
  2. Click on "Create" and select "Create Component from Dialog" from the dropdown menu.
  3. Fill in the details, such as:




  4. Click Next, and your component will be created.
  5. Rename the generated .jsp file to .html to use the HTL format for modern templating.




  6. Add a cq:dialog node for configuration:
    Click Create > Create Node, or
    Copy and paste the cq:dialog from an existing core component.
  7. Drag and drop your new component onto the page, and its contents will render.




How to Add Clientlibs to Specific Components in AEM

Client libraries are essential for adding styles and scripts to your AEM components. Follow these steps to create and link clientlibs:

1. Create the Clientlibs Folder

  1. Navigate to the component node in CRXDE Lite.
  2. Click on "Create" and select "Create Node".
  3. Name the node (e.g., clientlibs) and set its type to cq:ClientLibraryFolder.




2. Add Folders for CSS and JavaScript

  1. Inside the clientlibs folder:
    Create a folder named css and place all your CSS files inside.
    Create a folder named js and place all your JavaScript files inside.
  2. Add two files:
    css.txt: Import your CSS files (e.g., style.css).
    js.txt: Import your JS files (e.g., script.js).



3. Configure the Clientlibs Properties

  1. Select the clientlibs folder and add the following properties:
    categories: Assign a unique category name (e.g., mycomponent.styles).
    allowProxy: Set this to true for accessibility.

4. Include Clientlibs in Your HTML File

To link the clientlibs in your component, add the following code to your .html file:



code:

<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
    <sly data-sly-call="${clientlib.css @ categories='testScssClientlibs' }" />
</sly>
<h1 class="myClass">Test Scss Component is working</h1>
<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
   
    <sly data-sly-call="${clientlib.js @ categories='testScssClientlibs'}" />

</sly>

5. Verify Your Work

Reload your AEM page, and you should see your CSS and JS files successfully applied to the component.


How to Load Static Resources in a Component


To load static resources like images in AEM components, follow these steps:

  1. Create a folder named resources within your clientlibs directory.
  2. Place your images inside the resources folder.
  3. Use the path "/apps/emoney/components/site-components/TestScssCompo/test-scss-compo/clientlibs/resources/images/img1.png" to reference the image.
  4. This path can be used in both HTML and CSS files to load the image.





How to Use SCSS with AEM Components

For advanced styling, SCSS provides a cleaner and more maintainable approach compared to plain CSS. Here’s how to integrate SCSS into your AEM components.

1. Set Up Your Environment

  1. Install the VS Code AEM Sync extension for easy code management.

  2. Import your component from the AEM server:
    - Right-click the parent folder in VS Code.
    - Select "Import from Server".

  3. Install Sass globally using the following command:

    bash : npm install -g sass

2. Create and Compile SCSS

  1. Navigate to the css folder of your component.

  2. Create a new file named style.scss.

  3. Write your SCSS code and compile it to CSS with the following command:


    command : sass style.scss style.css
  4. The SCSS code will be converted to a style.css file, which is already linked to the component via clientlibs.

3. Export to AEM

After making changes, export the component back to AEM:

  1. Right-click your component in VS Code and select "Export to Server".
  2. Refresh the AEM page to see the updated styles.



Common Issues and Troubleshooting

Why Are My Clientlibs Not Loading?

  • Ensure that the allowProxy property is set to true.
  • Check that the categories name matches in both the clientlibs folder and your .html file.

How Can I Debug SCSS?

  • Use browser developer tools to inspect styles and ensure your compiled CSS is properly linked in css.txt.


Conclusion

This comprehensive guide covers everything you need to know about adding clientlibs to specific AEM components and integrating SCSS. By following these steps, you can build scalable, modular, and visually appealing components with ease.

If you found this guide helpful, don’t forget to share it with your peers. For more AEM tutorials and tips, bookmark this blog and stay updated!

Wednesday, December 25, 2024

Git Operations: A Comprehensive Guide | github

 

Git Operations: A Comprehensive Guide

Git is an essential tool for version control, widely used by developers. In this guide, we'll walk through common Git operations that every developer should know. Bookmark this page as we’ll continue adding more operations in the future.


Combine All Pushed Commits into One Method 1

To clean up your commit history and combine multiple commits into a single one, follow these steps:


1. Count the total commits on the live branch

command: git log 
description: this will show all the commits on git you just need to count where is your branch name

2. Rebase the last X commits:

command: git rebase -i HEAD~6

description: instead of 6 you need to write a number of commits that you found in step 1

3. Edit the commits A terminal console will appear with all the commits labeled "pick."

  • Press i to enter insert mode.
  • Replace the word pick with squash for all but not for the first commit.
  • 4. Save and exit:

    Press Esc, then type :wq and hit enter.

    5. Push the changes:

    git push origin your-branch-name --force 

    Combine All Pushed Commits into One Method.2(Recomanded)

    command: git log 
    description: this will show all the commits on git you just need to count where is your branch name

    • git reset --soft head~(number of commits)
    • git stash
    • git checkout master and delete your old branch
    • git pull in master
    • git checkout -b branch with same name that we deleted
    • git stash apply (then solve conflict if any)
    • git push with --force

    How to Fetch a Remote Branch to Local

    If you need to fetch a remote branch and work on it locally, follow these steps:

    Step No 01: Fetch the branch: 

    git fetch origin
    Step No 02: Check out the branch:
    git checkout branch-name-that-you-need-to-checkout
     

    How to Rename a Branch Locally

    Sometimes you might want to rename a local branch.Here's how you can do it:

    Step No 01: Checkout the branch you want to rename
    git checkout branch-name
    Step No 02: Rename the branch git branch -m new-branch-name
    Step No 03: Delete the old branch from the remote git push origin --delete old-branch-name
    Step No 04: Push the renamed branch to the remote git push origin new-branch-name
    Step No 05: Set the upstream for the new branch git push --set-upstream origin new-branch-name

    Tuesday, December 24, 2024

    Comparing AEM as Cloud Service and AEM 6.5 | AEM 6.5 vs. AEM as a Cloud Service

     AEM 6.5 vs. AEM as a Cloud Service: What You Need to Know

    When it comes to enterprise content management, Adobe Experience Manager (AEM) is a leading solution. However, businesses often face a crucial decision: Should they choose AEM 6.5 or AEM as a Cloud Service? This guide provides a clear comparison to help you make an informed choice, focusing on features, benefits, and use cases for both.





    What is AEM 6.5?

    AEM 6.5 is the traditional on-premises version of Adobe Experience Manager. It allows businesses to deploy and manage their content management system (CMS) in a private or hybrid cloud environment.

    Key Features:

    • Full control over infrastructure and deployment.
    • Customizable architecture tailored to specific business needs.
    • Extensive support for integrations with legacy systems.

    Ideal For: Organizations that need strict standards or prefer on-premises infrastructure for more control.


    What is AEM as a Cloud Service?

    AEM as a Cloud Service is Adobe’s fully managed, cloud-native CMS. It offers continuous updates and scalability without the need for manual upgrades or maintenance.

    Key Features:

    • Fully managed by Adobe with automatic updates.
    • Built-in scalability and high availability.
    • Faster time-to-market with modern cloud infrastructure.

    Ideal For: Businesses looking for a scalable, low-maintenance CMS with access to the latest features.


    Key Differences Between AEM 6.5 and AEM as a Cloud Service



    Benefits of AEM 6.5

    1. Complete Control: You have full control over infrastructure and security.
    2. Custom Integrations: Ideal for businesses with unique integration needs.
    3. Requirement-ready: Meets strict data privacy and regulatory requirements.

    Challenges:

    • Requires significant IT resources for management.
    • Manual upgrades can be time-consuming and costly.


    Benefits of AEM as a Cloud Service

    1. Continuous Innovation: Always up-to-date with Adobe’s latest features and improvements.
    2. Scalability: Automatically adjusts to handle spikes in traffic.
    3. Lower Maintenance: No need for manual upgrades or server management.

    Challenges:

    • Limited flexibility for highly customized use cases.
    • Relies on Adobe’s infrastructure, which may not meet specific compliance requirements.



    When to Choose AEM 6.5

    • Your business requires full control over infrastructure and data.
    • You need deep customization for complex workflows.
    • Meeting strict rules is a top priority.

    When to Choose AEM as a Cloud Service

    • Your focus is on scalability and faster time-to-market.
    • You want a low-maintenance CMS with continuous updates.
    • Your team prefers a subscription-based pricing model with predictable costs.

    Conclusion

    Choosing between AEM 6.5 and AEM as a Cloud Service depends on your business needs. If you require complete control and customization, AEM 6.5 is the right choice. However, if you prioritize scalability, reduced maintenance, and access to the latest features, AEM as a Cloud Service is the way forward. Both options are powerful solutions—the decision lies in your organization’s goals and resources.



    Download and install AEM Guides for the first time | AEM Development Environment

     Setting Up an AEM Development Environment: A Quick Tutorial

    Are you ready to dive into Adobe Experience Manager (AEM) development but unsure where to start? Setting up your development environment correctly is the first step to building powerful and scalable content management solutions. In this guide, we will walk you through the essential steps to set up an AEM development environment, with tips to ensure a smooth process.Download and install AEM Guides for the first time



    Why AEM?

    AEM is a leading content management system used by enterprises worldwide for its scalability, flexibility, and integration capabilities. Whether you’re creating multilingual websites or managing digital assets, AEM provides robust tools to meet your needs.


    Step 1: Check System Requirements

    Before installing AEM, ensure your system meets the following requirements:

    • Java Development Kit (JDK): AEM requires Java 8 or 11 (depending on the version you’re using).
    • Memory: At least 8 GB of RAM is recommended.
    • Disk Space: Minimum of 10 GB of free space for the AEM installation.
    • Operating System: Compatible with Windows, macOS, or Linux.

    Tip: Use Adobe’s official documentation to verify the compatibility of your system.




    Step 2: Install Java

    AEM requires a compatible JDK to run. Follow these steps:

    1. Download Java from Oracle’s official website.

    2. Install the JDK and set the JAVA_HOME environment variable.

    Command to verify Java installation: 

    java --version



    Step 3: Install Apache Maven

    AEM requires Apache Maven. Follow these steps:

    1. Download Maven from the Apache Site.

    2. There is no need to install Maven. Simply extract the Maven folder, move the extracted folder to the Program Files directory on your Windows drive, and configure the environment variables.

    Command to verify mvn installation: 

    mvn --version


     

    Step 3: Download AEM

    1. Log in to the Adobe Software Distribution portal with your Adobe ID.

    2. Download the required version of the AEM jar file (e.g., aem-author-p4502.jar).

    3. Obtain the license.properties file provided by Adobe.


    Step 4: Run the AEM Jar File

    1. Place the aem-author-p4502.jar file and the license.properties file in the same folder.keep the same name of jar file as written here,

    2. Note: If you rename the file to something like aem-author-p4502.jar, it will run as an Author instance. Similarly, renaming the file to aem-publish-p4503.jar will make it run as a Publish instance.

    3. Open the terminal or command prompt and navigate to the folder.

    4. Run the following command:

    java -jar aem-author-p4502.jar

     



    Step 5: Access AEM

    Once installed, AEM runs on localhost:4502 by default.

    • Open a browser and navigate to http://localhost:4502.
    • Log in using the default credentials:
    • Username: admin
    • Password: admin

    Optional: Change the default password immediately to secure your instance.



    Troubleshooting Tips (optional)

    • AEM doesn’t start? Check your JAVA_HOME and ensure Java is correctly installed.
    • Memory issues? Increase the heap size by editing the startup parameters:

    java -Xmx4096m -jar aem-author-p4502.jar
    • Login problems? Reset the admin password via the repository.


    Conclusion

    Setting up an AEM development environment may seem complex, but following these steps will get you up and running quickly. AEM offers immense flexibility for building enterprise-level solutions, and with the right tools and practices, you’ll be ready to create powerful applications in no time.



    Feel free to leave a comment if you need any further assistance.

    Top 10 AEM Best Practices for Developers | adobe AEM
     Adobe Experience Manager (AEM) is a powerful platform for building enterprise-level websites and managing content. To get the most out of AEM, developers need to follow best practices that ensure high performance, scalability, and maintainability. Here are the top 10 AEM best practices every developer should know.








    Top 10 AEM Best Practices for Developers



    1. Plan Your Component Development

    Before you start coding, define the purpose and scope of each component. Create a consistent naming convention and ensure reusability to avoid duplication


    2. Use Editable Templates

    Leverage AEM’s editable templates to empower authors to create content with flexibility. Avoid static templates unless there is a compelling reason.


    3. Follow HTL (Sightly) Standards

    HTL (HTML Template Language) is the recommended scripting language in AEM. It ensures clean and secure code, separating logic from markup. Avoid using JSP for new projects.


    4. Optimize Dispatcher Configuration

    The dispatcher acts as a caching and load balancing tool. Properly configure it to cache static assets and reduce server load. Test your configuration to avoid caching issues.


    5. Implement Version Control

    Use Git or another version control system to track changes and collaborate with your team effectively. Follow branching strategies like GitFlow for organized development.


    6. Adopt Component-Based Development

    Break down your UI into small, reusable components. This approach improves maintainability and ensures consistency across pages.


    7. Test Your Code Thoroughly

    Use testing tools like JUnit for backend logic and Jest or Cypress for front-end testing. Regularly test your AEM workflows and dispatcher configurations.


    8. Optimize DAM Asset Management

    Organize Digital Asset Management (DAM) assets in a clear folder structure. Use metadata schemas for efficient search and retrieval. Compress large images to improve page load times.


    9. Enable Caching and Lazy Loading

    Use caching mechanisms to enhance performance. Implement lazy loading for images and videos to improve initial page load times.


    10. Keep Up with Security Best Practices

    Protect your AEM environment by implementing SSL, user access controls, and regularly updating to the latest AEM version. Follow Adobe’s security guidelines to safeguard your content.


    Conclusion

    By following these best practices, AEM developers can deliver high-quality, scalable, and secure websites. Whether you’re building new components or optimizing existing workflows, these tips will help you maximize AEM’s potential.

    If you found this article helpful, share it with your network or leave a comment below. Stay tuned for more AEM tips and insights!

    Monday, December 23, 2024

    Mastering Sling Models and Resource Resolvers in Adobe AEM: A Complete Guide

     In this article, we will learn about the Complete Flow of Resource Resolvers that we use in the Sling Model.



    What is ResourceResolver in AEM Sling Model?


    In AEM, ResourceResolver is an interface that provides access to resources in the JCR (Java Content Repository). It is part of the Sling API and serves as a bridge between your code and the JCR repository, allowing you to read, update, or manipulate resources (e.g., pages, components, nodes).



    Resource Resolver Flow



    Here's a rephrased and more understandable version:
    • The AEM instance starts running.
    • Once the AEM instance is running, the Resource Resolver Factory executes and provides all possible Resource Resolvers. There can be one or multiple Resource Resolvers.
    • In our Sling Model, the Resource used in the @Model adaptable annotation comes from the Resource Resolver provided by the Resource Resolver Factory.
    • Using this Resource, we can access the getResourceResolver() function.
    • Through this function, we obtain the QueryBuilder and Session objects.






    • Predicates are the parameter that we get form Query Builder AEM instance to pass in QueryBuilder in Code.





    Sling Model and its Annotations Explained

    In AEM, Sling Models are a framework that allows developers to map Java objects to resources in the JCR (Java Content Repository). They simplify data access and manipulation in AEM components.

    Key Annotations in Sling Models:

    @Model:
    This annotation defines a class as a Sling Model.
    It specifies the adaptables
    (the source object types the model can work with, such as SlingHttpServletRequest or Resource)

    .Adaptables:
    The adaptables attribute in the @Model annotation specifies what the Sling Model can adapt to:

    SlingHttpServletRequest.class: Used when you want to adapt HTTP requests, often to access page-related objects like currentPage.
    example
    @Model(adaptables = SlingHttpServletRequest.class) public class MyModel { // Model logic here }
    Resource.class: Used when you want to work with JCR nodes directly.
    @Model(adaptables = Resource.class) public class MyModel { // Model logic here }


    full code example



    import com.adobe.cq.sightly.WCMUsePojo;
    import com.day.cq.wcm.api.Page;
    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.ScriptVariable;
    import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;

    @Model(adaptables = SlingHttpServletRequest.class)
    public class ExampleModel {

    // Injecting the current page object , for this we need to use Resource in adbaptables
    @ScriptVariable
    private Page currentPage;

    // ValueMapValue Injecting a non-page property (e.g., fname) for this we need to use SlingHttpServletRequest
    @ValueMapValue
    private String fname;

    // Injecting a property directly using @ValueMapValue
    @ValueMapValue
    private String sname;

    // Injecting ResourceResolver to access JCR
    @SlingOnject
    private ResourceResolver resourceResolver;

    // Fetching a resource using ResourceResolver
    public String getCustomProperty() {
    String customProperty = "Not found";

    // Using resourceResolver to fetch a resource
    Resource resource = resourceResolver.getResource("/content/mywebsite/home");
    if (resource != null) {
    // Fetching the property from the resource
    customProperty = resource.getValueMap().get("customProperty", String.class);
    }
    return customProperty;
    }

    // Getter methods for the properties
    public String getCurrentPageTitle() {
    return currentPage.getTitle();
    }

    public String getFname() {
    return fname;
    }

    public String getSname() {
    return sname;
    }
    }






    Some other UseFull annotation of Sling Modal

    1. What is @RequestAttribute

    The @RequestAttribute annotation is used in Sling Models to inject a variable or value that is passed from Sightly (HTL) into the Sling Model. It provides a simple way to pass data dynamically from the front end to the back end.


    Sightly Code
    <section
    class="gv4-container w-full"
    data-sly-use.obj="eand.com.money.core.models.GiftPlayZone @ variableName='TestAttribute'"
    >
    <!-- Example: Output the value -->
    <p>${obj.reqVariable}</p>
    </section>

    Here, variableName='TestAttribute' passes the value "TestAttribute" as an attribute to the Sling Model.

    Sling modal code

    @RequestAttribute(name = "variableName")
    private String reqVariable;

    public String getReqVariable() {
    return reqVariable;
    }
    • @RequestAttribute injects the variableName value from Sightly into the reqVariable field in the Sling Model.




    2. @PostConstruct

    The @PostConstruct annotation marks a method to be executed after all injections (like @Inject, @ValueMapValue, @ScriptVariable) are completed. It is primarily used for initialization logic in the Sling Model.

    Use Case:

    • When you need to process or prepare data after dependencies have been injected into the model.
    @PostConstruct
    protected void init() {
    // Logic to initialize or process after all injections are done
    if (reqVariable != null) {
    reqVariable = reqVariable.toUpperCase();
    }
    }


    Key Notes:

    • This method is executed automatically after the object has been fully initialized.
    • Use it for data manipulation, validation, or additional setup.

    3. @OSGiService

    The @OSGiService annotation is used to inject OSGi services (either default or custom) into the Sling Model. These services are managed by the OSGi container and provide reusable business logic or utilities.

    Use Case:

    • When you need to call a default or custom OSGi service in your model for additional logic or processing.
    @OSGiService
    private MyCustomService myService;

    public String getServiceResult() {
    return myService.processData(); // Call a method from the OSGi service
    }









    Sling Model for multifield-like faqs with GraphQL and OSGI Service in AEM


    • modal class

    package eand.com.money.core.models;

    import eand.com.money.core.services.BaseUrlOsgiConfig;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.sling.api.SlingHttpServletRequest;
    import org.apache.sling.models.annotations.Model;
    import org.apache.sling.models.annotations.injectorspecific.OSGiService;
    import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;
    import org.apache.sling.models.annotations.DefaultInjectionStrategy;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import javax.annotation.Resource;
    import org.apache.http.HttpResponse;
    import org.apache.http.util.EntityUtils;
    import eand.com.money.core.utilities.ApisConstant;
    import eand.com.money.core.utilities.GQueries;
    import eand.com.money.core.Beans.FaqsBean;
    import com.google.gson.JsonArray;
    import com.google.gson.JsonObject;
    import com.google.gson.JsonParser;

    @Model(adaptables = { SlingHttpServletRequest.class, Resource.class },
    defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
    public class Faqs {

    @OSGiService
    private BaseUrlOsgiConfig config;

    public String getBaseURL() {
    assert config != null;
    return config.getBaseUrl();
    }
    @ValueMapValue
    private boolean rtl; // Remove 'static' so AEM can inject the value

    public String fetchFaqsCF() {
    try {
    CloseableHttpClient httpClient = HttpClients.createDefault();
    // String fullPath = "http://localhost:4502/" + ApisConstant.EMONEY_GRAPHQL;
    String fullPath = getBaseURL() + ApisConstant.EMONEY_GRAPHQL;
    HttpPost httpPost = new HttpPost(fullPath);

    // Set request headers
    httpPost.setHeader("Authorization", "Basic YWRtaW46YWRtaW4=");
    httpPost.setHeader("Content-Type", "application/json");
    httpPost.setHeader("Cookie", "cq-authoring-mode=TOUCH");

    // Set request body
    String requestBody;
    if (rtl) {
    requestBody = GQueries.FaqsArabic; // Arabic query if RTL is true
    } else {
    requestBody = GQueries.FaqsEnglish; // English query if RTL is false
    }

    httpPost.setEntity(new StringEntity(requestBody));
    HttpResponse response = httpClient.execute(httpPost);

    if (response.getStatusLine().getStatusCode() == 200) {
    String responseData = EntityUtils.toString(response.getEntity());
    return responseData;
    } else {
    String errorMessage = "Error: " + response.getStatusLine().getStatusCode() + " "
    + response.getStatusLine().getReasonPhrase();
    return errorMessage;
    }
    } catch (Exception e) {
    return "";
    }
    }

    public List<FaqsBean> getFaqs() {
    List<FaqsBean> FaqsList = new ArrayList<>();
    String jsonString = fetchFaqsCF();

    // Parsing the JSON string
    JsonParser parser = new JsonParser();
    JsonObject jsonObject = parser.parse(jsonString).getAsJsonObject();

    // Accessing data
    JsonObject data = jsonObject.getAsJsonObject("data");
    JsonObject emoneyFaqsList = data.getAsJsonObject("faqsList");
    JsonArray items = emoneyFaqsList.getAsJsonArray("items");

    if (items != null) {
    for (int i = 0; i < items.size(); i++) {
    JsonObject item = items.get(i).getAsJsonObject();
    FaqsBean faqsList = new FaqsBean();
    faqsList.setQuestion(item.get("question").getAsString());
    faqsList.setAnswer(item.get("answer").getAsJsonObject().get("html").getAsString());
    faqsList.setTutorial(item.get("tutorial").getAsString());
    FaqsList.add(faqsList);
    }
    }

    Collections.reverse(FaqsList);
    return FaqsList;
    }

    // public static void main(String[] args) {
    // // Create a dummy Faqs object to simulate injection
    // Faqs faqs = new Faqs();
    // faqs.rtl = true; // Simulate AEM setting for testing

    // for (FaqsBean faqsList : faqs.getFaqs()) {
    // System.out.println("Tutorial: " + faqsList.getTutorial());
    // }
    // }
    }



    • OSGI Configuration
    package eand.com.money.core.services.Impl;
    import org.osgi.service.metatype.annotations.*;
    import eand.com.money.core.services.BaseUrlOsgiConfig;
    import org.osgi.service.component.annotations.Activate;
    import org.osgi.service.component.annotations.Component;

    @Component(service = BaseUrlOsgiConfig.class,immediate = true)
    @Designate(ocd = BaseUrlOsgiConfigImpl.ServiceConfig.class )
    public class BaseUrlOsgiConfigImpl implements BaseUrlOsgiConfig{

    @ObjectClassDefinition(name="Emoney Base URL Configuration",
    description = "Emoney Base URL Configuration")
    public @interface ServiceConfig {

    @AttributeDefinition(
    name = "Base URL",
    description = "Enter files Path Ex: 'http://localhost:4502/'",
    type = AttributeType.STRING)
    public String baseURL() default "";
    }

    private String baseURL;

    @Activate
    protected void activate(ServiceConfig serviceConfig){
    baseURL=serviceConfig.baseURL();
    }

    @Override
    public String getBaseUrl() {
    return baseURL;
    }
    }

    • Gquery.java

    package eand.com.money.core.utilities;

    public class GQueries {
    public static final String AppsLink = "{\"query\":\"{\\n" + "appsLinkList(\\n" + "variation: \\\"en\\\"\\n"
    + " )\\n" + " {\\n" + "items {\\n" + "icon\\n" + "link\\n" + "}\\n" + "}\\n" + "}\\n"
    + "\",\"variables\":{}}";
    public static final String FaqsEnglish = "{\"query\":\"{\\n" +"faqsList(\\n" + "variation: \\\"en\\\"\\n"+")\\n"+"{\\n"+"items{\\n"+"question\\n"+"answer{\\n"+"html\\n"+"}\\n"+"tutorial\\n"+"}\\n"+"}\\n"+"}\\n"+"\",\"variables\":{}}";

    public static final String FaqsArabic = "{\"query\":\"{\\n" + //
    " faqsList(\\n" + //
    " variation: \\\"ar\\\"\\n" + //
    " )\\n" + //
    " {\\n" + //
    " items {\\n" + //
    " question\\n" + //
    " answer {\\n" + //
    " html\\n" + //
    " }\\n" + //
    " tutorial\\n" + //
    " }\\n" + //
    " }\\n" + //
    "}\\n" + //
    " \",\"variables\":{}}";
    }



    • ApiConstan.java
    package eand.com.money.core.utilities;

    public class ApisConstant {

    public static final String EMONEY_GRAPHQL = "/content/cq:graphql/emoney/endpoint.json";
    }



    Key Points for Managing Multifields in AEM Sling Models:

    1. Using a Map: Best suited when all fields in the multifield are of the same type, such as String or Boolean.
    2. Using a Bean: Ideal when fields in the multifield have different types, allowing for better structure and type safety.